托管智能体入门:循环、沙箱和会话都交给 Anthropic,你只管发事件、收事件
Claude Managed Agents 把智能体的循环、工具执行和会话状态放到 Anthropic 那边运行。本文按官方文档整理它的四个概念、最小流程、工具和权限策略、事件怎么收发,以及从自己写的循环迁过来要改什么。中转站没有这组接口,全文未实测。
本文根据公开分享整理,本站尚未实测。操作前请对照文末的原始来源。
本页目录(11 节)
这篇教程解决一个问题:想让 Claude 自己跑几十分钟到几小时的任务,读文件、跑命令、上网查资料,但不想自己写循环、搭沙箱、存对话历史,有没有现成的?
有,叫 Claude Managed Agents(托管智能体)。它是 beta 功能,本文连同后面两篇把它的 37 页文档整理成三篇。
先说清楚:全文按官方文档整理,没有实测。 这组接口只在官方平台上有。本站在酷站AI 中转站上探测了智能体、环境、会话、保险库、记忆库、部署这六个接口,全部返回 404。文中的示例代码来自官方文档,本站没有运行过。
一、它和消息接口、Agent SDK 的区别
这个系列前面十几篇讲的都是消息接口:你发一个请求,模型回一个响应,循环、工具执行、历史都归你管。托管智能体是另一条路:
| 消息接口 | Agent SDK | 托管智能体 | |
|---|---|---|---|
| 循环谁来跑 | 你写 | SDK 替你跑,在你的进程里 | Anthropic 那边跑 |
| 工具在哪执行 | 你的环境 | 你的机器,对着你的文件系统 | Anthropic 托管的沙箱(也可以换成你自己的) |
| 对话历史存在哪 | 你自己存,每次重发 | SDK 管,在你这边 | 服务端存着 |
| 适合 | 要自己控制每一步 | 要一个现成的智能体,跑在自己的机器上 | 跑得久、异步、不想管基础设施 |
官方的概括:消息接口适合“自己写循环、要细粒度控制”,托管智能体适合“长时间运行的任务和异步的工作”。缓存、上下文压缩这些优化,托管智能体内置了。
Agent SDK 见《第一个智能体》。
二、四个概念和一个最小的流程
| 概念 | 是什么 |
|---|---|
| 智能体(agent) | 一份配置:模型、系统提示词、工具、MCP 服务器、skill。建一次,反复用 |
| 环境(environment) | 会话在哪里运行的配置:Anthropic 托管的云端沙箱,或你自己机器上的沙箱 |
| 会话(session) | 智能体在某个环境里的一次运行,做一件具体的事 |
| 事件(event) | 你的程序和智能体之间来回传的消息:用户的话、工具结果、状态变化 |
官方快速上手里的完整流程是四步:
from anthropic import Anthropic
client = Anthropic()
# 1. 建智能体(只建一次,记下 ID)
agent = client.beta.agents.create(
name="Coding Assistant",
model="claude-opus-5-5",
system="You are a helpful coding assistant. Write clean, well-documented code.",
tools=[{"type": "agent_toolset_20260401"}], # 整套内置工具
)
# 2. 建环境(也只建一次)
environment = client.beta.environments.create(
name="quickstart-env",
config={"type": "cloud",
"networking": {"type": "limited", "allow_package_managers": True}},
)
# 3. 建会话
session = client.beta.sessions.create(agent=agent.id, environment_id=environment.id)
# 4. 先打开事件流,再发消息,然后处理收到的事件
with client.beta.sessions.events.stream(session.id) as stream:
client.beta.sessions.events.send(session.id, events=[
{"type": "user.message",
"content": [{"type": "text", "text": "写一个脚本,生成前 20 个斐波那契数,存到 fibonacci.txt"}]},
])
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "agent.tool_use":
print(f"\n[调用工具:{event.name}]")
case "session.status_idle":
print("\n智能体做完了。")
break
发出消息之后,服务端做的事是:按环境配置准备一个沙箱;跑智能体的循环,由 Claude 决定用哪些工具;工具在沙箱里执行;过程通过事件流实时发给你;没事可做时发一个 session.status_idle。
几件上手时要知道的事:
- 所有接口都要带 beta 头
managed-agents-2026-04-01,SDK 会自动加。 - 所有 API 账号默认都有权限。
- 不想先写代码,可以在控制台里用图形界面配智能体、直接开一个测试会话看事件流,满意了再把智能体和环境的 ID 抄进代码。界面会显示等价的接口请求。
- 在 Claude Code 里运行
/claude-api managed-agents-onboard,有一个问答式的引导。
三、定义智能体
智能体的字段:
| 字段 | 说明 |
|---|---|
name |
必填 |
model |
必填。Claude 4.5 及之后的模型。可以写模型名,也可以写成对象,对象里还能设 speed(快速模式)、effort、inference_geo(推理所在的地区) |
system |
系统提示词,定义行为和人设。具体要做的事放在用户消息里,不放这里 |
tools |
内置工具集、MCP 工具、自定义工具 |
mcp_servers |
要连的 MCP 服务器 |
skills |
挂上的 skill |
multiagent |
让它把活交给别的智能体,见本组第三篇 |
description、metadata |
说明和你自己用的标签 |
智能体是有版本的。 每次更新只要改动了配置,版本号就加一。围绕版本有几条规则:
- 更新时可以带上当前的
version。和服务端的不一致就返回 409,这样两个人同时改不会互相覆盖。不带就是无条件覆盖,后写的赢。 - 没写的字段保持原样。数组类的字段(
tools、mcp_servers、skills)是整体替换。metadata按键合并,把某个键设成null是删除它。 - 更新后和当前版本没有差别,就不产生新版本。
- 归档不可逆。 归档后智能体只读,不能再被新的会话引用,已有的会话照常运行。
建会话时,传智能体的 ID 用的是最新版本;想控制上线节奏,就传一个带版本号的对象,把会话钉在某个版本上。
单个会话可以临时改配置,不动智能体本身,也不产生新版本。可以覆盖的有 model、system、tools、mcp_servers、skills,每个字段三种写法:不写就继承;写成 null 或空数组就清空;写了值就整体替换(不会和智能体的配置合并,所以覆盖 tools 时要把这个会话需要的工具列全)。model 不能清空。
四、工具
内置的工具集
在 tools 里写 {"type": "agent_toolset_20260401"},就打开了整套内置工具,默认全部启用:
| 工具 | 名字 | 做什么 |
|---|---|---|
| Bash | bash |
在一个 shell 会话里执行命令 |
| 读 | read |
读沙箱里的文件 |
| 写 | write |
写文件 |
| 编辑 | edit |
按字符串替换改文件 |
| Glob | glob |
按通配符找文件 |
| Grep | grep |
用正则搜文本 |
| 抓取网页 | web_fetch |
取一个网址的内容 |
| 联网搜索 | web_search |
搜索 |
用 configs 关掉个别工具,或者反过来先全关、只开需要的:
tools = [{
"type": "agent_toolset_20260401",
"default_config": {"enabled": False}, # 先全关
"configs": [{"name": "read", "enabled": True}, # 只开这两个
{"name": "grep", "enabled": True}],
}]
工具的输出超过 10 万个字符(约 2.5 万 token)时,会被自动写进沙箱里的一个文件,模型拿到的是截断的预览和文件路径。
限制它能上哪些网站
web_search 和 web_fetch 的配置里各自可以放一个域名清单:allowed_domains(只许这些)或 blocked_domains(不许这些),二选一,每个清单 1 到 64 个域名。web_fetch 还可以设 max_content_tokens,web_search 可以设 user_location。
要留意:这两个工具跑在 Anthropic 的服务器上,不在沙箱里。 所以沙箱的网络限制本来管不到它们;但如果环境用的是 limited 网络,环境的 allowed_hosts 也会作用到这两个工具上。被清单拦下的搜索结果直接不出现,被拦下的抓取返回一个出错的工具结果。
自定义工具
和消息接口里自己定义的工具是一回事:你给出名字、说明和参数的 schema,Claude 决定什么时候调,由你的程序执行,再把结果送回会话。
{"type": "custom",
"name": "get_weather",
"description": "Get current weather for a location",
"input_schema": {"type": "object",
"properties": {"location": {"type": "string", "description": "City name"}},
"required": ["location"]}}
名字不能以 mcp__ 或 ant__ 开头,也不能和内置工具重名。说明怎么写好,和《工具调用入门》第三节讲的完全一样。
五、权限策略:哪些工具调用要先问你
在服务端执行的工具(内置工具集和 MCP 工具)受权限策略管:
| 策略 | 行为 |
|---|---|
always_allow |
直接执行,不问 |
always_ask |
会话暂停,等你批准 |
auto |
服务端逐个评估每次调用:放行、拒绝,或者拿不准时暂停问你 |
默认值要记住:内置工具集是 always_allow,MCP 工具集是 always_ask。 也就是说,不做任何配置时,bash 命令是不经确认直接跑的。
可以给整个工具集设一个默认策略,再对个别工具单独设。下面是“别的都放行,bash 每次都问”:
tools = [{
"type": "agent_toolset_20260401",
"default_config": {"permission_policy": {"type": "always_allow"}},
"configs": [{"name": "bash", "permission_policy": {"type": "always_ask"}}],
}]
关于 auto,文档有几句话说得很直接:
- 服务端判断时看的是工具、这次调用的参数和会话到此为止的内容,所以同一个工具的两次调用可能结果不同。
- 被它判成高风险而拒绝的调用,你的程序不能推翻。
- 你在用户消息里说的话算作你的意图,可以让它放行原本会拒绝的调用。工具结果、抓来的网页、MCP 服务器的返回里的话不算。
auto不是人工把关。 它判断为安全的调用会在任何人看到之前就执行,后果可能无法撤销。必须有人先看的,用always_ask。
权限策略管不到自定义工具。自定义工具本来就是你的程序在执行,要不要执行由你的代码决定。
六、事件:发什么,收什么
和智能体的全部交流都是事件。事件的类型名是“领域.动作”的形式。
你发的:
| 事件 | 用途 |
|---|---|
user.message |
给它派活,或者接着聊 |
user.interrupt |
打断正在做的事 |
user.custom_tool_result |
回自定义工具的结果 |
user.tool_confirmation |
批准或拒绝一次需要确认的工具调用 |
user.define_outcome |
定义一个要达成的成果,见下一篇 |
system.message |
追加系统级的上下文(要模型支持) |
你收的,常用的几种:
| 事件 | 含义 |
|---|---|
agent.message |
智能体说的话 |
agent.thinking |
它在思考。只是进度信号,不带思考内容 |
agent.tool_use、agent.tool_result |
调了内置工具,以及结果 |
agent.mcp_tool_use、agent.mcp_tool_result |
调了 MCP 工具,以及结果 |
agent.custom_tool_use |
调了你的自定义工具,等你回结果 |
session.status_running、session.status_idle |
开始干活、停下来等输入 |
session.error |
出错了,带一个是否在重试的状态 |
span.model_request_end |
一次模型请求结束,带 token 用量 |
三条容易错的规则
先开流,再发消息。 事件流只送它打开之后产生的事件,先发后开会漏。
停下来不一定是做完了。 session.status_idle 里有一个 stop_reason,要看它的类型:
stop_reason.type |
为什么停 | 你要做什么 |
|---|---|---|
end_turn |
这一轮做完了,或者被你打断了 | 有新的活就再发 user.message |
requires_action |
有工具调用在等你:自定义工具的结果,或者一次确认 | 逐个回应 |
budget_reached |
花费到了这个会话的预算 | 调高或去掉预算 |
断线重连要对历史。 重连的做法是:开一个新流,把完整的事件历史列出来、记下见过的事件 ID,再跟着新流走,跳过已经见过的。
回应等着你的工具调用
自定义工具被调用时,收到 agent.custom_tool_use,执行完用 user.custom_tool_result 回:
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
match event.type:
case "agent.custom_tool_use":
result = call_tool(event.name, event.input) # 你自己的执行逻辑
client.beta.sessions.events.send(session.id, events=[
{"type": "user.custom_tool_result",
"custom_tool_use_id": event.id,
"content": [{"type": "text", "text": result}]},
])
case "session.status_idle":
if event.stop_reason and event.stop_reason.type == "end_turn":
break
需要确认的调用,等会话停在 requires_action 时,stop_reason.event_ids 里就是要回应的那几个事件。对每一个发 user.tool_confirmation,result 写 allow 或 deny,拒绝时可以用 deny_message 说明原因,这句话会交给智能体。会话会一直等下去,不会超时。
打断和改方向
发一个 user.interrupt,紧跟着再发一个 user.message 说新的要求。正在生成的模型回复会立刻停,正在跑的工具调用可能要多等一会儿。被打断的那一轮同样以 end_turn 结束。
边生成边显示
默认情况下,agent.message 是整条攒好了才发的。要做“打字机”效果,打开事件流时加上 event_deltas[] 参数,就能在整条消息到达之前收到增量的预览。文档强调:预览只是显示上的辅助,最后那条完整的 agent.message 才是准的;忽略预览的客户端拿到的仍然是完整正确的事件流。预览事件不进历史。
七、会话的状态和寿命
| 状态 | 含义 |
|---|---|
idle |
在等输入。刚建好、还没发消息的会话就是这个状态 |
running |
正在干活 |
rescheduling |
遇到临时错误,在自动重试 |
terminated |
结束了:出了无法恢复的错误,或者被归档 |
正常做完的会话是回到 idle,不是 terminated。
- 会话可以隔很久再接着用。 对话历史一直留着,除非你删除。会话空闲时,沙箱会被存一个检查点,文件、装过的包都在。
- 沙箱的状态只保留 30 天,从沙箱创建算起,期间有没有活动都不延长。 过了 30 天再继续,拿到的是一个全新的沙箱。重要的产出让智能体写到输出目录里,及时取走。
- 会话建好以后,只能改它的
tools和mcp_servers,而且会话必须是空闲的。模型、系统提示词、skill 要在建会话时用覆盖的办法定下来。 - 归档:不再接收新事件,历史保留。删除:会话记录、事件和沙箱一起永久删除,会话自己产生的文件也一起删,你通过 Files API 上传的文件不受影响。正在运行的会话要先打断,等它空闲了才能归档或删除。
建会话时可以用 initial_events 把第一条消息一起带上,省一次调用。
八、限流、数据和命名
- 创建类的接口每个组织每分钟 300 次,读取类的每分钟 1,200 次。组织原有的消费上限和按档位的限流照样生效。
- 不在零数据保留和 HIPAA 的范围内。 它天生有状态:对话历史、沙箱状态、产出都存在服务端。你可以随时删除会话和上传的文件。
- 在自己的产品里提到它时,可以叫“Claude Agent”或“由 Claude 驱动的某某”,不能叫“Claude Code”或“Claude Cowork”,界面也不能做得像这两个产品。
会话的费用由三部分组成:模型的 token、联网搜索的次数、会话的运行时长。怎么给一个会话设花费上限,见下一篇。
九、从自己写的循环或 Agent SDK 迁过来
原来用消息接口自己写循环的,大部分代码可以删掉:
| 以前 | 以后 |
|---|---|
| 自己维护对话历史,每轮重发 | 历史在服务端,你只发事件、收事件 |
| 遍历工具调用、逐个执行、把结果拼回去 | 内置工具在沙箱里自动执行,你只处理自定义工具 |
| 自己准备跑代码的沙箱 | 用会话的沙箱 |
| 自己判断循环什么时候结束 | 等 session.status_idle |
原来用 Agent SDK 的,概念是对得上的,区别在于在哪里运行:
| Agent SDK | 托管智能体 |
|---|---|
| 每次运行构造一份选项 | 建一次智能体,服务端保存并带版本 |
query() 或客户端对象 |
建会话,然后收发事件 |
| 用装饰器定义的工具,SDK 自动分发 | 声明成自定义工具,你的程序处理事件并回结果 |
| 内置工具对着你的文件系统 | 同样的工具,对着沙箱里的 /workspace |
| 指向本地目录 | 把文件上传或把仓库挂载成会话的资源 |
系统提示词加 CLAUDE.md 的层级 |
智能体上的一个 system 字符串 |
| 权限模式和回调 | 每个工具的权限策略,加确认事件 |
有几样 SDK 自动做的事,迁过来以后归你的程序:
| SDK 里的功能 | 在托管智能体里怎么办 |
|---|---|
| 计划模式 | 先跑一个只做计划的会话,再开第二个会话执行 |
| 输出风格、斜杠命令 | 在发消息之前、收到回复之后,由你的程序处理 |
| 工具调用前后的钩子 | 自定义工具本来就经过你的程序;内置工具用 always_ask 逐个审 |
| 最大轮数 | 自己数 |
这组文章接下来讲什么
- 第二篇:环境和沙箱、文件和代码仓库、凭据、MCP、skill、记忆、成果、预算、观测、webhook、定时运行。
- 第三篇:多个智能体协作,以及把沙箱放在自己的机器上。
没有实测的部分
- 全文没有实测。 托管智能体只在官方平台上有,本站用的中转站对这组接口返回 404。
- 示例代码来自官方文档,本站没有运行过,只把其中的提示词换成了中文、删掉了部分输出语句。
- 价格、限流的数字和支持的模型以官方文档为准,这是 beta 功能,行为可能在版本之间调整。
- 控制台的图形界面没有看过,是按文档的描述写的。
来源
- Claude Managed Agents overview(Claude 开发平台文档)
- Get started with Claude Managed Agents(Claude 开发平台文档)
- Build in Console(Claude 开发平台文档)
- Define your agent(Claude 开发平台文档)
- Start a session(Claude 开发平台文档)
- Session operations(Claude 开发平台文档)
- Session event stream(Claude 开发平台文档)
- Preview responses with event deltas(Claude 开发平台文档)
- Tools(Claude 开发平台文档)
- Restrict web search and web fetch domains(Claude 开发平台文档)
- Permission policies(Claude 开发平台文档)
- Reference(Claude 开发平台文档)
- Migration(Claude 开发平台文档)