Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
{
"group": "Agents in sandbox",
"pages": [
"docs/agents/anthropic-managed-agents",
"docs/agents/amp",
"docs/agents/claude-code",
"docs/agents/claude-managed-agents",
"docs/agents/codex",
"docs/agents/devin",
"docs/agents/openai-agents-sdk",
Expand Down Expand Up @@ -3727,6 +3727,11 @@
}
},
"redirects": [
{
"source": "/docs/agents/anthropic-managed-agents",
"destination": "/docs/agents/claude-managed-agents",
"permanent": true
},
{
"source": "/docs/troubleshooting/pip-install-error",
"destination": "/docs/faq/pip-install-error",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
---
title: "Anthropic Managed Agents"
description: "Use E2B as the sandbox runtime for Anthropic Managed Agents self-hosted environments."
title: "Claude Managed Agents"
description: "Use E2B as the sandbox runtime for Claude Managed Agents self-hosted environments."
icon: "/images/icons/claude-code.svg"
---

[Anthropic Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) can use a self-hosted environment when you want to run tool calls in your own infrastructure. E2B provides a reusable `E2B/claude-managed-agents-webhooks` template that receives Anthropic webhooks and routes each Managed Agents session to a persistent E2B worker sandbox.
[Claude Managed Agents](https://platform.claude.com/docs/en/managed-agents/overview) can use a self-hosted environment when you want tool calls to run in your own infrastructure. Claude runs the agentic loop and reasoning process; E2B provides isolated sandbox infrastructure for the environment where tool calls execute. The reusable `E2B/claude-managed-agents-webhooks` template receives webhooks and routes each Claude Managed Agents session to a persistent E2B worker sandbox.

Check warning on line 7 in docs/agents/claude-managed-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/agents/claude-managed-agents.mdx#L7

Did you really mean 'agentic'?

<Info>
For the full source, local setup scripts, and app-owned routing examples, see the [Anthropic Managed Agents cookbook](https://github.com/e2b-dev/e2b-cookbook/tree/main/examples/anthropic-managed-agents).
This separation is intentional for security: Claude decides what work to do, while the sandbox contains the execution environment, filesystem, tools, network access, and runtime logs.
</Info>

<Info>
For the full source, local setup scripts, and app-owned routing examples, see the [Claude Managed Agents cookbook](https://github.com/e2b-dev/e2b-cookbook/tree/main/examples/anthropic-managed-agents).
</Info>

## Install dependencies
Expand All @@ -28,20 +32,20 @@
# E2B dashboard API keys: https://e2b.dev/dashboard?tab=keys
export E2B_API_KEY="..."

# Anthropic Console API keys: https://console.anthropic.com/settings/keys
# Claude Console API keys: https://console.anthropic.com/settings/keys
export ANTHROPIC_API_KEY="..."

# Anthropic Console environments: https://platform.claude.com/workspaces/default/environments
# Claude Console environments: https://platform.claude.com/workspaces/default/environments
export ANTHROPIC_ENVIRONMENT_ID="..."

# Open the self-hosted environment in the Anthropic Console and click Generate environment key.
# Open the self-hosted environment in the Claude Console and click Generate environment key.
export ANTHROPIC_ENVIRONMENT_KEY="..."
```

## Start the webhook sandbox

Start the public template with auto-resume enabled. The template starts a webhook server on port `8000`.
Because Anthropic only shows the webhook signing key after you register an endpoint, write the router config now and add the signing key to the same sandbox after registration.
Because the signing key only appears after you register a webhook endpoint, write the router config now and add the signing key to the same sandbox after registration.

<CodeGroup>
```typescript JavaScript & TypeScript
Expand Down Expand Up @@ -109,7 +113,7 @@

## Register the webhook

In the [Anthropic Console webhooks settings](https://platform.claude.com/settings/workspaces/default/webhooks), create a webhook endpoint using the printed URL:
In the [Claude Console webhooks settings](https://platform.claude.com/settings/workspaces/default/webhooks), create a webhook endpoint using the printed URL:

```text
https://<sandbox-host>/webhook
Expand Down Expand Up @@ -143,25 +147,25 @@
```
</CodeGroup>

## Send work to the agent
## Run an end-to-end smoke test

Create or select a Managed Agents agent in the [Anthropic Console](https://platform.claude.com/workspaces/default/agents), then create a session with that agent and the same `ANTHROPIC_ENVIRONMENT_ID` you wrote into the webhook sandbox. Creating the session does not start work; the `user.message` event does.
Create or select a Claude Managed Agents agent in the [Claude Console](https://platform.claude.com/workspaces/default/agents), then create a session with that agent and the same `ANTHROPIC_ENVIRONMENT_ID` you wrote into the webhook sandbox. Creating the session does not start work; the `user.message` event does.

```bash
export ANTHROPIC_AGENT_ID="agent_..."
```

Use a small sandbox task for the first smoke test:
Use a small shell task for the first smoke test:

```text
Use bash to echo webhook-smoke-ok. Answer only with that text.
```

<CodeGroup>
```typescript JavaScript & TypeScript
import Anthropic from '@anthropic-ai/sdk'
import Claude from '@anthropic-ai/sdk'

const client = new Anthropic({
const client = new Claude({
apiKey: process.env.ANTHROPIC_API_KEY,
})

Expand Down Expand Up @@ -190,9 +194,9 @@

```python Python
import os
import anthropic
from anthropic import Anthropic as Claude

client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
client = Claude(api_key=os.environ["ANTHROPIC_API_KEY"])

session = client.beta.sessions.create(
agent=os.environ["ANTHROPIC_AGENT_ID"],
Expand All @@ -219,6 +223,12 @@
```
</CodeGroup>

Claude should answer:

```text
webhook-smoke-ok
```

Then check the webhook sandbox:

<CodeGroup>
Expand Down Expand Up @@ -261,30 +271,30 @@
- `/health` returning `ok: true`.
- Router logs showing `routing work` and `assigned session`.
- A session-to-sandbox assignment in the router's assignment store.
- The assigned worker sandbox's `worker.log` showing claimed work, tool execution, and successful results posted back to Anthropic.
- The Anthropic session returning to `session.status_idle`.
- The assigned worker sandbox's `worker.log` showing the shell tool execution and successful results posted back to Claude.
- The Claude Managed Agents session returning to `session.status_idle`.

The assignment store records the worker sandbox ID for each routed session. Connect to that sandbox and check `/opt/anthropic-managed-agents-js/worker.log` when you need the tool execution logs.

If the session stays at `requires_action`, check `/opt/anthropic-managed-agents-js/webhook.log` in the router sandbox first, then check `/opt/anthropic-managed-agents-js/worker.log` in the assigned worker sandbox. Stale environment keys, missing signing keys, archived sessions, and failed tool-result posts show up there.

## Runtime behavior

The worker runs with `/mnt/session` as its workdir. File tools are constrained to that workdir, skills are downloaded under `/mnt/session/skills/<name>/`, and generated artifacts should be written under `/mnt/session/outputs`.
The worker sandbox runs tool calls with `/mnt/session` as its workdir. File tools are constrained to that workdir, skills are downloaded under `/mnt/session/skills/<name>/`, and generated artifacts should be written under `/mnt/session/outputs`.

Check warning on line 283 in docs/agents/claude-managed-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/agents/claude-managed-agents.mdx#L283

Did you really mean 'workdir'?

Check warning on line 283 in docs/agents/claude-managed-agents.mdx

View check run for this annotation

Mintlify / Mintlify Validation (e2b) - vale-spellcheck

docs/agents/claude-managed-agents.mdx#L283

Did you really mean 'workdir'?

The webhook sandbox is the router. It keeps a session-to-sandbox assignment store and starts worker sandboxes with E2B auto-resume and pause-on-timeout settings.

## Session-scoped sandboxes

By default, the public webhook template gives each Managed Agents session its own E2B worker sandbox. Follow-up turns for the same session reconnect to the same worker and reuse its `/mnt/session` filesystem.
By default, the public webhook template gives each Claude Managed Agents session its own E2B worker sandbox. Follow-up turns for the same session reconnect to the same worker and reuse its `/mnt/session` filesystem. The sandbox is the isolated execution environment, not the place where Claude's reasoning loop runs.

Use [cloud buckets](/docs/storage/cloud-buckets), [Archil](/docs/storage/archil), or [volumes](/docs/volumes) when files need to outlive a sandbox or be shared across many sandboxes.

If you want to run that router in your own service instead of in E2B, use the cookbook's [`app-webhooks/` example](https://github.com/e2b-dev/e2b-cookbook/tree/main/examples/anthropic-managed-agents/javascript/app-webhooks). It receives Anthropic webhooks in your app, claims work there, and routes each session to its own E2B sandbox by default.
If you want to run that router in your own service instead of in E2B, use the cookbook's [`app-webhooks/` example](https://github.com/e2b-dev/e2b-cookbook/tree/main/examples/anthropic-managed-agents/javascript/app-webhooks). It receives webhooks in your app, claims work there, and routes each session to its own E2B sandbox by default.

## Clean up

Remove the webhook endpoint in the Anthropic Console before deleting the router sandbox. Then kill the router sandbox and any assigned worker sandboxes you no longer need.
Remove the webhook endpoint in the Claude Console before deleting the router sandbox. Then kill the router sandbox and any assigned worker sandboxes you no longer need.

## Related guides

Expand Down
166 changes: 149 additions & 17 deletions docs/agents/devin.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
---
title: "Devin"
description: "Run Devin for Terminal in a secure E2B sandbox."
description: "Run Devin in or against secure E2B sandboxes."
icon: "/images/icons/devin.svg"
---

[Devin for Terminal](https://devin.ai/terminal) is Cognition's coding agent for working directly from a terminal. You can install it in an E2B sandbox and use the sandbox as an isolated workspace for agent tasks.
[Devin](https://devin.ai) is Cognition's coding agent. You can use E2B with Devin in two ways:

## Installation
- run Devin for Terminal directly inside an isolated E2B sandbox
- run a Devin Outposts worker in an E2B sandbox and route Devin sessions to it

Use a PTY for install and login because Devin's setup is interactive. You can create a Devin account during sign up if you don't have one.
## Run Devin for Terminal

[Devin for Terminal](https://devin.ai/terminal) runs directly from a terminal. Install it in a sandbox to give Devin an isolated workspace without access to your local machine.

```bash
e2b sandbox create base
Expand All @@ -17,30 +20,159 @@ e2b sandbox create base
# Inside the sandbox
###
curl -fsSL https://cli.devin.ai/install.sh | bash

source /home/user/.bashrc
```

## Usage

After installation and login, use `devin -p` for non-interactive mode and `--permission-mode dangerous` to auto-approve tool calls.
After completing Devin's interactive sign-in, run a task from the project directory:

```bash
mkdir -p /home/user/project
cd /home/user/project
git clone https://github.com/your-org/your-repo.git /home/user/repo
cd /home/user/repo

devin --permission-mode dangerous -p "Add error handling to all API endpoints"
```

## Run Devin Outposts in E2B

Use the public `devin-outposts` template to run an Outposts worker and its setup UI inside an E2B sandbox. The template includes the Devin CLI, starts the setup UI on port `3000`, and reserves `/mnt/repos` as the worker workspace.

<Card title="Open the Devin Outposts template" icon="terminal" href="https://e2b.dev/dashboard/terminal?template=aiengineer-d56d/devin-outposts">
Start the template in the E2B dashboard and open its terminal.
</Card>

You can also start it with the SDK:

```ts
import { Sandbox } from "e2b"

devin --permission-mode dangerous -p "Create a hello world HTTP server in Go"
const sandbox = await Sandbox.create("aiengineer-d56d/devin-outposts")
console.log(sandbox.sandboxId)
```
Comment thread
cursor[bot] marked this conversation as resolved.

## Example: work on a cloned repository
The immutable template ID is `myw11k4t1jtjbr7ckvz8`.

After installing Devin for Terminal and signing in, clone a repository and run Devin from the project directory.
### Open the setup UI

When the terminal connects, it prints the exact setup URL for that sandbox and the command that reads its sandbox-local control token. The URL has this shape:

```text
https://3000-<sandbox-id>.<e2b-domain>
```

The sandbox receives its runtime ID as `E2B_SANDBOX_ID`. A self-hosted E2B deployment must configure its own E2B domain when building the template; the sandbox cannot infer that public domain from its runtime ID.

Read the setup token inside the sandbox:

```bash
git clone https://github.com/your-org/your-repo.git /home/user/repo
cd /home/user/repo
cat /home/user/.config/devin-outposts/control-token
```

devin --permission-mode dangerous -p "Add error handling to all API endpoints"
Enter it in the setup UI. A successful exchange issues a signed, HTTP-only session cookie valid for 12 hours. The control token remains reusable inside that sandbox and is not stored in browser local storage.

### Configure the worker

The setup UI asks for credentials and routing information from your Devin organization:

| Value | Purpose |
| --- | --- |
| Devin API key | List and message sessions after this worker claims them |
| Devin API URL | API endpoint for your Devin deployment |
| Devin organization URL | Full `/org/<slug>` page used to open the task composer in the same organization as the API selection |
| Organization | Organization that owns the sessions |
| Outposts pool ID | Virtual environment the worker joins |
| Outposts worker token | Authenticates the worker to that pool |

<Warning>
Do not put these credentials in a public template. The setup UI stores them only in the running sandbox with file mode `0600`. Treat a snapshot of a configured sandbox as secret-bearing.
</Warning>

Save the configuration and start the worker. The status view shows whether the worker process is running and displays recent worker output for troubleshooting. Confirm the pool appears in Devin's virtual-environment menu before sending a task; process state alone does not prove pool registration.

If the template reports that no Outposts pools are available, the API key cannot see a pool that this worker can join. Create or assign the pool in Devin, then run **Check Devin account** again before saving the connection.

Copy the organization URL from Devin while that organization is open. For example:

```text
https://app.devin.ai/org/your-org
```

The organization selected in the template UI controls API session listing and follow-ups. The `/org/<slug>` URL controls where Devin creates the browser session. These must refer to the same organization; an origin-only URL such as `https://app.devin.ai` is rejected because it would inherit the browser's last selected organization. Confirm the pairing in the setup form after selecting the API organization. Changing either value requires confirmation again.

### Send a task to the Outposts worker

<Steps>
<Step title="Wait for the worker process">
The template UI header should say **Process running**. This means the local worker process is alive. Before sending work, also verify that the pool is available in Devin; process state alone does not prove registration.
</Step>
<Step title="Describe the task">
Enter what Devin should build, change, or investigate. The template adds instructions to use `/mnt/repos` and to stop when the wrong virtual environment was selected. Nothing is sent while you type.
</Step>
<Step title="Open Devin with the prepared task">
Choose **Open Devin with this task**. A new Devin page opens with the prompt pre-filled, but the task is not sent yet.
</Step>
<Step title="Open Configuration in Devin">
Look directly below the prompt. Select the **Configuration** button beside the attachment and effort controls, then open **Virtual environment**.

```text
┌──────────────────────────────────────────────┐
│ Prepared task │
│ │
└──────────────────────────────────────────────┘
Attach [ Configuration ] Normal Send
└─ Virtual environment
```
</Step>
<Step title="Select the Outposts pool">
Choose the virtual environment whose name exactly matches the pool shown in the template UI. Devin labels registered pools as Outpost environments. Do this before selecting **Send**.
</Step>
<Step title="Send and attach the session">
Send the prepared task in Devin. Return to the template UI, select **Refresh** under **Sessions claimed by this worker**, and attach the new session after this worker claims it. You can then read history and send follow-up messages from the template UI.
</Step>
</Steps>

The task prompt tells Devin to work in `/mnt/repos`. If Devin reports a different workspace, such as `/home/ubuntu/repos`, the session is running on a managed Devin machine instead of the selected Outposts environment.

<Check>
The session is routed correctly when Devin works in `/mnt/repos`, does not ask you to choose a repository path, and the session appears in the template UI after the worker claims it.
</Check>

<Warning>
If Devin says `/mnt/repos` is missing or reports `/home/ubuntu/repos`, stop that session. Open the task again and select the Outposts pool under **Configuration** → **Virtual environment** before sending it.
</Warning>

The task is passed to Devin in the browser URL. Do not include credentials or other secrets in the task field.

<Note>
Creating a session through the public Devin v3 API does not currently select an Outposts pool. The initial task is therefore sent from Devin's web UI, where the virtual environment can be selected. After the worker claims the session, the template UI can display its history and send follow-up messages through the API.
</Note>

### Verify the worker

The worker log is the first place to check startup and claim failures:

```bash
devin --version
test -d /mnt/repos
tail -200 /home/user/devin-worker.log
```

Devin can edit files, run commands, and work on code inside the sandbox without accessing your local machine.
Successful claim logs may contain either `serving session <session-id>` or a structured `session_id` field. Once attached, the setup UI polls the session history and renders Devin's messages as they become available.

### How the integration works

<img
src="/images/Frame-13.png"
alt="Frame 13"
title="Frame 13"
style={{ width:"53%" }}
/>

The worker, setup UI, credentials, and workspace stay inside the sandbox. The browser talks to the setup UI, and the setup UI makes authenticated Devin API requests on behalf of the user.

## Limitations

- A Devin API key does not start an Outposts worker. The worker also needs a pool ID and worker token.
- Existing Devin sessions remain assigned to the worker that claimed them. Do not assume a follow-up will migrate an old session to a replacement worker.
- Devin can assign a new task to any available worker in the selected pool. Use a dedicated pool, or stop stale workers, when validating a specific sandbox or template build.
- Use scoped, short-lived Outposts worker tokens when available.
- Web apps started by Devin can be opened through their E2B sandbox preview URLs.
Binary file added images/Frame-13.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/devin_flowchart-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/devin_flowchart-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/devin_flowchart-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/devin_flowchart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading