Claude Agent SDK Inside the Sandbox, or the Sandbox as a Tool?
Updated October 27, 2026 .md
Short answer: Run the agent inside the sandbox when its built-in Bash and file tools should only ever touch a disposable VM and it works for long stretches alone. Keep the agent on your server and give it Sandboxer as an MCP tool when your keys and app state must stay with you and only code execution needs isolating.
Why the choice matters#
The Claude Agent SDK is a library that runs the Claude Code binary inside your program. Anthropic's hosting guide explains that each query() starts a claude subprocess that "owns the shell, the working directory, and the JSONL session transcripts on local disk." Its built-in tools (Bash, Read, Edit, Write) act on whatever machine that subprocess runs on.
So the real question is which machine that is:
- Setup A, agent inside the sandbox. Your program and its
claudesubprocess run in a Sandboxer VM. Every built-in tool touches only that VM. - Setup B, sandbox as a tool. Your program runs on your server. It reaches a Sandboxer VM through the MCP server, and you turn off the built-in Bash so commands don't run on your server.
The decision#
| A: agent inside the sandbox | B: agent on your server, sandbox as a tool | |
|---|---|---|
| Where the agent loop runs | In the VM | On your server |
Where ANTHROPIC_API_KEY lives |
In the VM's environment | On your server only |
| Where the Sandboxer key lives | On the machine that runs sbx (the VM gets none with --no-env) |
On your server, in the MCP config's header or env |
| What a bad command can reach | The VM: its files, its environment, its network | The VM, through MCP tools. Built-in tools you leave on still act on your server |
| Tool-call latency | Built-in tools run locally in the VM. Only model calls leave it | Each tool call is a network round trip to Sandboxer: about 90 ms per hosted MCP call in our test (below) |
| Startup | sbx new took 3.2 s in our test (October 27, 2026), plus a one-time SDK install (about 340 MB with its bundled binary) |
SDK init with both Sandboxer servers connected took 437–518 ms. The agent creates a VM (create_sandbox) when it needs one |
| Sandbox cost | The VM bills for the whole session, model time included | The VM bills from create_sandbox until stop_sandbox or its TTL |
| Session files and memory | In the VM. Stopping it keeps them; deleting it loses them | On your server, next to your app's own state |
| Best for | Long autonomous tasks, coding agents, anything you'd run with permission prompts off | Chat apps and multi-tenant services where the agent mostly talks and sometimes runs code |
Sandbox cost is small next to the model in both setups. small (2 vCPU, 4 GB) is $0.018 an hour and default (4 vCPU, 8 GB) is $0.036 an hour, billed per second. Anthropic's hosting guide notes that token cost "typically dominates container infrastructure cost by an order of magnitude or more."
Setup A: the agent runs inside the sandbox#
Create a VM. --no-env keeps your account's secrets out of it, so the agent can't act on your Sandboxer account:
sbx new --type small --no-envIn our single run on October 27, 2026, it was ready in 3.2 s. Every sandbox has Node, Python and Claude Code preinstalled:
sbx exec sb_lw7iz00qux "node --version; npm --version; python3 --version; claude --version"v22.23.3
10.9.9
Python 3.12.3
2.1.301 (Claude Code)That's above Anthropic's stated minimums (Node.js 18+ or Python 3.10+). Install the SDK in the VM and check that it imports:
sbx exec sb_lw7iz00qux --timeout 300 'mkdir -p agent && cd agent && npm init -y >/dev/null && npm pkg set type=module && npm i @anthropic-ai/claude-agent-sdk && node -e "import(\"@anthropic-ai/claude-agent-sdk\").then(m => console.log(typeof m.query, typeof m.tool, typeof m.createSdkMcpServer))"'added 105 packages, and audited 106 packages in 10s
…
found 0 vulnerabilities
function function functionquery, tool and createSdkMcpServer all imported (package version 0.3.311). For Python, use a virtual environment:
sbx exec sb_lw7iz00qux --timeout 300 'cd agent && python3 -m venv .venv && .venv/bin/pip install -q claude-agent-sdk && .venv/bin/python -c "import claude_agent_sdk as s; print(s.__version__, s.query.__name__, s.ClaudeAgentOptions.__name__)"'0.2.174 query ClaudeAgentOptionsBoth SDKs bundle their own Claude Code binary, per Anthropic's quickstart. That's why the installs are large: node_modules was 342 MB and the venv 338 MB. Install once, then save the VM as a template so later VMs start with it. See Turn a sandbox into a reusable template.
Here is a small agent that uses the built-in tools, which now act only on the VM:
// agent.mjs
import { query } from "@anthropic-ai/claude-agent-sdk";
const prompt = process.argv[2] ?? "Run the tests in this repo and fix what fails.";
for await (const message of query({
prompt,
options: {
cwd: "/home/user/agent",
allowedTools: ["Bash", "Read", "Edit", "Write", "Glob", "Grep"],
permissionMode: "acceptEdits",
maxTurns: 30,
},
})) {
if (message.type === "system" && message.subtype === "init") {
console.log("init: model", message.model, "tools", message.tools.length);
} else if (message.type === "result") {
console.log("result:", message.subtype, message.result ?? "");
}
}Copy it in and start it in the background, so it keeps running after your terminal closes:
sbx scp ./agent.mjs sb_lw7iz00qux:/home/user/agent/
sbx exec sb_lw7iz00qux --detach --cwd agent 'node agent.mjs "Say hello"'{"ok":true,"type":"command.started","command":"node agent.mjs \"Say hello\"","commandId":"cmd_3xaqnt6wzzqb",…,"processId":630,…}Read its output any time, even after the sandbox stops:
sbx history sb_lw7iz00qux cmd_3xaqnt6wzzqbinit: model claude-opus-5-5 tools 25
result: success Not logged in · Please run /loginWe ran this with no Anthropic key in the VM, so the agent started, loaded its 25 built-in tools and stopped at sign-in. No model call ran. To run it for real, give the VM your key. Keys saved on the dashboard's Agents page never reach a --no-env sandbox, so pass it to that one sandbox with sbx new --no-env -e ANTHROPIC_API_KEY=…. Anthropic's quickstart says the SDK reads the key from the environment and doesn't load .env files.
If you don't need your own program at all, the integrated agents run Claude Code in the VM from one sbx prompt call or API request.
Setup B: the agent runs on your server and calls the sandbox#
Point the SDK's mcpServers option at Sandboxer. Anthropic's MCP guide uses type: "http" with headers for remote servers and command/args/env for stdio servers. This config sets up both Sandboxer servers, the hosted one and the local sbx mcp. In practice you'd pick one:
// agent.mjs, on your server
import { query } from "@anthropic-ai/claude-agent-sdk";
const q = query({
prompt: "List my sandboxes.",
options: {
mcpServers: {
sandboxer: {
type: "http",
url: "https://sandboxer.com/mcp",
headers: { Authorization: `Bearer ${process.env.SANDBOXER_API_KEY}` },
},
"sandboxer-local": {
type: "stdio",
command: "sbx",
args: ["mcp", "--type", "small", "--ttl", "1800"],
env: { SANDBOXER_API_KEY: process.env.SANDBOXER_API_KEY },
},
},
allowedTools: ["mcp__sandboxer__*", "mcp__sandboxer-local__*"],
disallowedTools: ["Bash"],
maxTurns: 1,
},
});
try {
for await (const message of q) {
if (message.type === "system" && message.subtype === "init") {
console.log("servers:", message.mcp_servers);
const tools = message.tools.filter((t) => t.startsWith("mcp__"));
console.log(`${tools.length} MCP tools, e.g.`, tools.slice(0, 3));
} else if (message.type === "result") {
console.log("result:", message.subtype, message.result ?? "");
}
}
} catch (err) {
console.log("ended:", String(err).split("\n")[0]);
}node agent.mjsservers: [
{ name: 'sandboxer', status: 'connected', source: 'dynamic' },
{ name: 'sandboxer-local', status: 'connected', source: 'dynamic' }
]
37 MCP tools, e.g. [
'mcp__sandboxer__command_status',
'mcp__sandboxer__create_sandbox',
'mcp__sandboxer__delete_sandbox'
]
result: success Not logged in · Please run /login
ended: Error: Claude Code returned an error result: Not logged in · Please run /loginBoth servers connected: 18 tools from the hosted server and 19 from sbx mcp, which adds handoff_session. As in Setup A, there was no Anthropic key, so the run stopped at sign-in, before any model call. Over three runs, the init message arrived 437–518 ms after query() started.
Notes on this config:
- Use a key, not browser sign-in. Anthropic's MCP guide says the SDK "doesn't open a browser or run an interactive OAuth flow," so send a Sandboxer API key in
headers. A scoped key limits what the agent can do. - Turn off the built-in tools you don't want on your server.
disallowedTools: ["Bash"]stops shell commands from running on your server. AddWriteandEditif the agent shouldn't change files there either. allowedToolswithmcp__sandboxer__*lets the agent call every Sandboxer tool without a prompt. Tool names follow Anthropic'smcp__<server>__<tool>pattern. List single tools instead, such asmcp__sandboxer__exec, to allow less.- Cap what the agent creates.
sbx mcp --type small --ttl 1800makes every sandbox the agent createssmall, stopping after 30 minutes unless the agent passes its own values.
Check the Sandboxer side yourself#
You can call the hosted server without the SDK. The key goes in through stdin, so it never shows up in your shell history or process list:
printf 'Authorization: Bearer %s\n' "$SANDBOXER_API_KEY" | curl -sS -D headers.txt -H @- \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"0"}}}' \
https://sandboxer.com/mcp{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"tools":{"listChanged":false}},"instructions":"Tools for Sandboxer cloud sandboxes: Ubuntu microVMs with root, Docker and a public HTTPS URL per port.\n…","protocolVersion":"2025-06-18","serverInfo":{"name":"sandboxer","title":"Sandboxer",…}}}The response carries an mcp-session-id header. Send it back as Mcp-Session-Id with notifications/initialized (HTTP 202), then tools/list. That returned 18 tools, from create_sandbox to delete_snapshot, in 116 ms. Each initialize took 89–91 ms and each list_sandboxes call took 91 ms.
The stdio server answers the same handshake on stdin:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | sbx mcp --type small --ttl 1800It returned serverInfo sandboxer and 19 tools.
Mixing the two#
The setups combine well. A server-side agent (B) can create a sandbox, copy a second Agent SDK program into it and start that with exec and detached: true. That inner agent (A) then works on its own with the Anthropic key you gave that VM. Your orchestrator holds the Sandboxer key, and each worker VM holds only the Anthropic key it needs. To run several workers side by side, see Run coding agents in parallel.
FAQ#
Does the Claude Agent SDK need Claude Code installed in the sandbox?#
No. Anthropic's quickstart says both SDKs bundle a native Claude Code binary for most installs. Sandboxer VMs also have claude preinstalled (2.1.301 in our test), which is handy for claude -p or an interactive session over SSH.
Can I use my Claude subscription with an Agent SDK agent?#
Anthropic's docs say third-party developers can't offer claude.ai login or rate limits in products built on the Agent SDK unless Anthropic has approved it. Use an API key, or Bedrock, Vertex or Foundry credentials as Anthropic's quickstart describes.
Which setup is faster?#
For tool-heavy tasks, Setup A. Each Bash or file call runs inside the VM, while in Setup B every tool call is a network round trip (about 90 ms per hosted MCP call in our test). Model calls cost the same in both, and they usually take far longer than either.
Is it safe to run the agent with permission prompts off?#
In Setup A, the agent can only reach what's in that VM, so start it with --no-env and only the keys the task needs. See Claude Code without permission prompts.
Do I need the CLI on my server for Setup B?#
No. The hosted server at https://sandboxer.com/mcp needs only an API key in headers. Use sbx mcp if you want its --type and --ttl defaults or its handoff_session tool. See Local or hosted MCP.
Related#
More guides
For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.
For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.
The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.
If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.