Managed Agents

规模化基础设施 — 将大脑与双手解耦、会话作为持久日志、以及超越实现的接口

过时假设问题

每个 Harness 都编码了对模型限制的假设。这些假设会随着模型改进而过时。

一个真实的例子:Claude Sonnet 4.5 表现出一种”上下文焦虑”(context anxiety)— 模型在接近上下文窗口限制时会过早终止任务,即使它还有足够空间继续。为此,Anthropic 的工程师在 Harness 中添加了上下文重置逻辑。但当 Opus 4.5 不再表现出该行为时,这些代码就成了无用的负担。同样,因为模型无法维持长期连贯性而添加的 Sprint 分解策略,在 Opus 4.6 改进了长期规划后也变得不必要了。

Anthropic 的应对:构建具有足够通用以超越任何特定 Harness 实现的接口的基础设施。

“我们预期 Harness 将持续演进。因此我们构建了 Managed Agents:一个通过一小组旨在超越任何特定实现(包括我们当前运行的实现)的接口来运行长时 Agent 的托管服务。”

深入思考:这揭示了一个结构性矛盾 — Harness 的演进速度必须跟上模型的演进速度,但基础设施的演进速度远低于两者。多数团队的直觉是”模型升级了,改 Harness 就行”,但当补丁累积到一定程度,Harness 本身就会变成一团无法维护的假设堆栈。Anthropic 选择的不是更快地改 Harness,而是让 Harness 成为可丢弃的,用稳定接口承托不断变化的实现。


设计哲学:尚未设想的程序

该设计从操作系统中汲取灵感。早期的操作系统设计者面临同样的问题:如何为尚不存在的程序构建基础设施。

他们的解决方案:将硬件虚拟化为通用抽象 — 进程、文件、套接字 — 超越任何具体实现。read() 系统调用不关心它访问的是 1970 年代的磁盘还是现代 SSD。

Managed Agents 应用了同样的原则,将 Agent 组件虚拟化为三个稳定的抽象:

抽象用途
Session所有发生事件的仅追加日志
Harness调用模型并路由工具调用的循环
SandboxAgent 可以运行代码的执行环境

不要养宠物

最初的架构将所有内容放在单个容器中 — 模型、Harness、沙箱。这种设计足够简单:模型生成的代码要修改一个文件,直接发起一个系统调用就行,不需要设计复杂的服务边界和通信协议。

然而,服务器可以被分为两种:宠物(Pets)牛群(Cattle)。“宠物”服务器是独一无二的,有自己的名字,需要人工精心照料,一旦它生病了,你就得想办法治好它,因为它无可替代。“牛群”服务器则是标准化的、可互换的,坏掉一台,直接换掉即可,系统整体不受影响。

将所有组件耦合在一个容器里,无异于把每一个 Agent 会话都变成了一只”宠物”。

耦合架构 单一容器 — 每次故障都是全局的,每个组件不可分离 单一容器 (Container) Session(状态) Harness(逻辑) Sandbox(执行) 容器崩溃 → 状态全丢 → 无法恢复 调试访问 → 进入容器内部 → 隐私悖论 VPC 对接 → 网络对等互联 → 技术债务 每个容器都是"宠物" — 独一无二、不可替代、脆弱易损

这带来了层层递进的问题:

  • 崩溃 = 状态全失 — 容器失败,会话就丢了。没有恢复,没有重放。WebSocket 事件流无法区分是 Harness bug、网络丢包还是容器宕机。
  • 调试 = 隐私悖论 — 排查问题需要 shell 进入容器,但容器存有用户数据。为了可维护性,不得不破坏安全性。
  • 代码 + 凭证共存 — 不受信任的模型生成代码与 OAuth token、API 密钥在同一环境运行。
  • 网络锁定 — Agent 所操作的一切资源都必须在同一环境里。客户想访问私有 VPC,就必须与 Anthropic 网络做对等互联。

深入思考:这四个问题并非孤立存在,它们共享同一个根因 — 本应独立的组件被迫共享命运。而每一种”修补”方案都只能解决一个症状:加重启逻辑治崩溃、加权限隔离治安全、加网络代理治 VPC — 补丁越打越多,但底层的耦合一直在。一个最初为了简单的架构设计,最终变成了阻碍业务扩展的巨大技术债务。真正的解不是更多的补丁,而是消除让补丁成为必要的那个前提。


将大脑与双手解耦

解决方案:将大脑(模型 + Harness)与双手(执行环境)分离。三个组件拆分为可以独立存在、独立失效的实体:

  • 大脑(Brain):Claude 模型和它的 Harness 循环 — 负责思考、决策和调度
  • 手脚(Hands):Sandbox 和工具 — 负责执行具体操作
  • 会话(Session):独立于两者之外的 append-only 事件日志 — 记录一切

解耦架构 无状态大脑 · 持久日志 · 可丢弃手脚 — 牲畜而非宠物 Session 持久事件日志 • Append-only • 唯一真实来源 • 可承受任何故障 getSession(id) Harness 大脑 · 无状态 • 调用模型 • 路由工具调用 • 零本地状态 wake(sessionId) Sandbox 手脚 · 可丢弃 • 运行代码 • 与密钥隔离 • 可互换替代 execute(name, input) getEvents emitEvent execute result 结构性保证 ① 崩溃恢复 — 新 Harness 读取会话日志,从最后事件恢复执行 ② 安全隔离 — 凭证永远不进入 Sandbox,密钥经代理路径流转 ③ 可组合 — 任何大脑可用任何手脚,手脚可服务多个大脑

每个组件都有清晰的接口定义 — 只要满足右列的条件,左列可以用任何技术实现:

组件接口(伪代码)满足条件
SessiongetSession(id)(Session, Event[])任何接受幂等追加的 append-only 日志
getEvents(id)PendingEvent[]
emitEvent(id, event)
编排wake(session_id)void任何能按 ID 调用函数并在失败时重试的调度器
Harnessyield Effect<T>EffectResult<T>任何产出 effect 并将结果追加到 Session 的循环
Sandboxprovision(resources) / execute(name, input)string任何可配置一次、多次调用的执行器
Resources[(source_ref, mount_path)]任何可按引用获取的持久存储
Tools(name, description, input_schema)任何可描述为名称和输入 schema 的能力

Harness 离开容器

Harness 不再驻留在容器内部,它变成了一个无状态的服务。它将每个容器视为具有简单接口的工具:

execute(name, input) → string

容器变成了牲畜而非宠物 — 可互换且可丢弃。如果容器死亡,Harness 捕获失败(作为一次普通的工具调用失败),将错误传回给 Claude。模型可以决定重试,系统用 provision({resources}) 初始化一个新容器继续执行。无需维护失败的容器。

Session 作为持久日志

Session 日志位于 Harness 之外。Harness 中没有任何东西需要在崩溃中存活:

  • 新 Harness 通过 wake(sessionId) 启动
  • 通过 getSession(id) 检索事件日志
  • 从最后记录的事件恢复
  • 所有事件通过 emitEvent(id, event) 持久写入

深入思考:三个问题的解法其实都指向同一个洞察 — 状态是最麻烦的东西,谁持有状态谁就变成”宠物”。解耦的本质不是”把大系统拆成小系统”(那只是微服务的老话),而是把状态收敛到一个专门的、高可用的 Session Log 中,让其他所有组件都变成无状态的。一旦做到这一点,崩溃恢复、安全隔离、部署灵活性就不是需要逐个”实现”的特性,而是架构的涌现属性 — 它们自然就在那里。

安全边界

在耦合设计中,提示注入只需说服模型读取环境变量即可获取 token。

结构性修复:token 永远无法从模型生成代码运行的沙箱中访问。 两种模式实现了这一点:

安全边界 — 凭证隔离 Token 永远不进入执行环境 — 结构性保证,而非策略约束 Harness 大脑 代理服务 Proxy 保险库 Vault ① session ID ② 获取凭证 ③ 代理服务用凭证调用外部服务 → 将结果返回给 Harness 结构性隔离边界 Sandbox 模型代码在此运行 ✕ 永远不可达 保险库 密钥存储于此 提示注入即使完全控制 Sandbox → 零密钥泄露

  • 捆绑认证(Bundled auth):仓库 token 在沙箱初始化期间克隆仓库并接入本地 git remote。git pushgit pull 无需暴露 token 即可工作。Agent 永远不处理 token 本身。
  • 保险库认证(Vault-based auth):MCP 工具通过专用代理调用。代理接收与会话关联的 token,从安全保险库获取凭证,用凭证调用外部服务,然后将结果返回给 Harness。Harness 永远看不到实际凭证。

深入思考:多数安全方案本质上是”策略性”的 — 通过给权限收窄范围、给 token 设短有效期来降低风险。但这类方案隐含了一个危险假设:模型不够聪明,无法利用有限权限做意想不到的事。问题是,模型的智能程度在飞速进化,今天的安全假设明天可能就被轻易打破。Anthropic 的方案是结构性的 — 不是限制模型能做什么,而是让它物理上接触不到 密钥。这就像把金库和车间建在不同的建筑里,而不是在同一栋楼里加更多的锁。


Session 不是 Claude 的上下文窗口

长周期任务必然会超出模型的上下文窗口。关键洞察:Session 和上下文窗口是两个不同的东西

Session 是所有事件的完整、持久、可查询的记录。而上下文窗口只是 Harness 从 Session 中选取并组装后传给模型的一个子集。Harness 可以通过 getEvents() 接口灵活地查询 Session:

  • 从停止处继续读取 — 按位置切片获取新事件
  • 回溯到特定时刻之前 — 重新审视导致某个事件的上下文
  • 在特定操作前重读上下文 — 重新理解某个决策的前因

Harness 还可以在将事件传给模型之前转换它们 — 例如为了 prompt cache 命中率重组消息顺序。

这种分离是在基础设施层面启用 Context Engineering 的关键:Harness 选择 Session 中什么进入上下文窗口,以及如何组织。存储和管理被完全解耦 — 未来模型上下文窗口扩大或策略变化时,Session 接口保持不变。

深入思考:这一设计可以类比为操作系统中 RAM 和磁盘的关系。上下文窗口是 RAM — 一个临时工作区,仅加载当前计算所需的子集。Session 日志是磁盘 — 完整的持久记录。Harness 扮演内存管理单元(MMU)的角色,智能地决定每次模型调用时将什么”加载”到上下文中。

这带来一个重要的认知转变:上下文压缩不是”丢失记忆”,而是”驱逐缓存”。完整历史始终安全地存储在 Session 中,随时可以重新加载。这比在上下文窗口内部做不可逆压缩的方案高明得多 — 后者一旦丢弃了错误的内容,没有回头路。


多个大脑,多双手

扩展大脑

一旦 Harness 移出容器,VPC 访问的网络对等互联就变得不必要了。更重要的是性能提升:

  • 之前:每个会话都要支付完整的容器设置成本(克隆仓库、启动进程、获取事件),即使它从未使用沙箱
  • 解耦后:容器仅在需要时按需配置。推理在编排层从 Session 日志拉取待处理事件后立即开始

结果:p50 首个 token 响应时间下降约 60%,p95 下降超过 90%。

扩展双手

每个执行环境成为具有相同 execute(name, input) → string 接口的工具。Harness 不关心沙箱是什么 — 容器、手机、浏览器或其他任何东西:

  • 没有任何一双手与任何大脑耦合
  • 大脑可以将手传递给彼此
  • 多双手可以服务一个大脑,一双手也可以服务多个大脑

这种可组合性意味着同一接口支持 Claude Code(广泛通用)、特定任务 Harness(窄领域优化)和自定义 Harness(任意 Agent 组合)。


元 Harness (Meta-Harness)

Managed Agents 不是一个具体的 Harness。它是一个元 Harness — 一个能容纳许多不同 Harness 实现的通用接口系统:

  • 对接口有主见:操纵状态(Session)和执行计算(Sandbox)的能力
  • 对实现无主见:不假设大脑或手的数量或位置,也不假设 Claude 需要的具体 Harness
  • 为演进而设计:当模型能力变化、Harness 假设过时时,接口保持稳定

挑战是永恒的:为尚不存在的程序设计系统。操作系统通过虚拟化硬件解决了它。Managed Agents 通过虚拟化 Agent 的基础设施来解决它 — 创建对未预见的 Harness 足够通用,同时对当前使用足够具体的接口。

深入思考:Anthropic 为日益强大的大模型,构建了一个与之匹配的、工业级的、可靠的运行环境。这个环境的价值,在今天可能还未被充分认识。但随着 Agent 从演示走向落地,人们终将发现,一个健壮、可扩展、安全的底层架构,远比模型本身多几个点的评分要重要得多。这是让 AI 从”聪明”走向”有用”的必经之路。


来源

Scaling Managed Agents: Decoupling the Brain from the Hands — Lance Martin, Gabe Cemaj & Michael Cohen, Anthropic, 2026.04.

这页有帮助吗?