Mastra
Native sandbox provider for Mastra Workspaces.
@inis-run/mastra is a native sandbox provider for Mastra Workspace — it implements the WorkspaceSandbox contract from @mastra/core/workspace, backed by a real, isolated inis.run session instead of a local process.
Beta. Verified against @mastra/core==1.55.0.
Install
npm install @inis-run/mastra @mastra/core @inis-run/sdkQuickstart: attached (recommended)
One inis.run session for a whole conversation, owned by your app:
import { Client } from "@inis-run/sdk";
import { Workspace } from "@mastra/core/workspace";
import { InisSandbox } from "@inis-run/mastra";
const client = new Client();
const session = await client.sessions.create({ egress: { mode: "deny" } });
const workspace = new Workspace({ sandbox: new InisSandbox({ session }) });
try {
const result = await workspace.sandbox?.executeCommand?.("ls /workspace");
} finally {
await session.destroy(); // this app owns the session; InisSandbox never will
}InisSandbox never destroys, pauses, or resumes a session passed this way. Reattach later with the session ID:
const sandbox = new InisSandbox({ session: existingSessionId, client });Owned: the sandbox manages its own session
const workspace = new Workspace({
sandbox: new InisSandbox({ egressDefault: "deny", size: "medium" }),
});
await workspace.sandbox?.executeCommand?.("ls /workspace"); // creates the session lazily
await workspace.destroy(); // destroys itstop()/start() pause and resume the real session (VM, filesystem, and background processes freeze in place and thaw exactly where they left off) rather than recreating it. clone() builds an independent owned sibling.
Owned-mode options also accept connections — inline Connections to create alongside the session; getInfo() echoes each session's redacted connections (name, origin, state, allow rules — never the secret) under metadata.connections.
What it does
executeCommand(foreground)- Background processes:
spawn/list/get/kill - Remote cancellation (
abortSignal, timeout) — genuineSIGTERM→SIGKILLserver-side - Output streaming (
onStdout/onStderr) — a live log follow, not polling - Bulk file write (
writeFiles) - Exposed ports (
networking.getPortUrl), viasession.expose() sessionaccessor (pause/resume/fork/checkpoint/expose/files) — host-side only, never a model tool
Notes
ProcessHandle.sendStdin is not implemented — no stdin-write endpoint for a named background process. mount/unmount are not supported: both throw MountNotSupportedError rather than silently no-op'ing; inis.run has no FUSE-style mount primitive.
One known platform-level rough edge, not papered over by this adapter: killProcess can report true for a process that was already exiting on its own.