“Self-hosted sandboxes”(自托管沙箱)将智能体的工具执行从 Anthropic 托管的云沙箱迁移到您控制的基础设施中,而 Anthropic 继续运行智能体本身。要了解这意味着什么并判断它是否适合您的智能体,请参阅选择智能体环境。
工作原理
self_hosted 环境充当一个工作队列。您运行一个 environment worker(环境工作进程),这是在您自己的基础设施上为该队列提供服务的进程:
- 您创建一个以该环境为目标的会话。Anthropic 将该会话作为工作项加入队列。
- 您的工作进程认领该工作项,并下载智能体的 skills 和会话的 memory stores。
- Claude 在 Anthropic 一侧运行并请求工具调用。您的工作进程在本地运行每个调用,并将结果回传。
工具的输入和输出仍会流向 Anthropic 的 control plane(控制平面),以便模型接收结果并决定下一步操作。技能和记忆存储由 Anthropic 存储,您的沙箱会为该会话保存一份副本。有关完整的数据流边界,请参阅安全模型。
自托管沙箱支持 Managed Agents 中可用的所有 Claude 模型。模型是在智能体上配置的,而不是在环境上。
ant CLI 以及 Python、TypeScript 和 Go SDK 都附带预构建的工作进程。Cloudflare、Daytona 和 Modal 等沙箱提供商也发布了各自的平台指南。
快速入门
本快速入门使用 ant CLI 运行一个常驻工作进程,向其发送一个会话,并确认智能体的工具调用在您的主机上运行。
前提条件
- 一个智能体: 如果您还没有,请先完成开始使用 Claude Managed Agents,并记下智能体 ID。
- 一台 Linux 或 macOS 主机: 主机需要在该确切路径下有
/bin/bash。worker 只需要出站 HTTPS。 - 一个 Claude API 密钥: 您在自己的机器上使用它来创建会话和读取队列统计信息。不要将它放在 worker 主机上,因为智能体的工具调用可能会读取到它。
- 您自己机器上的
antCLI 或 SDK: 本快速入门中的统计和会话步骤在您自己的机器上运行,而不是在 worker 主机上。请按照安装步骤为 worker 安装 CLI 的相同方式安装 CLI,或者安装 SDK。
注意
在 Claude Platform on AWS 上,工作进程使用 AWS IAM(SigV4)或在 AWS Console 中生成的 API 密钥进行身份验证,而不是使用环境密钥。请将
AnthropicSelfHostedEnvironmentAccess托管策略附加到运行工作进程的 IAM 主体上。在 Claude Console 中生成的环境密钥不适用于 Claude Platform on AWS 端点。在 Claude Models on Google Cloud (Anthropic managed) 上,工作进程使用 Google Cloud 凭据进行身份验证,而不是使用环境密钥。请在项目上为您的工作进程所使用的 Google Cloud 身份授予
roles/claude.user或roles/claude.admin角色。这两个角色都包含environments.processWork(工作进程需要该权限来轮询和管理工作项),以及运行会话所需的会话和技能权限。在 Claude Console 中生成的环境密钥不适用于 Claude Models on Google Cloud (Anthropic managed) 端点。antCLI 以及 Python、TypeScript 和 Go SDK 中的预构建工作进程不支持 Claude Models on Google Cloud (Anthropic managed),因此请实现您自己的工作进程,直接调用 Environments Work 端点。请参阅不支持的功能。
注意
在 macOS 上,即使您使用 Homebrew 安装了较新版本的 Bash,worker 的 bash 工具仍会运行位于
/bin/bash的系统 Bash 3.2。要在 macOS 上使用记忆存储,请先准备 macOS 主机。
运行您的第一个会话
-
创建自托管环境
在 Claude Console 中,前往 Environments 页面(
platform.claude.com/environments),点击 Create environment,然后在 Hosting 下选择 Self-hosted。或者通过 API:
cURL
curl -sS --fail-with-body https://api.anthropic.com/v1/environments \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ -d '{ "name": "self-hosted", "config": {"type": "self_hosted"} }'CLI
ant apply environment.yamlenvironment.yaml
# yaml-language-server: $schema=https://platform.claude.com/schemas/ant/beta/environment.json name: self-hosted config: type: self_hostedPython
client = anthropic.Anthropic() environment = client.beta.environments.create( name="self-hosted", config={"type": "self_hosted"} ) print(environment.id)TypeScript
const client = new Anthropic(); const environment = await client.beta.environments.create({ name: "self-hosted", config: { type: "self_hosted" } }); console.log(environment.id);C#
using Anthropic.Models.Beta.Environments; var client = new AnthropicClient(); var environment = await client.Beta.Environments.Create( new EnvironmentCreateParams { Name = "self-hosted", Config = new BetaSelfHostedConfigParams(), } ); Console.WriteLine(environment.ID);Go
client := anthropic.NewClient() environment, err := client.Beta.Environments.New(context.Background(), anthropic.BetaEnvironmentNewParams{ Name: "self-hosted", Config: anthropic.BetaEnvironmentNewParamsConfigUnion{ OfSelfHosted: &anthropic.BetaSelfHostedConfigParams{}, }, }) if err != nil { panic(err) } fmt.Println(environment.ID)Java
import com.anthropic.models.beta.environments.BetaSelfHostedConfigParams; import com.anthropic.models.beta.environments.EnvironmentCreateParams; void main() { var client = AnthropicOkHttpClient.fromEnv(); var environment = client.beta().environments().create( EnvironmentCreateParams.builder() .name("self-hosted") .config(BetaSelfHostedConfigParams.builder().build()) .build() ); IO.println(environment.id()); }PHP
$client = new Client(); $environment = $client->beta->environments->create( name: 'self-hosted', config: ['type' => 'self_hosted'], ); echo $environment->id, PHP_EOL;Ruby
client = Anthropic::Client.new environment = client.beta.environments.create( name: "self-hosted", config: {type: :self_hosted} ) puts environment.id -
生成环境密钥
在 Console 中,打开该环境并点击 Generate environment key。环境密钥用于向其队列验证 worker 的身份。即使是通过 API 创建的环境,也只能在 Console 中生成环境密钥。
在 worker 主机上导出环境 ID 和密钥:
export ANTHROPIC_ENVIRONMENT_KEY="sk-ant-oat01-..." export ANTHROPIC_ENVIRONMENT_ID="env_..." -
安装 ant CLI
在 worker 主机上运行以下命令。
Homebrew (macOS)
brew install anthropics/tap/antcurl (Linux/WSL)
对于 Linux 环境,请直接下载发布版二进制文件。
VERSION=2.4.0 OS=$(uname -s | tr '[:upper:]' '[:lower:]') case $(uname -m) in x86_64) ARCH=amd64 ;; aarch64) ARCH=arm64 ;; esac curl -fsSL "https://github.com/anthropics/anthropic-cli/releases/download/v${VERSION}/ant_${VERSION}_${OS}_${ARCH}.tar.gz" \ | sudo tar -xz -C /usr/local/bin ant您可以在 GitHub 发布页面上找到所有发布版本。
Go
您也可以使用
go install从源代码安装 CLI。需要 Go 1.25 或更高版本。go install github.com/anthropics/anthropic-cli/v2/cmd/ant@latest二进制文件会被放置在
$(go env GOPATH)/bin中。如果该目录尚未添加到您的PATH中,请将其添加进去:export PATH="$PATH:$(go env GOPATH)/bin"检查安装情况:
ant --version -
启动 worker
创建工作目录,然后将
--workdir设置为该目录来启动 worker。如果不使用该标志,worker 将使用当前目录。Linux
传入
/workspace以与系统默认值保持一致。sudo mkdir -p /workspace && sudo chown "$USER" /workspace ant beta:worker poll --workdir /workspacemacOS
根卷是只读的,因此
mkdir无法创建/workspace。请改用您主目录中的某个目录。如果智能体使用 skills,请按照沙箱文件系统中的说明,将此目录的完整路径(echo ~/workspace会打印该路径)添加到其系统提示中。mkdir -p ~/workspace ant beta:worker poll --workdir ~/workspaceworker 会读取您导出的两个变量,并持续轮询,直到您停止它。
-
验证 worker 已连接
在您自己的机器上,将
ANTHROPIC_API_KEY设置为您的 Claude API 密钥(而不是环境密钥),并将ANTHROPIC_ENVIRONMENT_ID(python, ruby:environment_id; typescript, java, csharp:environmentId; go:environmentID; php:$environmentId) 设置为环境 ID。确认workers_polling(java, php:workersPolling; csharp, go:WorkersPolling) 至少为 1:cURL
curl -sS --fail-with-body "https://api.anthropic.com/v1/environments/$ANTHROPIC_ENVIRONMENT_ID/work/stats" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01"CLI
ant beta:environments:work stats --environment-id "$ANTHROPIC_ENVIRONMENT_ID"Python
client = anthropic.Anthropic() stats = client.beta.environments.work.stats(environment_id) print(f"workers_polling={stats.workers_polling}")TypeScript
const client = new Anthropic(); const stats = await client.beta.environments.work.stats(environmentId); console.log(`workers_polling=${stats.workers_polling}`);C#
var client = new AnthropicClient(); var stats = await client.Beta.Environments.Work.Stats(environmentId); Console.WriteLine($"workers_polling={stats.WorkersPolling}");Go
client := anthropic.NewClient() stats, err := client.Beta.Environments.Work.Stats( context.Background(), environmentID, anthropic.BetaEnvironmentWorkStatsParams{}, ) if err != nil { panic(err) } fmt.Printf("workers_polling=%d\n", stats.WorkersPolling)Java
var client = AnthropicOkHttpClient.fromEnv(); var stats = client.beta().environments().work().stats(environmentId); IO.println("workers_polling=" + stats.workersPolling().orElse(null));PHP
$client = new Client(); $stats = $client->beta->environments->work->stats($environmentId); printf("workers_polling=%d\n", $stats->workersPolling);Ruby
client = Anthropic::Client.new stats = client.beta.environments.work.stats(environment_id) puts "workers_polling=#{stats.workers_polling}"如果
workers_polling(java, php:workersPolling; csharp, go:WorkersPolling) 一直为 0,请参阅故障排除。 -
启动会话
将
AGENT_ID(python, ruby:agent_id; typescript, java, csharp:agentId; go:agentID; php:$agentId) 设置为您的智能体 ID。创建一个以该环境为目标的会话,然后向其发送一个任务:cURL
# 创建会话 curl -sS --fail-with-body https://api.anthropic.com/v1/sessions \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ -d '{ "agent": "'"$AGENT_ID"'", "environment_id": "'"$ANTHROPIC_ENVIRONMENT_ID"'" }' # 向其发送任务:SESSION_ID 是创建响应中返回的 ID curl -sS --fail-with-body "https://api.anthropic.com/v1/sessions/$SESSION_ID/events" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "anthropic-beta: managed-agents-2026-04-01" \ -H "content-type: application/json" \ -d '{ "events": [ { "type": "user.message", "content": [ { "type": "text", "text": "Write the output of \"uname -a\" to hello.txt in your working directory." } ] } ] }'CLI
# 创建会话 ant beta:sessions create \ --agent "$AGENT_ID" \ --environment-id "$ANTHROPIC_ENVIRONMENT_ID" # 向其发送任务:SESSION_ID 是创建响应中返回的 ID ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML' events: - type: user.message content: - type: text text: Write the output of "uname -a" to hello.txt in your working directory. YAMLPython
session = client.beta.sessions.create( agent=agent_id, environment_id=environment_id, ) client.beta.sessions.events.send( session.id, events=[ { "type": "user.message", "content": [ { "type": "text", "text": 'Write the output of "uname -a" to hello.txt in your working directory.', }, ], }, ], )TypeScript
const session = await client.beta.sessions.create({ agent: agentId, environment_id: environmentId }); await client.beta.sessions.events.send(session.id, { events: [ { type: "user.message", content: [ { type: "text", text: 'Write the output of "uname -a" to hello.txt in your working directory.' } ] } ] });C#
var session = await client.Beta.Sessions.Create(new() { Agent = agentId, EnvironmentID = environmentId, }); await client.Beta.Sessions.Events.Send(session.ID, new() { Events = [ new BetaManagedAgentsUserMessageEventParams { Content = [ new BetaManagedAgentsTextBlock { Text = "Write the output of \"uname -a\" to hello.txt in your working directory.", }, ], }, ], });Go
session, err := client.Beta.Sessions.New(context.Background(), anthropic.BetaSessionNewParams{ Agent: anthropic.BetaSessionNewParamsAgentUnion{OfString: anthropic.String(agentID)}, EnvironmentID: environmentID, }) if err != nil { panic(err) } _, err = client.Beta.Sessions.Events.Send(context.Background(), session.ID, anthropic.BetaSessionEventSendParams{ Events: []anthropic.BetaManagedAgentsEventParamsUnion{{ OfUserMessage: &anthropic.BetaManagedAgentsUserMessageEventParams{ Content: []anthropic.BetaManagedAgentsUserMessageEventParamsContentUnion{{ OfText: &anthropic.BetaManagedAgentsTextBlockParam{ Text: "Write the output of \"uname -a\" to hello.txt in your working directory.", }, }}, }, }}, }) if err != nil { panic(err) }Java
var session = client.beta().sessions().create(SessionCreateParams.builder() .agent(agentId) .environmentId(environmentId) .build()); client.beta().sessions().events().send( session.id(), EventSendParams.builder() .addEvent(BetaManagedAgentsUserMessageEventParams.builder() .addTextContent("Write the output of \"uname -a\" to hello.txt in your working directory.") .build()) .build());PHP
$session = $client->beta->sessions->create( agent: $agentId, environmentID: $environmentId, ); $client->beta->sessions->events->send( $session->id, events: [ [ 'type' => 'user.message', 'content' => [['type' => 'text', 'text' => 'Write the output of "uname -a" to hello.txt in your working directory.']], ], ], );Ruby
session = client.beta.sessions.create( agent: agent_id, environment_id: environment_id ) client.beta.sessions.events.send_( session.id, events: [ { type: :"user.message", content: [{type: :text, text: 'Write the output of "uname -a" to hello.txt in your working directory.'}] } ] )会话会在环境的队列中等待,直到有 worker 认领它。如果没有连接任何 worker,会话将保持排队状态,而不会失败。
-
确认工具在您的主机上运行
在 worker 主机上,读取智能体写入的文件:
Linux
cat /workspace/hello.txtmacOS
cat ~/workspace/hello.txt该文件描述的是您自己主机的内核,因此智能体的工具调用是在那里运行的。要实时跟踪智能体的工作,请参阅会话事件流。
会话资源
自托管沙箱仅支持 memory_store 资源。在自托管环境上包含 file 或 github_repository 资源的会话会被拒绝,并返回 400 错误:
Environment env_... is a self-hosted environment. `resources` are not supported with self-hosted environments.
以自托管环境为目标的部署遵循相同的规则。要为会话提供其自己的输入文件,请参阅为会话暂存文件。
自托管沙箱与 MCP 隧道
自托管控制的是智能体代码在哪里运行。MCP 隧道控制的是 Anthropic 如何访问您网络中的 MCP 服务器。两者相互独立:
- 在 Anthropic 云沙箱中的会话可以通过隧道访问私有 MCP 服务器。例如,私有 MCP 服务器可能部署在您防火墙后的数据库或内部 API 前面。
- 自托管会话可以使用经隧道连接的 MCP 服务器或公共 MCP 服务器。
当您希望执行和工具访问都保留在您的边界内时,请同时使用两者。要跳过隧道,请将 MCP 服务器封装为自定义工具,由您的工作进程提供服务。
平台指南
这些页面介绍了如何在任何沙箱平台上构建工作进程。此外还提供以下特定平台的指南:
- AWS Lambda MicroVMs
- Blaxel
- Cloudflare
- Daytona
- E2B
- Fly.io
- GKE Agent Sandbox
- Modal
- Namespace
- Superserve
- Vercel
后续步骤
-
部署工作进程:运行 SDK 工作进程、通过 webhook 触发工作进程,或为每个会话提供独立的沙箱。
-
自托管沙箱中的记忆存储:准备主机、配置同步,并处理只读存储和冲突。
-
自定义工具和 MCP 服务器:从工作进程提供您自己的工具,包括来自您网络内 MCP 服务器的工具。
-
监控和故障排除:读取队列深度、干净地停止会话和工作进程,并修复常见故障。
-
工作进程参考:CLI 标志、环境变量、文件系统路径和 SDK 辅助选项。
-
安全模型:自托管沙箱环境的责任共担模型。
可用性
自托管沙箱在所有模型上可用。
API 支持
Managed Agents
- 可用性:可用
| 状态 | 云平台 | 模型 |
|---|---|---|
| 可用 | Claude API, Claude Platform on AWS, Claude Models on Google Cloud (Anthropic managed) | 所有模型 |
所需的 beta 请求头
Beta 请求头让您可以在实验性功能和新模型能力成为标准 API 的一部分之前访问它们。
managed-agents-2026-04-01
数据处理
| 项目 | 零数据保留 | HIPAA |
|---|---|---|
| 状态 | 不具备资格 | 不具备资格 |
| 详细信息 | 会话是有状态的资源;对话记录会一直保留,直到您将其删除。适用于所有 Managed Agents 子功能,包括自托管沙箱。 | 适用于所有 Managed Agents 子功能,包括自托管沙箱。 |
适用的端点:
/v1/agents/v1/sessions/v1/environments