跳到正文
Anthropic Engineering·· 2026-04-08精选AI 评分87

Claude Managed Agents 如何通过解耦“大脑”与“双手”实现扩展

Scaling Managed Agents: Decoupling the brain from the hands

AI 导读

Anthropic 详解 Claude Managed Agents 的架构,将 Claude 及其执行框架、沙箱与工具、会话日志解耦,使各组件能够独立替换或故障恢复。持久化会话日志支持按需读取历史事件,凭证隔离在沙箱之外,执行容器也改为按需创建。采用这一架构后,首 token 延迟(TTFT)的 p50 下降约 60%,p95 下降超过 90%。

推荐理由

将会话持久化、智能体执行循环与沙箱拆成独立接口,为长任务系统提供了可迁移的设计方法,使模型演进不必牵动全部基础设施。

正文 · AI 翻译

请按照我们的文档开始使用 Claude Managed Agents。

工程博客上持续探讨的一个主题是如何构建有效的智能体,以及如何为长时间运行的工作设计执行框架。这些工作有一个共同点:执行框架编码了对 Claude 无法独立完成哪些事情的假设。然而,这些假设需要经常重新审视,因为随着模型改进,它们可能会过时。

举个例子,在之前的工作中,我们发现,Claude Sonnet 4.5 感觉到上下文限制即将到来时,会过早地结束任务——这种行为有时被称为“上下文焦虑”。我们通过在执行框架中添加上下文重置来解决这个问题。但当我们在 Claude Opus 4.5 上使用同一执行框架时,发现这种行为已经消失了。这些重置变成了无用的负担。

我们预计执行框架会持续演进。因此,我们构建了 Managed Agents:Claude Platform 中的一项托管服务,通过一小组旨在超越任何特定实现(包括我们今天运行的实现)的接口,代表你运行长时程智能体。

构建 Managed Agents 意味着要解决计算领域的一个老问题:如何为“尚未有人想到的程序”设计系统。几十年前,操作系统通过将硬件虚拟化为抽象概念——进程、文件——解决了这个问题;这些抽象足够通用,能够支持尚不存在的程序。抽象概念比硬件更持久。read()命令并不关心它访问的是 20 世纪 70 年代的磁盘组,还是现代 SSD。上层的抽象保持稳定,而底层的实现可以自由更换。

Managed Agents 遵循相同的模式。我们将智能体的组件虚拟化:会话(记录所有已发生事件的只追加日志)、执行框架(调用 Claude 并将 Claude 的工具调用路由到相关基础设施的循环),以及沙箱(Claude 可以在其中运行代码和编辑文件的执行环境)。这样就可以替换每个组件的实现,而不影响其他组件。我们对这些接口的形式有明确主张,但不限定它们背后运行的内容。

别养“宠物”

我们最初将所有智能体组件放入单个容器中,这意味着会话、智能体执行框架和沙箱都共享同一个环境。这种做法有一些优点,包括文件编辑是直接的系统调用,而且无需设计服务边界。

但把所有东西耦合进一个容器后,我们遇到了一个老旧的基础设施问题:我们养了一只宠物。在“宠物与牲畜”的比喻中,宠物是有名字、需要悉心照料、不能失去的个体,而牲畜则可以互换。在我们的案例中,服务器成了那只宠物;如果容器发生故障,会话就会丢失。如果容器没有响应,我们就得费心把它恢复正常。

照料容器意味着要调试无响应、卡住的会话。我们唯一的观察窗口是 WebSocket 事件流,但它无法告诉我们故障发生在哪里,这意味着执行框架中的错误、事件流中的数据包丢失,或容器离线,表现出来都一样。要弄清楚出了什么问题,工程师必须在容器内打开 shell;但由于该容器通常还存放着用户数据,这种做法实际上意味着我们无法进行调试。

第二个问题是,运行框架假定 Claude 处理的所有内容都与它位于同一个容器中。当客户要求我们将 Claude 连接到他们的虚拟私有云时,他们必须将自己的网络与我们的网络建立对等连接,或者在自己的环境中运行我们的运行框架。当我们希望将运行框架连接到不同的基础设施时,其中内置的一项假设就成了问题。

我们最终找到的解决方案是,将我们所理解的“大脑”(Claude 及其运行框架)与“双手”(执行操作的沙箱和工具)以及“会话”(会话事件日志)解耦。三者各自通过接口交互,彼此之间几乎不作假设,而且都可以独立发生故障或被替换。

运行框架移出容器。 将大脑与双手解耦,意味着运行框架不再位于容器内部。它像调用其他工具一样调用容器:execute(name, input) → string。容器成了可随时替换的资源。如果容器崩溃,运行框架会将这一故障捕获为工具调用错误,并将其传回 Claude。如果 Claude 决定重试,就可以按标准流程重新初始化一个新容器:provision({resources})。我们不再需要费心修复出故障的容器。

从运行框架故障中恢复。 运行框架也成了可随时替换的资源。由于会话日志位于运行框架之外,运行框架中的任何内容都无需在崩溃后保留下来。当一个运行框架发生故障时,可以通过 wake(sessionId) 启动一个新的运行框架,使用 getSession(id) 取回事件日志,再从最后一个事件继续运行。在智能体循环期间,运行框架通过 emitEvent(id, event) 向会话写入数据,以持久保存事件记录。

安全边界。 在耦合设计中,Claude 生成的任何不可信代码都在存有凭据的同一个容器中运行,因此,提示注入只需诱使 Claude 读取自身的环境即可。攻击者一旦获得这些令牌,就能创建不受限制的新会话,并向其委派任务。严格限定权限范围是一种显而易见的缓解措施,但这隐含了一个假设:Claude 使用受限令牌无法做到某些事情,而 Claude 正变得越来越聪明。结构性的修复方法是确保这些令牌永远无法从运行 Claude 所生成代码的沙箱中访问。

我们采用了两种模式来确保这一点。身份验证信息可以与资源捆绑,也可以保存在沙箱之外的凭据保管库中。对于 Git,我们在沙箱初始化期间使用各个代码仓库的访问令牌来克隆仓库,并将令牌配置到本地 git 远程仓库设置中。Git push 和 pull 可以在沙箱内正常使用,而智能体始终无需直接处理令牌。对于自定义工具,我们支持 MCP,并将 OAuth 令牌存储在安全的凭据保管库中。Claude 通过专用代理调用 MCP 工具;该代理接收一个与会话关联的令牌。随后,代理便可从凭据保管库中获取相应的凭据,并调用外部服务。运行框架始终不会接触到任何凭据。

会话并不等于 Claude 的上下文窗口

长周期任务往往会超出 Claude 上下文窗口的长度,而解决这一问题的常规方法都涉及对保留哪些内容作出不可逆的决定。我们在关于上下文工程的先前研究中探讨过这些技术。例如,压缩机制允许 Claude 保存上下文窗口的摘要,而记忆工具则允许 Claude 将上下文写入文件,从而实现跨会话学习。这还可以结合上下文裁剪,有选择地移除旧工具结果或思考块等内容中的词元。

但不可逆地决定有选择地保留或丢弃上下文,可能会导致失败。我们很难知道后续轮次会需要哪些 token。如果消息经过压缩步骤处理,运行框架就会从 Claude 的上下文窗口中移除已压缩的消息;只有将这些消息存储起来,才能恢复。先前的工作探索过通过将上下文存储为位于上下文窗口之外的对象来解决这一问题的方法。例如,上下文可以是 REPL 中的一个对象,LLM 可以通过编写代码对其进行筛选或切片,从而以编程方式访问它。

在 Managed Agents 中,会话提供了同样的优势:它充当位于 Claude 上下文窗口之外的上下文对象。但上下文并非存储在沙盒或 REPL 中,而是持久地保存在会话日志中。接口 getEvents(), 允许大脑通过选择事件流中的位置切片来检索上下文。该接口使用灵活:大脑可以从上次停止读取的位置继续,可以回退到某个特定时刻之前的几个事件以查看前因,也可以重新读取某个特定操作之前的上下文。

任何获取到的事件也可以先在运行框架中转换,再传入 Claude 的上下文窗口。这些转换可以是运行框架所编码的任何处理,包括通过整理上下文来提高提示缓存命中率,以及上下文工程。我们将会话中可恢复的上下文存储,与运行框架中任意的上下文管理分开处理,因为我们无法预测未来模型需要怎样的具体上下文工程。这些接口将上下文管理交由运行框架处理,只保证会话持久保存并可供检索。

多个大脑,多个执行端

多个大脑。 将大脑与执行端解耦,解决了我们最早遇到的客户投诉之一。当团队希望 Claude 使用其自有 VPC 中的资源时,唯一的办法是将他们的网络与我们的网络对等连接,因为承载运行框架的容器默认所有资源都位于容器旁边。运行框架不再位于容器中后,这一假设也就不复存在。这一变化还带来了性能提升。最初我们把大脑放进容器时,意味着需要多少个大脑,就需要多少个容器。对于每个大脑,必须等容器配置完成后才能进行推理;每个会话都要预先承担完整的容器启动成本。每个会话——即使之后根本不会使用沙盒——都必须克隆代码仓库、启动进程,并从我们的服务器获取待处理事件。

这段空等时间体现在首 token 延迟(TTFT)上,它衡量会话从接受任务到生成第一个响应 token 之间需要等待多久。TTFT 是用户感受最明显的延迟。

将大脑与执行端解耦,意味着只有在需要时,大脑才会通过工具调用 (execute(name, input) → string) 配置容器。因此,不需要立即使用容器的会话无需等待容器就绪。编排层从会话日志中提取待处理事件后,就可以立即开始推理。采用这种架构后,我们的 p50 TTFT 降低了约 60%,p95 降低了 90% 以上。扩展到多个大脑,只需启动多个无状态运行框架,并仅在需要时将它们连接到执行端。

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

将大脑与手解耦,会让每一只手都成为一个工具,execute(name, input) → string:输入一个名称和参数,返回一个字符串。这个接口支持任何自定义工具、任何 MCP 服务器,以及我们自己的工具。这个执行框架并不知道沙箱是容器、手机,还是 Pokémon 模拟器。而且由于任何一只手都不与任何一个大脑耦合,大脑之间可以彼此传递手。

结论

我们面临的挑战是一个老问题:如何为“尚未被想到的程序”设计一个系统。操作系统之所以能延续数十年,是因为它们把硬件虚拟化为足够通用的抽象,从而能够容纳当时尚不存在的程序。通过 Managed Agents,我们的目标是设计一个系统,能够容纳未来围绕 Claude 的执行框架、沙箱或其他组件。

Managed Agents 是一种有着相同理念的元执行框架,它并不对 Claude 在未来会需要的具体执行框架预设立场。相反,它是一个拥有通用接口、能够支持许多不同执行框架的系统。例如,Claude Code 就是一个出色的执行框架,我们在各类任务中广泛使用它。我们也已经表明,面向特定任务的智能体执行框架在狭窄领域中表现出色。Managed Agents 能够容纳其中任何一种,并随着时间推移匹配 Claude 的智能水平。

元执行框架设计意味着,我们会对 Claude 周边的接口做出明确判断:我们预计 Claude 将需要操纵状态(session)和执行计算(sandbox)的能力。我们也预计 Claude 将需要扩展到多个大脑和多只手的能力。我们设计这些接口,是为了让这些能力能够在长时间范围内可靠且安全地运行。但我们并不对 Claude 所需的大脑或手的数量和位置做任何假设。

来源:Anthropic Engineering · anthropic.com