This page shows what the examples expect Anthropic to send and how the E2B worker responds.
In the orchestrator example, your app starts the worker before sending user messages.
sequenceDiagram
participant App
participant Anthropic
participant E2B
participant Worker as EnvironmentWorker
App->>E2B: make start-worker
E2B->>Worker: run EnvironmentWorker.run()
App->>Anthropic: update environment metadata with worker sandbox id
Worker->>Anthropic: poll self-hosted environment work queue
App->>Anthropic: create session
App->>Anthropic: send user.message
Anthropic-->>Worker: session work item
Worker->>E2B: execute bash/read/write tools in /mnt/session
Worker-->>Anthropic: user.tool_result events
Anthropic-->>App: stream agent.message and status events
make send creates a Managed Agents session and sends one user event:
session = client.beta.sessions.create(
agent=os.environ["ANTHROPIC_AGENT_ID"],
environment_id=os.environ["ANTHROPIC_ENVIRONMENT_ID"],
)
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Run pwd, then echo hello from E2B"}],
}
],
)The exact IDs and timestamps differ, but a successful run has this shape:
session=sesn_...
SessionStatusRunningEvent(type='session.status_running')
UserMessageEvent(type='user.message', content=[TextBlock(text='Run pwd, then echo hello from E2B')])
AgentToolUseEvent(type='agent.tool_use', name='bash', input={'command': 'pwd'})
SessionStatusIdleEvent(stop_reason=RequiresAction(...))
UserToolResultEvent(type='user.tool_result', content=[TextBlock(text='/mnt/session')])
SessionStatusRunningEvent(type='session.status_running')
AgentToolUseEvent(type='agent.tool_use', name='bash', input={'command': 'echo hello from E2B'})
UserToolResultEvent(type='user.tool_result', content=[TextBlock(text='hello from E2B')])
AgentMessageEvent(type='agent.message', content=[TextBlock(text='...')])
SessionStatusIdleEvent(stop_reason=EndTurn(...))
The agent.tool_use events come from Anthropic. The SDK worker running inside E2B executes those
tool calls and sends matching user.tool_result events back to Anthropic.
In the webhook example, Anthropic wakes the E2B sandbox when a session needs work.
sequenceDiagram
participant Anthropic
participant E2B as E2B auto-resume sandbox
participant Webhook as FastAPI webhook_runtime.py
participant Worker as EnvironmentWorker
Anthropic->>E2B: POST /webhook
E2B->>Webhook: resume sandbox and deliver request
Webhook->>Webhook: verify signature with ANTHROPIC_WEBHOOK_SIGNING_KEY
Webhook->>Worker: start worker if not already running
Worker->>Anthropic: poll and service session work
Anthropic signs the raw body and sends Standard Webhooks-style headers. The receiver passes the
raw body and headers to client.beta.webhooks.unwrap(...).
Representative request:
POST /webhook HTTP/1.1
content-type: application/json
webhook-id: whmsg_...
webhook-timestamp: 1760000000
webhook-signature: v1,...Representative body:
{
"id": "event_...",
"type": "event",
"created_at": "2026-05-20T09:44:28.000000Z",
"data": {
"type": "session.status_run_started",
"id": "sesn_...",
"workspace_id": "wrkspc_...",
"organization_id": "org_..."
}
}The Python webhook handler only uses the event type:
event = client.beta.webhooks.unwrap(payload, headers=dict(request.headers), key=signing_key)
if event.data.type == "session.status_run_started":
start_worker_if_needed()If ANTHROPIC_WEBHOOK_SIGNING_KEY is missing, /webhook returns 503 so you can start the
sandbox once to get its public URL before creating the Anthropic webhook endpoint.
Both flows use the same worker contract:
| Value | Meaning |
|---|---|
ANTHROPIC_ENVIRONMENT_ID |
The self-hosted environment the worker polls. |
ANTHROPIC_ENVIRONMENT_KEY |
Bearer credential for the environment worker. |
/mnt/session |
This example's E2B workdir. |
/mnt/session/outputs |
Suggested artifact output directory. |
e2b_worker_sandbox_id |
Compatibility metadata key for the most recent worker sandbox. |
e2b_worker_sandbox_ids |
JSON metadata list of known worker sandboxes. |
e2b_webhook_sandbox_id |
Compatibility metadata key for the most recent auto-resumable webhook sandbox. |
e2b_webhook_sandbox_ids |
JSON metadata list of known auto-resumable webhook sandboxes. |
The direct worker and sandbox-hosted webhook examples poll work at the Anthropic environment level,
so persistent files belong to the worker sandbox that claimed the work. Use the app-webhooks/
example with APP_SANDBOX_ROUTING_SCOPE=session when each Managed Agents session should have its
own E2B sandbox and follow-up state.