扩展托管代理:将“大脑”与“手”解耦 | Anthropic

作者:Anthropic Engineering | 日期:2026年4月9日

随着模型改进,harness 会编码那些会变陈旧的假设。Managed Agents 是 Anthropic 的托管服务,用于长时程代理工作,它围绕一些即使 harness 发生变化也能保持稳定的接口构建。

工程博客中一个持续的话题,是如何构建有效的代理,以及如何为长时间运行的工作设计 harness。这项工作中的一个共同线索是,harness 会编码关于 Claude 仅靠自己做不到什么的假设。不过,这些假设需要被频繁质疑,因为随着模型改进,它们可能会变得陈旧。

仅举一个例子,在之前的工作中,他们发现 Claude Sonnet 4.5 会在感知到其上下文限制临近时过早结束任务,这种行为有时被称为“context anxiety”。Anthropic 通过在 harness 中加入上下文重置来解决这个问题。但当他们在 Claude Opus 4.5 上使用相同的 harness 时,他们发现这种行为消失了。这些重置变成了额外负担。

Anthropic 预计 harness 会继续演化。因此他们构建了 Managed Agents:Claude Platform 上的一项托管服务,通过一小组接口代表你运行长时程代理,这些接口旨在比任何特定实现存续得更久,包括他们今天运行的那些实现。

构建 Managed Agents 意味着要解决计算中的一个老问题:如何为“尚未被想到的程序”设计系统。数十年前,操作系统通过将硬件虚拟化为抽象解决了这个问题,例如进程和文件,这些抽象对于那些尚不存在的程序来说也足够通用。这些抽象比硬件本身存在得更久。read() 命令并不关心它访问的是 20 世纪 70 年代的磁盘组还是现代 SSD。

上层的抽象保持稳定,而底层的实现可以自由变化。

Managed Agents 采用同样的模式。Anthropic 将代理的组成部分虚拟化了:session,记录一切已发生内容的追加式日志;harness,调用 Claude 并将 Claude 的工具调用路由到相关基础设施的循环;以及 sandbox,Claude 可以在其中运行代码并编辑文件的执行环境。这使得每一部分的实现都可以在不干扰其他部分的情况下被替换。他们对这些接口的形态有明确主张,但不对其背后的具体运行内容设限。

不要收养宠物

Anthropic 一开始把所有代理组件都放进一个容器中,这意味着 session、agent harness 和 sandbox 共享同一个环境。这种方法有一些好处,包括文件编辑是直接系统调用,也不需要设计服务边界。

但由于把一切都耦合进一个容器中,他们遇到了一个老式基础设施问题:他们收养了一个宠物。在宠物与牲畜的类比中,宠物是一个有名字、需要人工照料、且不能承受失去的个体,而牲畜则是可互换的。就他们而言,服务器变成了那个宠物;如果某个容器失败,session 就会丢失。如果某个容器无响应,他们就不得不把它护理恢复。

护理这些容器意味着调试那些无响应、卡住的 session。他们唯一能看到的是 WebSocket 事件流,但它无法告诉他们故障出在哪里,这意味着 harness 中的 bug、事件流中的丢包、或容器离线,表现出来都一样。为了弄清哪里出了问题,工程师不得不进入容器打开 shell,但由于该容器通常也包含用户数据,这实际上意味着他们缺乏调试能力。

第二个问题是,harness 假定 Claude 正在处理的内容与它一起位于容器中。当客户要求 Anthropic 把 Claude 连接到他们的虚拟私有云时,他们必须要么与 Anthropic 的网络建立对等连接,要么在他们自己的环境中运行 Anthropic 的 harness。一个嵌入在 harness 中的假设,在他们想把它连接到不同基础设施时就成了问题。

将大脑与手解耦

他们最终得到的解决方案,是将他们所认为的“大脑”(Claude 和它的 harness)与“手”(执行动作的 sandbox 和工具)以及“session”(session 事件日志)解耦。每一部分都变成了一个对其他部分假设很少的接口,并且每一部分都可以独立失败或被替换。

Harness 离开了容器。将大脑与手解耦,意味着 harness 不再驻留在容器内部。它像调用其他任何工具一样调用容器:execute(name, input) -> string。容器变成了牲畜。如果容器死掉,harness 就把这个故障作为一次工具调用错误捕获,并将其传回给 Claude。如果 Claude 决定重试,就可以用一个标准配方重新初始化一个新容器:provision({resources})

他们不再需要把失败的容器护理恢复。

从 harness 故障中恢复。Harness 本身也变成了牲畜。由于 session 日志位于 harness 之外,harness 中没有任何东西需要在崩溃中幸存。当某个 harness 失败时,可以用 wake(sessionId) 启动一个新的,使用 getSession(id) 取回事件日志,并从最后一个事件恢复。在代理循环期间,harness 通过 emitEvent(id, event) 将内容写入 session,以保留事件的持久记录。

安全边界。 在耦合式设计中,Claude 生成的任何不受信任代码都与凭证运行在同一个容器中,因此一次提示注入只需要说服 Claude 去读取它自己的环境。一旦攻击者拿到这些令牌,他们就可以生成新的、不受限制的 session,并把工作委派给它们。缩小作用域显然是一种缓解措施,但这编码了一个关于 Claude 拿着受限令牌做不了什么的假设,而 Claude 正变得越来越聪明。

结构性的修复办法,是确保这些令牌永远无法从 Claude 生成代码运行所在的 sandbox 中被触达。

Anthropic 使用了两种模式来做到这一点。认证信息可以与资源打包在一起,或保存在 sandbox 外部的一个保险库中。对于 Git,他们使用每个仓库的访问令牌在 sandbox 初始化期间克隆仓库,并把它接入本地 git remote。Git push 和 pull 可以在 sandbox 内部工作,而代理本身从不处理该令牌。对于自定义工具,他们支持 MCP,并将 OAuth 令牌保存在安全保险库中。

Claude 通过一个专用代理调用 MCP 工具;这个代理接收与 session 关联的令牌。然后该代理可以从保险库中提取相应的凭证,并向外部服务发起调用。Harness 永远不会接触到任何凭证。

Session 不是 Claude 的上下文窗口

长时程任务经常会超出 Claude 的上下文窗口长度,而解决这一问题的标准方式都涉及对保留什么作出不可逆的决定。Anthropic 在有关上下文工程的先前工作中探索了这些技术。例如,compaction 让 Claude 可以保存其上下文窗口的摘要,而 memory 工具让 Claude 可以把上下文写入文件,从而支持跨 session 的学习。

这可以与上下文裁剪搭配使用,后者会选择性移除旧的工具结果或 thinking blocks 等 token。

但对上下文进行选择性保留或丢弃的不可逆决定会导致失败。很难知道未来的轮次会需要哪些 token。如果消息经过 compaction 步骤转换,harness 会把已压缩的消息从 Claude 的上下文窗口中移除,而只有在它们被存储下来时,这些消息才可以恢复。先前的工作已经探索了通过将上下文存储为一个位于上下文窗口之外的对象来解决这个问题的方法。

例如,上下文可以是 REPL 中的一个对象,LLM 通过编写代码来访问它,并对它进行过滤或切片。

在 Managed Agents 中,session 提供了同样的好处,作为一个位于 Claude 上下文窗口之外的上下文对象而存在。但它不是存储在 sandbox 或 REPL 内,而是持久地存储在 session 日志中。接口 getEvents() 允许大脑通过选择事件流的位置切片来查询上下文。

这个接口可以被灵活使用,让大脑从它上次停止读取的地方继续,在某个特定时刻之前回退几个事件以查看前因,或者在某个特定动作之前重新读取上下文。

任何取回的事件也都可以在传入 Claude 的上下文窗口之前,先在 harness 中进行转换。这些转换可以是 harness 所编码的任何内容,包括为实现较高 prompt cache 命中率而进行的上下文组织,以及上下文工程。Anthropic 将 session 中可恢复的上下文存储与 harness 中任意的上下文管理分离开来,因为他们无法预测未来模型会需要什么具体的上下文工程。

这些接口将上下文管理推入 harness 中,而只保证 session 是持久的并且可供查询。

多个大脑,多只手

多个大脑。将大脑与手解耦,解决了 Anthropic 最早的一项客户抱怨。当团队希望 Claude 处理位于它们自己 VPC 中的资源时,唯一的路径曾经是将它们的网络与 Anthropic 的网络建立对等连接,因为承载 harness 的容器假定所有资源都与它相邻。一旦 harness 不再位于容器中,这个假设就消失了。同样的变化还带来了性能收益。

当他们最初把大脑放进容器中时,这意味着有多少个大脑就需要多少个容器。对于每个大脑,在该容器被配置完成之前,推理都无法开始;每个 session 都必须预先支付完整的容器设置成本。每个 session,即使是那些永远不会接触 sandbox 的 session,也必须克隆仓库、启动进程,并从他们的服务器拉取待处理事件。

这段空耗时间体现在 time-to-first-token(TTFT)中,它衡量的是一个 session 从接收工作到产出第一个响应 token 之间等待了多久。TTFT 是用户感受最直接的延迟。

将大脑与手解耦,意味着容器只有在需要时,才由大脑通过一次工具调用 execute(name, input) -> string 来配置。因此,一个一开始并不需要容器的 session 就无需等待容器。只要编排层从 session 日志中取出待处理事件,推理就可以开始。采用这种架构后,他们的 p50 TTFT 大约下降了 60%,p95 则下降了 90% 以上。

扩展到多个大脑,仅仅意味着启动多个无状态 harness,并且只在需要时把它们连接到手。

多只手。Anthropic 也希望能够把每个大脑连接到多只手。在实践中,这意味着 Claude 必须对多个执行环境进行推理,并决定把工作发送到哪里,这比在单一 shell 中操作是一个更难的认知任务。他们一开始把大脑放在单个容器中,是因为早期模型还做不到这一点。随着智能提升,单个容器反而成了限制:当这个容器失败时,他们会丢失大脑正在伸向的每一只手的状态。

将大脑与手解耦,使每一只手都成为一个工具,execute(name, input) -> string:输入一个名称和参数,返回一个字符串。这个接口支持任何自定义工具、任何 MCP 服务器,以及 Anthropic 自己的工具。Harness 不知道 sandbox 是一个容器、一部手机,还是一个 Pokemon 模拟器。而且由于没有任何一只手耦合到任何一个大脑上,大脑之间可以彼此传递手。

结论

Anthropic 面对的挑战是一个老问题:如何为“尚未被想到的程序”设计系统。操作系统之所以能持续数十年,是因为它们把硬件虚拟化为对那些尚不存在的程序也足够通用的抽象。借助 Managed Agents,他们试图设计一个能够容纳未来围绕 Claude 构建的 harness、sandbox 或其他组件的系统。

Managed Agents 是一种同样精神下的 meta-harness,它并不对 Claude 在未来需要什么特定 harness 抱有成见。相反,它是一个拥有通用接口的系统,允许许多不同的 harness。举例来说,Claude Code 是一个优秀的 harness,Anthropic 在各种任务中广泛使用它。他们也已经表明,面向任务的 agent harness 在狭窄领域中表现出色。Managed Agents 能够容纳这些中的任何一种,并随着时间推移匹配 Claude 的智能。

Meta-harness 设计意味着要对围绕 Claude 的接口保持明确主张:Anthropic 预计 Claude 将需要操作状态(session)和执行计算(sandbox)的能力。他们也预计 Claude 将需要扩展到多个大脑和多只手。他们将这些接口设计为能够在长时间范围内可靠且安全地运行。但他们并不对 Claude 将需要的大脑和手的数量或位置作出任何假设。

https://www.anthropic.com/engineering/managed-agents

如果觉得内容不错,欢迎你点一下「在看」,或是将文章分享给其他有需要的人^^

相关好文推荐:

一种快速判别产品AI含量的黄金指标,帮你远离披着AI外皮的传统软件公司

飞书会取代微信吗?

AI 时代的软件与软件公司应该长什么样?

引入嵌套学习(Nested Learning):一种用于持续学习的全新机器学习范式

如何构建多智能体研究系统

0条留言

留言