How a managed agent splits between Anthropic and your sandbox
A managed agent has two halves, and only one of them runs on Anthropic’s infrastructure. Anthropic hosts the model, the agent loop, session state, and a work queue. It decides which tool to call but never executes one. Everybash, read, write, edit, glob, and grep call runs in an execution environment you own.
When you set a Claude Environment’s hosting type to Self-hosted, Anthropic doesn’t run tools itself. Each time a session run starts, it adds a work item to the environment’s queue. Your orchestrator reads that queue and creates a Tensorlake sandbox for the session. A worker inside the sandbox connects back to Anthropic and executes tool calls until the session ends.
Where to run the orchestrator
The orchestrator does the same work in every mode: get or create a sandbox for the session, launch the worker, then drain the queue. The reference implementation keeps that logic in one module,src/orchestrator_lib.py, and ships three entrypoints. The modes differ in where the code runs and how it learns about new work:
How webhook-in-sandbox mode works
In this mode the webhook receiver runs inside a Tensorlake sandbox, and Tensorlake serves port 5051 at a public HTTPS URL. Anthropic pushes webhooks to that URL. You run no host process and manage no TLS certificate. The launcher creates the receiver sandbox with an idle timeout, set byWEBHOOK_SANDBOX_TIMEOUT_SECONDS (default 600s). When no inbound request arrives within that window, the sandbox suspends, and Tensorlake preserves its memory and the running uvicorn process. The next inbound webhook resumes it. Tensorlake doesn’t bill a suspended sandbox.
Resume is a memory-snapshot restore, not a cold boot. In a test on tensorlake 0.5.30, a sandbox in the suspended state answered GET /healthz in about 0.6s and moved to running. Only inbound traffic through the exposed port counts as activity. The receiver’s own outbound polling doesn’t keep the sandbox awake, so it suspends on schedule.
How session sandboxes suspend and resume
Each session’s sandbox follows the same cycle. An agent session works in bursts, separated by waits for a human approval, a slow CI job, or model think time. AfterSANDBOX_TIMEOUT_SECONDS without activity, the session’s sandbox suspends, and Tensorlake freezes its filesystem and processes in a snapshot. Tensorlake doesn’t bill a suspended sandbox.
When the next work item arrives for that session, the orchestrator calls Sandbox.get_or_create() with the same name. One call handles every case:
- No sandbox exists: creates it from the image and blocks until it’s running
- The sandbox is running: attaches to it
- The sandbox is suspended: resumes it from its snapshot, with
/workspace, installed dependencies, and warm caches intact
bind_outcome attribute on the returned sandbox reports which path ran: created, attached, or resumed. The orchestrator then relaunches the worker with the session’s environment variables. On attach or resume, the previous worker may have exited at its idle limit, but the filesystem stays intact, so only the worker process restarts.
Image and resource arguments apply only on create. An existing sandbox keeps its own. See Get or create a named sandbox for the API.
Run the reference integration
The reference repo ships a working integration: an image build, the in-sandbox worker, and one orchestrator in three modes. The steps below set up the recommended webhook-in-sandbox mode. Two steps happen in the Claude Console and have no CLI equivalent. The repo README covers those Console steps, the other two modes, and troubleshooting.1
Copy the environment files and install dependencies
.env. Your Anthropic API key, workspace ID, and agent ID live in .env.local.2
Log in to Tensorlake and build the session image
Set
TENSORLAKE_API_KEY in .env, then run:make build builds the image each session sandbox starts from. The Python SDK reads TENSORLAKE_API_KEY and the tl CLI uses your login session. Point both at the same Tensorlake project. If they differ, the build registers the image in one project and the launcher looks for it in another.3
Create the agent and a self-hosted environment
In a non-default Claude Platform workspace, create the agent:In the Claude Console, create an Environment with hosting type Self-hosted and generate its environment key. Set
ANTHROPIC_WORKSPACE_ID, ANTHROPIC_API_KEY, and ANTHROPIC_AGENT_ID in .env.local. Set ANTHROPIC_ENVIRONMENT_ID and ANTHROPIC_ENVIRONMENT_KEY in .env.4
Build and launch the webhook receiver
https://5051-<sandbox-id>.sandbox.tensorlake.ai. The URL is keyed by sandbox ID, so recreating the sandbox changes it.5
Register the webhook and pass the signing secret to the receiver
In Claude Platform, create a Webhook pointed at the printed URL and subscribe it to Session lifecycle → Run started. Put the signing secret in The receiver reads the secret at launch, so it needs a restart after you set or rotate it. The sandbox ID and URL don’t change on restart.
ANTHROPIC_WEBHOOK_SIGNING_KEY in .env, then relaunch the receiver in place:6
Drive a session
running, thinking, and tool calls such as → write and → read, and ends with · done. If nothing streams, run the work.stats check in the README. In the webhook modes, workers_polling reads 0 between events because the receiver polls only on demand. Watch depth and pending rise and drain back to 0 instead.Pass credentials per process and name sandboxes as slugs
Two Tensorlake SDK rules shape how the orchestrator handles secrets and names:- Pass environment variables on
start_process, not on create: the orchestrator passesANTHROPIC_ENVIRONMENT_KEYand the session, work, and environment IDs throughstart_process(env={...}). The values merge on top of the sandbox’s base environment. - Use slug names: sandbox names allow lowercase letters, digits, and hyphens only. Anthropic session IDs contain underscores and uppercase letters, so the orchestrator lowercases the ID, replaces each disallowed character with a hyphen, and prefixes
agent-. The name is deterministic, so every work item for a session resolves to the same sandbox.
.env precedence, import config before the Tensorlake SDK so the API key loads first, and keep the SDK key and the tl CLI on one project. The README’s troubleshooting section covers each one.
Run tool calls in parallel from one snapshot
The parallel sub-agents example forks N sandboxes from one snapshot, so a single session can explore N candidate solutions at once. The parent callscheckpoint(), then the orchestrator calls Sandbox.create(snapshot_id=...) N times. Expose it to the agent in one of three ways:
- A CLI helper in the image that the agent calls through
bash - A Model Context Protocol (MCP) tool
- An orchestrator-side action gated by session metadata
Next steps
Reference code
The full integration: image build, in-sandbox worker, and one orchestrator in three runnable modes.
Claude Managed Agents
Anthropic’s docs for the agent harness, sessions, and self-hosted environments.
Sandbox lifecycle
The suspend, resume, and snapshot model behind wake-on-request.
Parallel sub-agents
Fork N sandboxes from one snapshot for best-of-N tool execution.