Managed Agents:脑手解耦
Anthropic 工程博客:把"脑"(harness + Claude)与"手"(sandbox / 工具)及 session 解耦——接口稳定,实现可换。
开篇:写进 harness 的假设会过期
以下来自 Anthropic 工程博客(作者 Lance Martin、Gabe Cemaj、Michael Cohen)。先看一个真实教训:
Anthropic 发现 Claude Sonnet 4.5 有个毛病叫 "context anxiety"——感觉到上下文快用完了,就提前收尾、不把任务做完。于是他们在 harness 里加了 context reset 来修。
结果换到 Claude Opus 4.5 上一跑:这个毛病消失了,reset 变成了死重——白占地方、毫无用处。
为什么解耦:操作系统早就想明白了
Anthropic 的类比是操作系统:process(进程)和 file(文件)这些抽象,比它们底下的硬件活得久得多——硬件换了好几代,接口没变。
Managed Agents 就是把 agent"虚拟化"成三个接口:
- session:append-only 的事件日志;
- harness:调用 Claude、路由 tool call 的 loop;
- sandbox:执行环境。
操作系统不直接指挥硬盘磁头,它靠"文件"这个抽象;Managed Agents 不直接指挥容器,它靠 session / harness / sandbox 三个接口。底下实现随便换,上面接口不动。
Anthropic 最初把 session、harness、sandbox 全塞进同一个容器,结果踩中了基础设施的老坑——养宠物(pet vs cattle):
- 容器一挂,session 就丢了;
- 只能经 WebSocket 看事件流,分不清到底是哪一层坏了;
- 修容器还得开 shell 进一个装着用户数据的容器里动手。
宠物是取名手养、死不起的个体;牛群(cattle)是可替换的。你的服务器成了宠物,就是架构警报。
三者职责:脑、手、账本
| 角色 | 是什么 | 干什么 |
|---|---|---|
| 脑 | harness + Claude | 跑 loop:调模型、做决策、把 tool call 路由出去 |
| 手 | sandbox / 工具 | 执行环境:只管干活,不决策 |
| 账本 | session(事件日志) | append-only 的 durable 记录,不属于脑也不属于手 |
解耦的关键动作:harness 搬出容器。容器不再是"家",而是被当成普通工具来调用——容器死了,harness 收到的是一个 tool-call error,转手交给 Claude 决定要不要重试。
接口语言:五个调用讲清一切
解耦之后,各层之间只用几个接口说话:
execute(name, input) → string:调容器就像调普通工具——名字和输入进去,一个字符串回来;provision({resources}):容器死了?按标准配方重建一个,不用"抢救";wake(sessionId)+getSession(id):harness 挂了?新 harness 醒来,从 session 日志拿回事件,从最后一个事件继续——harness 自己也成了 cattle,崩了就换,不用抢救;emitEvent(id, event):loop 跑着的时候,harness 往 session 里写事件,留下 durable 记录;getEvents():脑按位置切片"审问"事件流——可以从上次读到的地方继续,可以倒回几步看前因,也可以重读某个动作之前的上下文;harness 还能在交给 Claude 之前做 transform(比如按 cache 友好的方式组织)。
安全边界:token 永不进 sandbox
解耦顺手解决了一个安全难题——token 永不进 sandbox:
- Git:用仓库 token 在初始化时把代码 clone 进去,之后 agent 的 push / pull 全程碰不到 token;
- MCP 的 OAuth token:放在 vault 里,Claude 经专用 proxy 调用;
- harness 感知不到任何 credential——它只负责调度,连钥匙长什么样都不知道。
Session ≠ 上下文窗口
容易混淆的一对概念,原文划了条线:
- 上下文窗口:compaction、memory、trimming 全是不可逆的取舍——压掉的东西就没了;
- session:窗口之外的可恢复的 context object,durable 地存在 session 日志里,丢了能找回来、能切片重读。
上下文窗口像黑板:擦了就没了。session 像课堂录像:随时可以回放、切片、倒带。
规模效应:Many brains,Many hands
解耦前,每个 session 都要预付容器成本(clone 仓库、启动进程……),不管它当下需不需要容器。解耦后,容器由脑按需 execute 拉起:
- 不需要容器的 session 不用等容器,推理在编排层从 session 日志拉到 pending 事件就能开始;
- 结果:p50 TTFT 降约 60%,p95 降超 90%(TTFT = time-to-first-token,用户最能感知到的延迟)。
Many hands:每只手都是 execute(name, input) → string——容器、手机、宝可梦模拟器无差别;而且手不绑定脑,brains 之间可以互相传递 hands。
结论:Managed Agents 是 meta-harness
原文的收束:Managed Agents 是一个 meta-harness——
- 对接口有主张:state / session、compute / sandbox、多 brain 多 hand、长时可靠;
- 对具体 harness 不预设:你怎么写 loop、用什么策略,那是你的事。
| 普通 harness | meta-harness(Managed Agents) | |
|---|---|---|
| 假设放哪 | 写死在实现里(如 context reset),模型一换就过期 | 只规定接口,实现可换 |
| 崩了怎么办 | 抢救容器 / 丢 session | 换一个新的,从 session 日志恢复 |
| 扩展方式 | 每个 session 预付容器成本 | 按需 provision,p50 TTFT 降 60% |
| 安全 | credential 和执行环境混在一起 | token 永不进 sandbox |
术语翻卡:点卡片看解释
自测一下:点问题展开参考答案
它是为 Sonnet 4.5 的 context anxiety(临近上下文上限提前收尾)写的补丁;换代后这个行为消失了,写死在 harness 里的假设过期,补丁成了累赘。
把 session、harness、sandbox 全塞进同一个容器:容器一挂 session 就丢,只能经 WebSocket 看事件流分不清哪层坏,修还得进装着用户数据的容器开 shell。
session 日志在 harness 之外;新 harness 用 wake(sessionId) 醒来,再用 getSession(id) 拿回事件日志,从最后一个事件继续——harness 自己也是 cattle。
Git 用仓库 token 在初始化时 clone,之后 agent 碰不到 token;MCP OAuth token 放 vault,Claude 经专用 proxy 调用;harness 感知不到任何 credential。