Sandbox
Isolated execution environments where agent tools run. Three built-in bindings — vercel, local, docker — with setup, snapshots, and full API.
Built-in tools like Read, Write, Bash, and JavaScript execute inside the sandbox. The agent can read files, run commands, and start dev servers without affecting your production system.
Sandbox Types
experimental-agent ships three sandbox bindings. Each has different isolation guarantees and deployment targets.
vercelSandbox() — Vercel Sandbox
Full Node.js and Python runtime, filesystem, and network. The production default when running on Vercel.
import { agent } from "experimental-agent";
import { vercelSandbox } from "experimental-agent/sandbox";
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
sandbox: vercelSandbox(),
});Use vercelSandbox() for production deployments. The sandbox runs in a Vercel Sandbox with configurable vCPUs, exposed ports, and network policies.
localSandbox() — Host filesystem
Runs on your machine's filesystem. Great for development — no cloud setup required.
import { agent } from "experimental-agent";
import { localSandbox } from "experimental-agent/sandbox";
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
sandbox: localSandbox(),
});Tools execute directly on the host. Use for fast iteration during development.
dockerSandbox() — Docker container
Runs inside a Docker container. Provides isolation without cloud dependencies.
import { agent } from "experimental-agent";
import { dockerSandbox } from "experimental-agent/sandbox";
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
sandbox: dockerSandbox(),
});Requires Docker Desktop with Docker Sandboxes enabled.
Auto-detection
When no sandbox binding is provided, the SDK auto-detects:
- Vercel — if
VERCEL_OIDC_TOKENis set - Docker — if the
docker sandboxCLI is available - Local — fallback
Sandbox Setup
Inline defaults (recommended)
Pass version, run, config, and networkPolicy directly to the binding factory. The sandbox is automatically set up when the session starts — no separate .setup() call needed:
import { agent } from "experimental-agent";
import { vercelSandbox } from "experimental-agent/sandbox";
export const myAgent = agent("my-agent", {
model: "anthropic/claude-opus-4.6",
sandbox: vercelSandbox({
version: "my-env-v1",
run: async (sandbox) => {
await sandbox.exec({ command: "npm", args: ["install"] });
},
}),
});Explicit setup
You can also call sandbox.setup() on a sandbox handle for more control:
const sb = myAgent.sandbox("my-sandbox");
const { done } = await sb.setup({
version: "my-env-v1",
run: async (sandbox) => {
await sandbox.exec({ command: "npm", args: ["install"] });
},
});
await done;Options passed to .setup() override any defaults set on the binding factory.
version + run
One-time initialization. run executes when the sandbox is first created (cold start, no snapshot). After it completes, the sandbox is snapshotted for fast resume.
version— Bump this string to invalidate the snapshot and re-run setup (e.g."my-env-v2"after adding new dependencies).run— Async function that receives the sandbox instance. Install deps, clone repos, or configure the environment.
Binding-specific config
Pass type and config to select a binding and configure it:
await sb.setup({
type: "vercel",
version: "v1",
config: {
ports: [3000],
resources: { vcpus: 4 },
},
run: async (sandbox) => {
await sandbox.exec({ command: "npm", args: ["install"] });
},
});Sandbox API
Inside setup.run or custom tools (via ToolContext), you get a sandbox instance with:
| Method | Description |
|---|---|
exec({ command, args?, cwd?, env?, sudo?, signal? }) | Run a shell command. Returns ExecResult with stdout, stderr, exit code, and logs() stream. |
readFile({ path, signal? }) | Read file contents. Returns Buffer | null. |
writeFiles({ files, destPath, signal? }) | Write multiple files to a destination path. Creates parent directories. |
getDomain({ port, signal? }) | Get the public domain URL for an exposed port. |
kill({ commandId, signal? }) | Kill a running command by ID. |
updateNetworkPolicy({ policy, signal? }) | Update network policy at runtime (Vercel sandboxes only). |
Example:
await sandbox.exec({ command: "npm", args: ["install", "lodash"] });
const buf = await sandbox.readFile({ path: "/app/package.json" });
await sandbox.writeFiles({
files: [{ path: "config.json", content: "{}" }],
destPath: "/app",
});Lifecycle Methods
Sandbox instances expose lifecycle methods directly on the instance:
| Method | Returns | Description |
|---|---|---|
start() | Promise<void> | Start the sandbox. |
stop() | Promise<void> | Stop the sandbox. |
snapshot() | Promise<{ snapshotId: string }> | Create a snapshot for fast resume. |
getStatus() | Promise<SandboxStatus> | Returns pending, running, stopping, stopped, or failed. |
const status = await sandbox.getStatus();
if (status === "running") {
await sandbox.snapshot();
}Next Steps
- Sandbox Bindings — Full binding reference and SandboxInstance API
- Sandbox Setup — Setup and snapshot patterns
- Tools — Built-in tools that run in the sandbox
- Storage — Where sandbox records and commands are persisted
- Architecture Overview — How it all works