Skip to main content
Claude Managed Agents can run its tools in an environment you host. This guide shows how to make that environment a Tensorlake sandbox: Anthropic runs the agent loop, an orchestrator you run creates one sandbox per session, and a worker inside that sandbox executes each tool call. You’ll learn how the parts fit together, where to run the orchestrator, how sessions suspend and resume, and how to run the reference integration.

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. Every bash, 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:
Run exactly one orchestrator per ANTHROPIC_ENVIRONMENT_ID: one host process or one webhook sandbox, never both.

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 by WEBHOOK_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. After SANDBOX_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
The 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

Credentials the orchestrator needs live in .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

The launcher prints a public URL of the form 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 ANTHROPIC_WEBHOOK_SIGNING_KEY in .env, then relaunch the receiver in place:
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.
6

Drive a session

A working session streams 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 passes ANTHROPIC_ENVIRONMENT_KEY and the session, work, and environment IDs through start_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.
The reference code has three setup traps. Watch .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 calls checkpoint(), 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.