Anthropic 工程团队
解耦‘大脑’与‘双手’:Managed Agents 的接口抽象设计
阅读正文 ↗点击知识块看内容,点击连线看依据。没有关系的块也保留。
发布于 2026 年 4 月 8 日
Harness(编排框架)会固化关于模型能力边界的假设,而这些假设会随着模型迭代而过时。托管型智能体(Managed Agents)——我们为长周期(long-horizon)智能体任务提供的托管服务(hosted service)——其核心是一组接口(interfaces),其设计目标是:即使 harness 不断演进,这些接口本身保持稳定。
通过阅读我们的文档(docs)开始使用 Claude 托管型智能体(Claude Managed Agents)。
工程博客(Engineering Blog)持续探讨的主题之一,是如何构建高效智能体(agent)并为长期运行任务设计 harness(编排框架)。这项工作的共性在于:harness(编排框架)隐式编码了关于 Claude 当前‘无法独立完成什么’的假设。然而,这些假设必须被持续质疑,因为随着大语言模型(LLM)能力提升,它们极易迅速过时(go stale)。
仅举一例:在先前工作中,我们发现 Claude Sonnet 4.5 在感知到上下文长度(context limit)临近时,会提前终止任务——这种行为有时被称为‘上下文焦虑(context anxiety)’。我们通过在 harness(编排框架)中添加上下文重置(context resets)来解决该问题。但当我们将同一 harness 部署到 Claude Opus 4.5 上时,该行为已不复存在;那些上下文重置(context resets)反而成了冗余负担(dead weight)。
我们预期 harness(编排框架)将持续演进。因此,我们构建了托管型智能体(Managed Agents):这是 Claude 平台(Claude Platform)中一项托管服务(hosted service),代表用户运行长周期(long-horizon)智能体,其全部功能仅通过一组精简接口(small set of interfaces)暴露——这些接口的设计目标是超越任何特定实现(including the ones we run today),具备长期稳定性。
构建托管型智能体(Managed Agents)本质上是在解决计算领域一个古老命题:如何为‘尚未构想出的程序(programs as yet unthought of)’设计系统。数十年前,操作系统(operating systems)通过将硬件虚拟化为抽象层(abstractions)——如 进程(process)、文件(file) ——解决了这一问题:这些抽象足够通用,足以支撑未来尚未诞生的程序。这些抽象的生命力远超其所依托的具体硬件。例如,read() 系统调用(system call)完全不关心其访问的是 1970 年代的磁盘组(disk pack)还是现代固态硬盘(SSD);顶层抽象保持稳定,而底层实现则可自由更迭。
托管型智能体(Managed Agents)遵循相同范式。我们对智能体(agent)的组件进行了虚拟化(virtualizing):会话(session,即仅追加(append-only)的日志,记录所有发生事件)、编排框架(harness,即调用 Claude 并将 Claude 的工具调用(tool calls)路由至相应基础设施的循环逻辑)、沙箱(sandbox,即 Claude 可安全运行代码并编辑文件的执行环境)。这使得每个组件的实现均可独立替换,而不会干扰其余组件。我们对这些接口(interfaces)的形态(shape)持有明确立场(opinionated),但对其背后的具体实现(what runs behind them)则持开放态度。
项目初期,我们将所有智能体(agent)组件置于单一容器(container)内,这意味着会话(session)、智能体编排框架(agent harness)和沙箱(sandbox)共享同一运行环境。该方案具备若干优势,例如:文件编辑可直接触发系统调用(syscalls),且无需设计服务间边界(service boundaries)。
但将全部组件耦合于单个容器,使我们陷入一个陈旧的基础设施困境:我们无意中采纳了一只‘宠物(pet)’。在‘宠物 vs 牲畜(pets-vs-cattle)’类比中,‘宠物’指一个被赋予名称、需人工悉心照料、不容有失的个体;而‘牲畜’则是可互换、可批量管理的单元。在我们的场景中,服务器(server)就成了那只‘宠物’:一旦容器(container)崩溃,会话(session)即告丢失;一旦容器无响应(unresponsive),我们就不得不手动‘护理’(nurse)它恢复健康。
‘护理’容器意味着调试那些卡死(stuck)且无响应的会话。我们唯一的可观测入口是 WebSocket 事件流(WebSocket event stream),但它无法告诉我们故障究竟发生在何处——这意味着编排框架(harness)中的缺陷、事件流(event stream)中的数据包丢失(packet drop)、或容器离线(container going offline)等不同根源,最终呈现为完全相同的表象。为定位问题根源,工程师不得不进入容器内部打开 shell 进行排查;但由于该容器通常还承载着用户数据,这种做法实质上等于我们丧失了可靠的调试能力。
第二个问题是:该编排框架(harness)隐含假设——Claude 所操作的一切内容都与其同处一个容器内。当客户要求我们将 Claude 接入其虚拟私有云(Virtual Private Cloud, VPC)时,他们要么必须将其网络与我们的网络进行对等连接(peer their network with ours),要么需在其自有环境中运行我们的编排框架(harness)。一个被硬编码(baked into)进 harness 的假设,在我们希望将其接入不同基础设施时,反而成了阻碍。
我们最终采用的方案是将我们所称的‘大脑’(Claude 及其运行时框架 harness)与‘双手’(执行操作的沙箱 sandbox 和工具)以及‘会话’(session,即会话事件日志)三者彼此解耦。每一部分都成为一个接口,对其他部分做出极少假设,并可独立失败或被替换。
**运行时框架(harness)离开容器。**将‘大脑’与‘双手’解耦意味着 harness 不再驻留在容器(container)内部。它以调用任意其他工具的方式调用容器:execute(name, input) → string。容器由此变为‘牲畜型资源’(cattle)。若容器崩溃,harness 将其捕获为一次工具调用错误(tool-call error),并原样传回给 Claude;若 Claude 决定重试,则可通过标准配方 provision({resources}) 重新初始化一个新容器。我们不再需要人工‘护理’故障容器使其恢复健康。
**从 harness 故障中恢复。**harness 本身也变为‘牲畜型资源’(cattle)。由于会话日志(session log)存于 harness 外部,harness 内部无需任何状态在崩溃后存活。当 harness 崩溃时,可启动一个新的实例,通过 wake(sessionId) 唤醒,并调用 getSession(id) 重新加载事件日志,从而从最后一个已记录事件处继续执行。在智能体循环(agent loop)中,harness 通过 emitEvent(id, event) 向会话写入事件,以持久化保存事件记录。
安全边界(security boundary)。 在紧耦合(coupled)设计中,Claude 生成的任何不受信任代码(untrusted code)均在同一容器内运行,而该容器同时持有凭据(credentials)——因此一次提示注入(prompt injection)攻击只需诱使 Claude 读取自身环境变量即可。一旦攻击者获取这些令牌(token),便可创建全新、无限制的会话,并将任务委托给它们执行。缩小权限范围(narrow scoping)是一种显而易见的缓解措施,但这隐含了一个假设:即 Claude 在受限令牌下无法达成某些行为;而 Claude 的能力正日益增强。根本性的结构修复(structural fix)是确保这些令牌绝不会被沙箱(sandbox)中运行的 Claude 生成代码所触及。
我们采用两种模式来保障这一点。认证信息(Auth)可随资源一同打包,或存放于沙箱外部的安全保险库(vault)中。对于 Git,我们在沙箱初始化阶段使用每个仓库的访问令牌(access token)克隆仓库,并将其配置为本地 git 远程仓库(remote)的凭证;此后所有 git push 与 git pull 操作均可在沙箱内部正常执行,而智能体(agent)本身全程不接触该令牌。对于自定义工具,我们支持 MCP(Model Context Protocol,模型上下文协议),并将 OAuth 令牌存储于安全保险库中。Claude 通过专用代理(proxy)调用 MCP 工具;该代理接收与会话关联的令牌,继而从保险库中提取对应凭据,并向外部服务发起调用。harness 自始至终均不感知任何凭据。
长视野(long-horizon)任务常常超出 Claude 的上下文窗口(context window)长度,而应对这一问题的标准方法均涉及对保留内容所作的不可逆决策(irreversible decisions)。我们在先前关于上下文工程(context engineering)的研究中已探讨过这些技术。例如,压缩(compaction) 允许 Claude 保存其上下文窗口的摘要;而记忆工具(memory tool) 则允许 Claude 将上下文写入文件,从而实现跨会话(across sessions)的学习。该方法可与上下文裁剪(context trimming) 配合使用,后者通过选择性移除令牌(tokens)——例如旧的工具调用结果或推理块(thinking blocks)——来优化上下文。
但针对上下文的选择性保留或丢弃所作的不可逆决策,可能导致失败。人们很难预判未来轮次(future turns)将需要哪些令牌。若消息经由压缩(compaction)步骤转换,运行时环境(harness)便会将已被压缩的消息从 Claude 的上下文窗口中移除;这些消息仅在被显式存储的前提下才可恢复。先前工作曾探索通过将上下文存储为一个位于上下文窗口之外(outside the context window) 的独立对象来解决此问题。例如,上下文可表现为一个 REPL(读取-求值-输出循环)中的对象,大语言模型(LLM)可通过编写代码对其进行过滤(filter)或切片(slice)以实现程序化访问。
在托管智能体(Managed Agents) 中,会话(session)提供了相同的益处:它作为一个位于 Claude 上下文窗口之外的上下文对象(context object)。但该上下文并非存储于沙箱(sandbox)或 REPL 内,而是持久化地存储于会话日志(session log) 中。接口 getEvents() 允许智能体的“大脑(brain)”通过选取事件流(event stream)的位置切片(positional slices)来查询上下文。该接口具有高度灵活性:大脑可从中断处继续读取、在特定时刻前倒回若干事件以观察前置脉络,或在特定动作前重读相关上下文。
任何被获取的事件均可在传入 Claude 的上下文窗口之前,由运行时环境(harness)进行变换(transformation)。这些变换可由 harness 自由编码,包括用于提升提示缓存命中率(prompt cache hit rate)的上下文组织方式,以及各类上下文工程(context engineering)策略。我们将可恢复的上下文存储(recoverable context storage) 职责置于会话(session)中,而将任意的上下文管理(arbitrary context management) 职责交由 harness 承担——这是因为我们无法预判未来模型所需的具体上下文工程技术。上述接口设计将上下文管理逻辑推至 harness 层,同时仅保证会话(session)本身具备持久性(durability)且可供随时查询(interrogation)
**多个大脑(Many brains)。**将‘大脑(brain)’与‘双手(hands)’解耦,解决了我们最早期客户的一个投诉。当团队希望 Claude 访问其自有虚拟私有云(VPC, Virtual Private Cloud)内的资源时,此前唯一的路径是将其网络与我们的网络对等连接(peering),因为承载‘控制装置(harness)’的容器默认假设所有资源都与其并置(co-located)。一旦控制装置不再运行于容器中,这一假设便不复存在。同一改动还带来了性能提升:最初我们将大脑置于容器中时,意味着多个大脑就需要多个容器;每个大脑启动前,都必须先完成对应容器的供给(provisioning),因此每次会话(session)都需预先承担完整的容器启动开销;甚至那些根本不会触及沙盒(sandbox)的会话,也不得不克隆代码仓库、启动进程、从我们的服务器拉取待处理事件。
这段停滞时间体现为‘首 token 延迟(time-to-first-token, TTFT)’——即会话从接受任务到生成首个响应 token 所耗费的时间。TTFT 是用户最敏锐感知到的延迟(latency)。
将大脑与双手解耦后,容器仅在真正需要时,才由大脑通过工具调用 execute(name, input) → string 动态创建。因此,无需立即使用容器的会话无需等待其就绪;推理(inference)可在编排层(orchestration layer)从会话日志(session log)中拉取待处理事件后即刻启动。采用该架构后,我们的 p50 TTFT 下降约 60%,p95 TTFT 下降超 90%。扩展至多个大脑,仅需启动多个无状态(stateless)控制装置,并仅在需要时将其连接至‘双手’。
**多双手(Many hands)。**我们还希望每个大脑都能连接至多双手。实践中,这意味着 Claude 必须能对多个执行环境(execution environment)进行推理,并决策将任务分发至何处——这比在单一 shell 中操作更具认知复杂性(cognitive task)。我们最初将大脑置于单个容器中,是因为早期模型尚不具备此能力;而随着模型智能水平(intelligence)提升,单容器反而成为瓶颈:一旦该容器故障,所有正被该大脑访问的‘双手’状态均会丢失。
大脑与双手解耦后,每只‘手’即成为一个工具(tool),接口为 execute(name, input) → string:输入一个名称(name)与输入(input),返回一个字符串(string)。该接口可支持任意自定义工具(custom tool)、任意 MCP(Model Context Protocol)服务器,以及我们自己的工具。控制装置(harness)无需知晓沙盒(sandbox)究竟是容器、手机,还是宝可梦(Pokémon)模拟器。且由于没有任何‘手’与特定‘脑’绑定,大脑之间可相互传递‘手’。
我们所面对的挑战由来已久:如何设计一套面向‘尚未构想出的程序(programs as yet unthought of)’的系统?操作系统(Operating System, OS)之所以能沿用数十年,正是因其将硬件虚拟化为足够通用的抽象层(abstraction),从而兼容那些诞生时尚未存在的程序。借助‘托管智能体(Managed Agents)’,我们的目标是构建一套系统,以容纳未来可能出现的各类控制装置(harness)、沙盒(sandbox)或其他围绕 Claude 的组件。
‘托管智能体(Managed Agents)’本身即是一种元控制装置(meta-harness),其设计理念与操作系统一脉相承——它不对 Claude 未来所需的具体控制装置持任何预设立场(unopinionated)。相反,它提供通用接口(general interface),支持接入多种不同的控制装置。例如,Claude Code 是一款极为出色的控制装置,我们在多项任务中广泛使用;我们也已证实,面向特定任务的智能体控制装置(task-specific agent harness)在狭窄领域中表现卓越。‘托管智能体’可兼容所有这些形态,并随 Claude 智能水平的演进而动态匹配。
元控制装置(meta-harness)的设计,意味着我们必须对 Claude 周边的接口持明确主张(opinionated):我们预期 Claude 需具备操纵状态(state,即会话 session)的能力,以及执行计算(computation,即沙盒 sandbox)的能力;我们也预期 Claude 将需要扩展至多个‘大脑’与多个‘双手’。我们所设计的接口,旨在确保这些能力可在长期时间尺度(long time horizons)内被可靠、安全地运行。但我们对 Claude 未来所需‘大脑’或‘双手’的具体数量与物理位置(location)不做任何假设。
作者:Lance Martin、Gabe Cemaj 与 Michael Cohen。感谢 Nodir Turakulov 与 Jeremy Fox 就相关议题提供的有益讨论。特别感谢智能体 API(Agents API)团队及 Jake Eaton 的贡献。
产品更新、操作指南(how-tos)、社区亮点(community spotlights)等资讯,每月推送至您的邮箱。
原文:https://www.anthropic.com/engineering/managed-agents
本文由英文原文全文翻译;阅读英文原文