Anthropic 在 10 月 22 日发了一篇《Building agents: When to fold subagents into your main agent loop》。作者是 Applied AI 的 Diane Sarkis,核心结论很朴素:把路由器、规划器、领域专家子 agent 折叠进主循环,改成「一个模型 + 一个上下文窗口 + 渐进披露的 skill 和 tool」,在多个企业部署里同时赢了质量和成本。

我读完之后认同它,但我更想把这篇文章记成另一句话——真正被讨论的不是「要不要子 agent」,而是 harness 的重量应该放在哪一层。因为同样是「一个能回答用户的能力」,落在架构里有三种位置,harness 的写法完全不一样。

同一个能力,三种落点

一、子 agent 自己面对用户

这是最重的一种。子 agent 有独立上下文、独立工具、独立指令,还需要能跟用户直接对话,于是 harness 必须负责:意图路由、对话交接、交接时传什么上下文、多套 prompt 怎么不冲突、多套权限怎么隔离、多套 eval 怎么汇总。

它换来的是组织上的自治:每个团队写自己的 agent,互不干扰。代价写在交接处——上下文一过边界就被压缩一次,而且没有人真正拥有端到端质量。文章里那个客服 agent 就是典型:十几个专家子 agent,品牌语气难统一,延迟把体验拖垮。

这种形态在组织规模大、团队边界硬的时候是合理的过渡。但它是「组织成本的解」,不是「能力的解」。

二、主 agent 通过 tool 调用子 agent

对话留在主 agent 手里,子 agent 变成一次可调用的黑盒:给定输入,交回紧凑的、结构化结果。harness 从「交接协议」退化成「一个工具定义」。

这是迁移成本最低的一站,也是最值得先做的一站:不用重写子 agent,主 agent 还能拿结论去对真实数据校验,最终综合的输入也能自己裁。但病根没除——每个 specialist 还是有自己的 prompt、上下文、owner 和 eval;每次调用还是交回一份有损摘要;每次调用还是嵌套一个模型循环,延迟照旧叠。

三、折叠成 skill + tool

子 agent 的 prompt 变成 skill(这个团队怎么做事、有哪些判断),它的 API 调用变成 MCP tool(能读什么、能写什么、返回什么形状)。主循环里只剩一个模型、一个窗口、一批工具、一组 skill 描述。

原来那些结构性的东西被拆散分配掉:编排和排序交给模型自己规划,领域流程进 skill,硬限制(校验、审批门)和中途需求(记忆检索)进 tool。代码只做那些便宜且几乎总是要做的机械活。

「越小越重」到底重在哪

harness 变小的部分很好数:分支少了、路由没了、提示词条数掉了、要维护的 eval 从 N 套变一套。Anthropic 说他们在更强的模型上把 Claude Code 的 system prompt 砍掉了 80% 以上,就是这件事的量化版本。

但重量没有消失,它被挪到了三个地方,而且这三处比代码更难写:

第一是描述。工具超过 30–50 个定义之后,工具选择本身开始退化,所以要用 tool search 做延迟加载;skill 必须先给一句足够准的短描述,让模型在该用的时候真的加载它。写代码时写错是报错,写描述时写错是静默失效——模型不知道自己有个能力,或者在不该用的时候用了。

第二是模型自己的连续性。第一轮就把计划写进上下文,后面随结果改计划,写计划的和执行计划的是同一个模型——这样才能中途改道。这是好事,但它要求模型真的会自我叙述进度、自我检查,而这件事在不同模型上强弱差别很大。

第三是所有权。小循环没有中间层可以甩锅:端到端 eval 必须由一个小团队真正拥有,覆盖生产里真实出现的链式调用和所有不可破的规则。文章里那个「折叠之后延迟降了,但主 agent 自己查了订单、没再问物流要送达日期」的例子说明,看总分不够,得看哪些任务翻转了,而且同一个任务要多跑几次——那次翻转只在一半的运行里出现。

所以「小」从来不等于省事。小 harness 是把复杂度从结构里赶出去,赶到描述、模型能力和验收标准上。这三样里任意一样松掉,小循环立刻退化成「一个超级 prompt」,而这正是文章开头批评的另一个失败模式。

为什么我信这条线:两个反面教材

一、把团队设计得太完整:Encoder 的 teammate

我学 Agent_Teammate 那阵,觉得多 agent 的形态很和谐:主 agent 和子 agent 要交互之外,子 agent 之间还能互相交流,走一个 mailbox;而且任务做完子 agent 不结束,退回 IDLE 等下一个任务或者主 agent 的 review。这套设计我后来在自己的 Encoder 项目里做完了——一个跑在终端里的 coding agent,team.py(源码)七百多行,就是它的多 agent 层。

具体长这样:每个 agent 一个收件箱文件 .Mailbox/<name>.json,五类消息 task / review / end / result / notice,按 end < review < task < notice 排队,review 永远压过排队中的新任务;teammate 一生在 work / idle / ending 三态之间走,只有主 agent 显式发 end 才关;同时最多三个;改代码的 teammate 默认在独立 worktree 里跑,各自 commit 到自己的分支,主 agent 再 integrate_results 归并,只有真冲突才起一个一次性的集成 agent;队友不继承派活类的工具,防止无限嵌套。

当时觉得这套东西很完整。现在回头看,完整是真的,必要是假的。

站得住的只有三条:一个任务只给一个 teammate;review 优先级高于新任务;改同一份代码的人各自在 worktree 里干活。这三条和模型强不强无关,它们解决的是隔离和验收,所以不会因为模型变强而失效。

站不住的是另外两条。一条是 IDLE 常驻。teammate 常驻保住的其实是两样东西:上下文热态和配好的工具实例。但模型本身没有热态,每次推理都是重新读一遍上下文,所以「待命」对一个 agent 来说不省事,反而多一份要维护的、会过期的上下文——我在代码里把 broadcast 攒进 self._notices,等下次派活再注入,就是这个代价的具象。真正值得常驻的是进程态:dev server、浏览器 profile、worktree 里装好的依赖。这些东西该待在 tool 层,跟 agent 活多久没关系。IDLE 该留给环境,不该留给模型。

另一条是 mailbox 互通。它让 agent 之间能对话,看着很自然,但它是把「共享事实」做成了「传话通道」。A 发现一个全局异常就广播,别人的下一轮拿到的是 A 当时那句话,不是 A 的上下文。同一份信息过 N 次边界就被压 N 次,出了事也看不见是谁漏了什么。跨 agent 真正需要共享的是事实——共享文件、结构化状态——不是一个对话链路。

边界也得说清楚:简单主 agent 够用,前提是单窗口装得下、并且不需要真并行地改同一份代码。任务多不构成并行的理由,只有「上下文必须丢弃」和「必须隔离写」才构成。这一点我其实早写在设计文档第一行——「能单 Agent 做的事情,就不需要多 agent」——只是当时没敢信。

二、把能力写进桥接层:personal agent 和 qqbot

我搭 personal agent 和 qqbot 的时候踩的坑不在子 agent,在桥接层。

一开始我把很多设计交给 AI 定,结果大量消息不是直接进模型,而是先进一个写死的程序:关键词、概率匹配,命中就直接返回。它几乎不花 token,但用久了必然腐化——用户换个说法就失效,分支越堆越多,失败时静默不报错。更麻烦的是,能力会顺着入口不断被吸进桥接层,因为那里改一行就能加功能。

代价是我第一次真正理解的:这些能力脱离了 agent 的视野。模型不知道自己有它,无法在需要时组合它,出了问题也无法自己解释和修复。功能在,但不可组合、不可观察。

现在看,这跟文章里的「传话游戏」是同一种病:边界画在了「这是哪段职责」上,而不是画在「这段工作需不需要其他部分的上下文」上。画在职责上,就要不停传摘要;画在上下文上,才谈得上自包含。我给自己留的判断标准只有一句:这段工作几乎不需要系统其他部分、结果能压成一小块交回来,才值得独立成一个上下文;需要来回要信息的,就该待在主循环里。

子 agent 仍然该留的地方

文章列了三条:单循环因为上下文膨胀出现可测量的性能下降;确实需要并行,且上下文用完可以丢弃;单个 agent 选不准工具或 system prompt 里有互相冲突的指令。

我的用法落在第二条:写代码这类任务派给后台的 coding agent 去做,它拿一个独立上下文,做完交回结果,上下文随即扔掉。它就是「一次性工人」——给它材料,它交成品,主循环继续拿着完整历史往前走。这跟折叠并不矛盾:折叠针对的是那些「常驻的、被当成架构一部分」的子 agent,不是这种用完就丢的执行器。

如果要动手,顺序是什么

  1. 先有端到端 eval。哪怕只有十个黄金例子。测的是「用户的问题最后有没有被解决好」,不是「某个中间步骤执行得漂不漂亮」。
  2. 从调用最密、耦合最紧的那一对开始合并——生产里经常一个接一个出现的,说明它们本来就是一个域。
  3. 先让主 agent 用 tool 的方式调它,保留对话权,同时拿到 baseline。
  4. 再一个一个折成 skill + tools,折一个跑一次 eval,对比折前折后,看翻转的任务而不只看分数。
  5. 顺手做一次 prompt 审计:把当初为旧模型写的那些补丁式指令删掉。它们现在只会让 agent 更慢、更僵。
  6. 权限不要做成「每个权限等级一个 agent」,而是每个 tool 自己检查调用者能看什么能做什么,不行就返回一句模型能读懂的拒绝。一个循环就能服务不同权限的用户。

最后

我用「能用 → 常用 → 好用」形容过自己搭 agent 的路径。这条线放在 harness 上也成立:结构不是设计出来的,是用出来的。模型每强一档,harness 就该薄一层;薄不下去的地方,多半不是模型不够,而是 eval 没建好,或者描述写得还不够准。

原文:https://claude.com/resources/articles/building-agents-when-to-fold-subagents-into-your-main-agent-loop