Table of Contents
- What a Claude Agent SDK sandbox actually contains
- Use three separate controls
- Start with an explicit Bash sandbox policy
- Choose gVisor or a full VM around the job
- Package and deploy one SDK worker
- Separate tenant state and plan for restarts
- Budget the worker separately from model usage
- Prove the boundary before scaling
Do not index
Do not index
A Claude Agent SDK sandbox is the execution environment for your SDK application, its Claude Code subprocess, and the code that subprocess runs. Agent37 can provide that environment through standard gVisor sandboxes or full VMs. Choose the runtime around your workload, then configure permissions, network access, and storage separately.
For a repository worker, the decision starts with two questions: does the job need Docker inside its environment, and what must survive between jobs? Those answers determine more of your infrastructure bill than the choice between a Python and TypeScript wrapper.
This guide covers deploying your own SDK application. For interactive CLI setup, see our Claude Code sandbox guide. Product details and prices below were checked on October 23, 2026.
What a Claude Agent SDK sandbox actually contains
Calling
query() starts a Claude Code subprocess. That process runs alongside your application, works with local files, and maintains session state. It is more demanding to host than a function that sends one model request and returns JSON. Anthropic documents this subprocess architecture.For a first deployment, put the SDK application and its subprocess inside the same isolated worker. Keep your customer-facing API, job queue, and workspace provisioning credentials outside it. Your API authenticates the customer, selects the worker, sends the task, and collects the result.
A tool call that executes elsewhere needs its own boundary. Moving a shell tool into a sandbox does not automatically isolate the application process left on your web server.
Also distinguish the Agent SDK from Claude Managed Agents. With the SDK, you host the agent loop. With Managed Agents, Anthropic hosts that loop and supports managed or self-hosted tool environments. That is a different deployment contract, described in Anthropic's environment guide.
Use three separate controls
Treat each layer as a separate decision:
Layer | What it controls | What to verify |
SDK tool permissions | Whether a proposed tool call is approved | Which tools exist, which calls are denied, and when callbacks run |
Built-in Bash sandbox | Filesystem and network access for sandboxed commands | Platform support, escape options, and allowed destinations |
Hosted execution environment | Where the worker and its processes run | Tenant separation, mounted data, resources, and lifecycle |
One common mistake is treating
allowedTools as the complete list of available tools. It pre-approves the named tools; other tools can remain available. Another is assuming canUseTool sees every call. Calls approved earlier in the permission flow can skip it. Use the documented tool configuration and deny rules, and put checks that must run for every tool call in a PreToolUse hook. See SDK permissions.The Bash sandbox has a narrower scope than the whole worker. Its network configuration does not constrain an in-process tool such as WebFetch. Likewise, a secret already available to the worker remains available inside the outer environment unless you restrict access to it.
Anthropic's secure deployment guide describes keeping credentials in an external proxy. That lets the worker request an allowed operation without receiving the underlying credential. Design the proxy's authorization around each job; merely hiding a key does not limit what an overpowered proxy can do.
Start with an explicit Bash sandbox policy
For a worker that needs shell commands, this is an illustrative
options.sandbox configuration:{
"enabled": true,
"failIfUnavailable": true,
"allowUnsandboxedCommands": false,
"excludedCommands": [],
"network": {
"allowedDomains": [],
"strictAllowlist": true
}
}It enables command sandboxing, refuses startup when the sandbox cannot initialize, and disables model-requested unsandboxed commands. On a clean worker with no inherited allow rules, it starts with no allowed command-network destinations. Add only the hosts your job needs and inspect the effective policy. Configure model API connectivity separately: this setting governs sandboxed commands, not the SDK's own model requests.
These fields and their scope are documented in the TypeScript sandbox reference. This object is a starting policy, not a complete application or a filesystem confinement policy. Review the effective filesystem rules and permissions too.
On Linux, the built-in sandbox depends on platform support and utilities such as bubblewrap and socat. Test it inside your chosen image. Nested restrictions can behave differently from those on your laptop. Do not solve a startup failure by silently allowing unsandboxed execution.
If the task needs Docker, change the outer runtime deliberately. Keep the command policy appropriate to that workload. A Docker socket gives commands extensive control over the Docker host, so passing one through is a major expansion of access.
For exact platform behavior and known limitations, use Anthropic's sandboxing documentation.
Choose gVisor or a full VM around the job
Standard Agent37 sandboxes use gVisor and shared host resources. They are a candidate for SDK workers that run ordinary commands, edit files, and spend time waiting on model or tool responses. Validate your language packages and system calls in the actual image before increasing concurrency.
Choose a full VM when the job must run a Docker daemon, Docker Compose, or workloads needing its own Linux kernel. Standard Agent37 sandboxes cannot run a Docker daemon. VM compute has a separate rate, so treating the two runtimes as interchangeable will produce the wrong budget.
For example, a worker that reviews source files and runs a Python test suite can start with a standard sandbox trial. A worker that launches a Compose application with databases belongs on the VM evaluation path. A browser-heavy job needs its browser dependencies, memory, and sandbox compatibility tested as well.
Agent37's
agent37-ubuntu VM template includes Docker. Its default allocation uses 12 GB disk, so specify disk explicitly when comparing another shape. VM entrypoints do not provide systemd init. Follow the VM documentation for process startup and durable Docker storage.Agent37 also has an instance-level outbound network policy. Its default allows public internet access. You can deny outbound traffic or allow specified IPv4 addresses and ranges; domain names are not accepted. This is separate from the Bash sandbox's domain rules. A restricted worker needs a reachable model endpoint or proxy, and DNS must be allowed when needed. Test the deployed policy before sending a real job.
These are workload selection rules, not a throughput benchmark. Measure completion time, peak memory, and failed jobs on your own repository.
Package and deploy one SDK worker
Start with one representative job and one worker. Make that path repeatable before building a pool.
1. Package the actual Agent SDK. For TypeScript, use
@anthropic-ai/claude-agent-sdk; for Python, use claude-agent-sdk. The basic Anthropic API client is a different package. Follow the SDK quickstart, lock dependencies, and verify that the bundled Claude Code executable launches in your built image. Most supported installs include it; some installation paths require a separate binary.2. Choose authentication for your application. The quickstart documents API credentials and supported cloud-provider authentication. Do not assume a personal Claude subscription can fund a third-party SDK product. Anthropic requires prior approval for third-party products offering claude.ai login or its rate limits. Inject runtime credentials without baking them into the image.
3. Register your image as an Agent37 template. Use a cloud build from your Dockerfile or import an existing registry image. The template records a pinned image copy. Your main process must remain running; a one-shot script that immediately exits is not a persistent worker service. Exclude secret files from the build context. Follow Build a custom image.
4. Create the instance from that template. Use the Cloud dashboard or
POST /v1/instances, select the runtime, and set resources deliberately. Keep the workspace API key in your provisioning service. The worker needs task credentials, not authority to manage your whole fleet. The instance reference covers lifecycle operations.5. Exercise the application contract. Submit a harmless job, collect its output and exit status, and repeat after a restart. Your custom SDK application owns its request interface. Registering an arbitrary image does not create a harness chat API for it.
Separate tenant state and plan for restarts
Different working-directory names are useful organization, but they do not by themselves prevent one process from reading another tenant's files. For an initial customer-facing deployment, one isolated worker per tenant or job is easier to reason about than many tenants sharing one writable environment.
Make three things explicit: the job workspace, the SDK configuration directory, and the saved conversation state. Decide which is temporary and which must survive. If the worker is deleted, how will you recover an unfinished job without repeating an external action?
settingSources: [] skips user, project, and local settings, but it is not a switch that removes every filesystem-sourced input. Auto memory has separate behavior. Review what settingSources does not control before relying on it for tenant separation.For sessions that move between hosts, the SDK provides a
SessionStore adapter for transcripts. That does not automatically store your repository or generated artifacts. Give those their own storage and recovery plan. Anthropic's session storage guide explains the distinction.Record a job ID, session ID, artifact location, and completion status outside the worker. Before retrying a job that sends a message or changes external data, check whether that action already completed. A restored transcript alone is not an exactly-once execution system.
Budget the worker separately from model usage
Agent37's standard rates are $0.80 per vCPU and $0.70 per GB RAM per 730 running hours, plus $0.09 per GB disk per 730 retained hours. Full VM compute costs 2.5 times standard compute; disk uses the same rate. Billing is metered by the minute. See current pricing.
The following examples allocate 2 vCPU, 4 GB RAM, and 8 GB disk to one worker. Eight GB provides more headroom than a tiny disk, but it is still only a planning assumption: repositories, package caches, and Docker images can require much more.
Usage during a 730-hour month | Standard gVisor | Full VM |
730 hours running, disk retained throughout | $5.12 | $11.72 |
60 hours running, disk retained throughout | About $1.08 | About $1.62 |
Stopped throughout, 8 GB disk retained | $0.72 | $0.72 |
For the standard 60-hour example, compute is
(2 × $0.80 + 4 × $0.70) × 60 / 730, approximately $0.36. Add $0.72 for the month of disk retention. For the VM example, multiply only that compute component by 2.5.An awake worker waiting for a model still bills compute. Stopping or sleeping pauses compute; retained disk continues billing. Configure auto-sleep deliberately and test that its idle rules fit your worker's activity. Do not assume a quiet background process automatically sleeps safely.
Model tokens and external tools are additional costs. The SDK's
maxBudgetUsd uses a client-side estimate that can overshoot its threshold; it is not a hard cap on every service your job touches. Track model spend separately using the SDK cost guidance.Prove the boundary before scaling
Use dummy data for the first acceptance run. Check that the worker can read its assigned repository and produce an artifact, while an unrelated tenant's test file remains inaccessible. Exercise both direct file tools and shell commands, since they follow different control paths.
Then test a blocked network destination, a permitted destination, a process failure, and a restart. Confirm that logs contain the job outcome without exposing credentials. Set a time limit outside the agent loop so a stuck process does not occupy a worker indefinitely.
Finally, measure a small batch of real jobs. Record aggregate running hours, peak disk use, model spend, and successful completions. That gives you a cost per completed task you can use to choose between persistent workers and disposable job environments.
Agent37 supplies the execution infrastructure while you control the SDK application. Create one sandbox, run your acceptance job, and size the next worker from what you measured.
