Skip to content

Commit 948bbbe

Browse files
Anthropic managed agents e2b (#99)
2 parents 4b25c51 + 2b37406 commit 948bbbe

64 files changed

Lines changed: 8452 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ Read more about E2B on the [E2B website](https://e2b.dev) and the official [E2B
6565
<td><a href="./examples/openai-codex-in-sandbox-js">TypeScript</a></td>
6666
</tr>
6767
<tr>
68-
<td rowspan="2">Anthropic</td>
68+
<td rowspan="3">Anthropic</td>
6969
<td>Claude 3 Opus</td>
7070
<td>Code interpreter</td>
7171
<td><a href="./examples/claude-code-interpreter-python">Python</a></td>
@@ -77,6 +77,12 @@ Read more about E2B on the [E2B website](https://e2b.dev) and the official [E2B
7777
<td><a href="./examples/anthropic-claude-code-in-sandbox-python">Python</a></td>
7878
<td><a href="./examples/anthropic-claude-code-in-sandbox-js">TypeScript</a></td>
7979
</tr>
80+
<tr>
81+
<td>Claude Managed Agents</td>
82+
<td>Self-hosted worker running inside a Sandbox</td>
83+
<td><a href="./examples/anthropic-managed-agents/python">Python</a></td>
84+
<td>-</td>
85+
</tr>
8086
<tr>
8187
<td>Mistral</td>
8288
<td>Codestral</td>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Anthropic Managed Agents on E2B
2+
3+
Run Anthropic Managed Agents self-hosted environments from E2B sandboxes.
4+
5+
## How It Works
6+
7+
Under the hood, a self-hosted Anthropic Managed Agents environment gives you a queue of work for
8+
your own worker to handle. You can keep a worker connected and polling for that work, or you can use
9+
webhooks to wake your infrastructure when a session starts running.
10+
11+
Anthropic owns the agent session and tool-call protocol, but the self-hosted sandbox runtime is not
12+
opinionated about where those tool calls run or how you route them. In practice, that means each
13+
self-hosted setup needs a small handler that starts or finds the right sandbox, runs the
14+
`EnvironmentWorker`, and maps files, logs, outputs, and cleanup to your use case. The examples below
15+
show the common shapes: direct app orchestration, an auto-resumable webhook sandbox, and an
16+
app-owned webhook router.
17+
18+
## Examples
19+
20+
| Language | Example | What it includes |
21+
| --- | --- | --- |
22+
| Python | [python](./python) | E2B template builder, long-running Anthropic `EnvironmentWorker`, setup scripts, and a session smoke driver. |
23+
| JavaScript | [javascript](./javascript) | E2B template builder, TypeScript worker/webhook runtime, setup scripts, and a session smoke driver. |
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
E2B_API_KEY=
2+
E2B_ACCESS_TOKEN=
3+
4+
ANTHROPIC_API_KEY=
5+
ANTHROPIC_ENVIRONMENT_ID=
6+
ANTHROPIC_ENVIRONMENT_KEY=
7+
ANTHROPIC_AGENT_ID=
8+
ANTHROPIC_WEBHOOK_SIGNING_KEY=
9+
APP_WEBHOOK_ADMIN_TOKEN=
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# Example Usage Walkthrough
2+
3+
This page shows what the examples expect Anthropic to send and how the E2B worker responds.
4+
5+
## Orchestrator Flow
6+
7+
In the orchestrator example, your app starts the worker before sending user messages.
8+
9+
```mermaid
10+
sequenceDiagram
11+
participant App
12+
participant Anthropic
13+
participant E2B
14+
participant Worker as EnvironmentWorker
15+
16+
App->>E2B: make start-worker
17+
E2B->>Worker: run client.beta.environments.work.worker(...).run()
18+
App->>Anthropic: update environment metadata with worker sandbox id
19+
Worker->>Anthropic: poll self-hosted environment work queue
20+
App->>Anthropic: create session
21+
App->>Anthropic: send user.message
22+
Anthropic-->>Worker: session work item
23+
Worker->>E2B: execute bash/read/write tools in /mnt/session
24+
Worker-->>Anthropic: user.tool_result events
25+
Anthropic-->>App: stream agent.message and status events
26+
```
27+
28+
### What Your App Sends
29+
30+
`make send` creates a Managed Agents session and sends one user event:
31+
32+
```ts
33+
const session = await client.beta.sessions.create({
34+
agent: process.env.ANTHROPIC_AGENT_ID,
35+
environment_id: process.env.ANTHROPIC_ENVIRONMENT_ID,
36+
});
37+
38+
await client.beta.sessions.events.send(session.id, {
39+
events: [
40+
{
41+
type: "user.message",
42+
content: [{ type: "text", text: "Run pwd, then echo hello from E2B" }],
43+
},
44+
],
45+
});
46+
```
47+
48+
### What Anthropic Streams Back
49+
50+
The exact IDs and timestamps differ, but a successful run has this shape:
51+
52+
```jsonl
53+
{"type":"session.status_running","id":"sevt_..."}
54+
{"type":"user.message","content":[{"type":"text","text":"Run pwd, then echo hello from E2B"}]}
55+
{"type":"agent.tool_use","name":"bash","input":{"command":"pwd"}}
56+
{"type":"session.status_idle","stop_reason":{"type":"requires_action","event_ids":["sevt_..."]}}
57+
{"type":"user.tool_result","is_error":false,"content":[{"type":"text","text":"/mnt/session"}]}
58+
{"type":"session.status_running","id":"sevt_..."}
59+
{"type":"agent.tool_use","name":"bash","input":{"command":"echo hello from E2B"}}
60+
{"type":"user.tool_result","is_error":false,"content":[{"type":"text","text":"hello from E2B"}]}
61+
{"type":"agent.message","content":[{"type":"text","text":"..."}]}
62+
{"type":"session.status_idle","stop_reason":{"type":"end_turn"}}
63+
```
64+
65+
The `agent.tool_use` events come from Anthropic. The SDK worker running inside E2B executes those
66+
tool calls and sends matching `user.tool_result` events back to Anthropic.
67+
68+
## Webhook Flow
69+
70+
In the webhook example, Anthropic wakes the E2B sandbox when a session needs work.
71+
72+
```mermaid
73+
sequenceDiagram
74+
participant Anthropic
75+
participant E2B as E2B auto-resume sandbox
76+
participant Webhook as webhook-runtime.ts
77+
participant Worker as EnvironmentWorker
78+
79+
Anthropic->>E2B: POST /webhook
80+
E2B->>Webhook: resume sandbox and deliver request
81+
Webhook->>Webhook: verify signature with ANTHROPIC_WEBHOOK_SIGNING_KEY
82+
Webhook->>Worker: start worker if not already running
83+
Worker->>Anthropic: poll and service session work
84+
```
85+
86+
### What Anthropic Sends to `/webhook`
87+
88+
Anthropic signs the raw body and sends Standard Webhooks-style headers. The receiver passes the
89+
raw body and headers to `client.beta.webhooks.unwrap(...)`.
90+
91+
Representative request:
92+
93+
```http
94+
POST /webhook HTTP/1.1
95+
content-type: application/json
96+
webhook-id: whmsg_...
97+
webhook-timestamp: 1760000000
98+
webhook-signature: v1,...
99+
```
100+
101+
Representative body:
102+
103+
```json
104+
{
105+
"id": "event_...",
106+
"type": "event",
107+
"created_at": "2026-05-20T09:44:28.000000Z",
108+
"data": {
109+
"type": "session.status_run_started",
110+
"id": "sesn_...",
111+
"workspace_id": "wrkspc_...",
112+
"organization_id": "org_..."
113+
}
114+
}
115+
```
116+
117+
The JavaScript webhook handler only uses the event type:
118+
119+
```ts
120+
const event = client.beta.webhooks.unwrap(body, {
121+
headers,
122+
key: process.env.ANTHROPIC_WEBHOOK_SIGNING_KEY,
123+
});
124+
125+
if (event.data.type === "session.status_run_started") {
126+
startWorkerIfNeeded();
127+
}
128+
```
129+
130+
If `ANTHROPIC_WEBHOOK_SIGNING_KEY` is missing, `/webhook` returns `503` so you can start the
131+
sandbox once to get its public URL before creating the Anthropic webhook endpoint.
132+
133+
## Worker Contract
134+
135+
Both flows use the same worker contract:
136+
137+
| Value | Meaning |
138+
| --- | --- |
139+
| `ANTHROPIC_ENVIRONMENT_ID` | The self-hosted environment the worker polls. |
140+
| `ANTHROPIC_ENVIRONMENT_KEY` | Bearer credential for the environment worker. |
141+
| `/mnt/session` | This example's E2B workdir. |
142+
| `/mnt/session/outputs` | Suggested artifact output directory. |
143+
| `e2b_worker_sandbox_id` | Compatibility metadata key for the most recent worker sandbox. |
144+
| `e2b_worker_sandbox_ids` | JSON metadata list of known worker sandboxes. |
145+
| `e2b_webhook_sandbox_id` | Compatibility metadata key for the most recent auto-resumable webhook sandbox. |
146+
| `e2b_webhook_sandbox_ids` | JSON metadata list of known auto-resumable webhook sandboxes. |
147+
148+
The worker polls work at the Anthropic environment level. Multiple E2B sandboxes can be tracked and
149+
started by these examples, but strict per-session isolation needs a production routing primitive or
150+
an app-level design that scopes work to a specific worker.

0 commit comments

Comments
 (0)