把 subagent 折回主循环
上个月我把手上一个 agent 应用里的三个 specialist 删了。
不是为了省 token。是那套 orchestrator 加三个 subagent 的结构,每加一个功能我就要改四个地方:路由的分类规则、subagent 自己的 prompt、主 agent 的 prompt(告诉它什么时候该转交给谁)、还有交接时那份字段约定。改完还要赌两边对“用户到底想要什么”的理解一致。
删完跑我们那套没几个 case 的回归,任务完成率没掉,端到端延迟掉了将近一半。
看到 Anthropic 的 Applied AI 团队在 10 月 22 号发的那篇 Building agents: When to fold subagents into your main agent loop,我第一反应不是“又多一个方法论”,而是“原来不只是我们这么干,而且他们把原因写清楚了”。
他们看到的和我看到的是同一件事
文章的论点一句话就能说完:少用点 subagent,把上下文和工具改成按需加载,质量往往会更好,成本和延迟还更低。
这跟我原来的直觉相反。我一开始做这套东西的时候,subagent 在我脑子里是“解耦”的同义词:把复杂的系统拆成职责单一的专家模块,每个模块自己的 prompt、自己的工具、自己的 owner,多干净。这不是软件工程讲了三十年的东西吗?
问题在于,我们习惯的那套拆法假设模块之间传的是精确的东西:函数签名、结构化的数据、明确的接口契约。而 agent 之间传的是自然语言摘要。A 干完活,总结一段话给 B,B 基于这段总结再往下走。每一次交接都是一次有损压缩,而且损失多少你根本看不见。它不会报错,不会抛异常,它只是让最后的结果变差了一点。
Anthropic 管这个叫 telephone game(传话游戏)。这个词挺准的。一个中间人说“用户反映最近两天订单状态没更新”,传到第三个 agent 耳朵里可能就变成了“用户要查订单”,那个“最近两天”和“状态没更新”的因果全没了。
为什么企业里会长出一堆 subagent
这篇文章里最扎我的是它讲失败模式那一段,因为那一段完全是从组织角度说的,不是技术角度。
一个大公司想做一个统一的 agent 入口,接住所有产品能力。但每个能力归不同的团队,于是很自然的一条路是:各团队先各自做一个 agent,然后平台团队在上面盖一个 orchestrator 把大家串起来。
看起来最省事,实际上立刻埋了五个雷:
- 上下文管理:你得决定 agent 之间传什么,传的过程中细节就丢了。
- subagent 泛滥:每个团队都发一个,最后几百个功能重叠的 subagent,没标准,没明确 owner。
- Frankenprompt:每个团队往 system prompt 里加一句自己的规则,加着加着开始互相打架,语气也不统一了。
- 各自为政的 eval:每个团队加一套针对自己子任务的评测,都过分优化了自己那一小块,没人拥有整体。然后老板看着一堆被稀释过的分数做决策。
- 延迟:每多一层嵌套就多一次模型调用,这是实打实的。
文里有个数字:一家客户把多 agent 的 harness 换成单循环之后,运行时快了大概两倍。跟我上面说的“将近一半”差不多是一回事,只不过他们是认真的 A/B,我是拍脑袋。
文章把根因点得很直接:Conway’s law。你的 agent 架构长成了你组织架构图的样子。这话不好听,但我确实在好几个项目里见过——拆分的边界不是按“上下文怎么流动”画的,是按“谁向谁汇报”画的。
现在能折回去,是因为三件事变了
我一直觉得“要不要用 subagent”这个问题没有普适答案,得看是什么年代问的。
两年前不行。那时候上下文窗口就那么点,一个 agent 塞不下七八个领域的知识,塞进去就开始注意力涣散、选错工具。所以拆 subagent 在当时是被迫的,不是因为架构更优雅,是因为上下文装不下。
现在能折,作者给了三个理由,我基本认同:
一,共享上下文确实能出更好的答案。长任务里,前面几步的原始结果都躺在同一个窗口里,模型自己就能把 A 的发现和 C 的发现连起来。而 subagent 模式下,主 agent 手里只有一堆二手摘要,这种跨步骤的联想能力基本被削掉了。这点我做 RAG 类的 agent 时感受很明显:当你把召回结果原样留在上下文里,模型经常能自己发现一些你没让它找的东西。
二,渐进披露(progressive disclosure)把“上下文装不下”这个前提消掉了。这是我觉得整篇文章技术含量最高的一处。思路很朴素:agent 一开始只看到一堆 skill 和 tool 的短描述,需要哪一个才把全文加载进来。上下文里常驻的从“所有领域知识”变成了“所有领域知识的目录”,差了一到两个数量级。
文章里有个数字我看了两遍:他们靠这个(包括 progressively disclosing skills 和 tools)把 Claude Code 在较新模型上的 system prompt 砍掉了 80% 以上。
三,模型自己变强了。从 Opus 4.5 开始,模型在单个循环里能扛的事情比大多数团队预期的要多。而且新模型会自己叙述进度、自己回头检查结果,很多我们以前写死在 harness 里的编排逻辑,现在纯属多余。
这一条我觉得比前两条都重要,也最容易被忽略。它意味着 harness 的复杂度应该跟着模型能力往下走,而不是往上加。文章里有句话我很喜欢:僵化的多 agent 结构,往往是新模型发挥不出来的真正原因。你想让它多做点,结果它被一堆写死的路由和交接协议卡住了。
但别急着把 subagent 全删了
这是我看完最想强调的一点,因为网上转这篇的标题大多挺耸动。
文章明确列了三条仍然该用 subagent 的条件,而且都是可测量的,不是审美判断:
- 单个循环因为上下文膨胀出现了可测量的性能下降;
- 多个任务需要并行,而且用完的上下文可以整个丢掉;
- 单个 agent 选不准工具,或者 system prompt 里存在互相冲突的指令。
我自己的经验是第二条最实在。上个月删的那三个 specialist,都是串行使用的。用户先要查订单,查到订单才可能问物流,问完物流才可能问退款。这种链式的东西放在一个循环里,上下文全是增益,删了当然好。
但另一个项目里我留了一个 subagent 没动,因为它干的是“把三十多份财报 PDF 全读一遍然后给我一个结论”。主 agent 根本不需要那三十份 PDF 的任何一页事后还留在上下文里,它只需要那一段结论。这种“读得远多于用得上”的活,subagent 是天然合适的,它存在的意义就是把一大坨上下文用完之后扔掉。
这也是文章里那个“按上下文切分边界”的说法:分给每个 subagent 的工作,应该是几乎不需要系统其余部分的那种,交回来一个紧凑的结果。符合这个条件的分法是好的,不符合的(按问题类型分,按团队分)就是传话游戏。
折叠的路径,以及一个把我吓到的细节
文章给的迁移路径很务实,没有让你一次重构完:
先有 eval。这个绕不过去,最少 10 条 golden examples 就能起步。中央团队维护一套端到端的,各团队给自己的 skill 带一套小的。还在用 orchestrator 的时候额外看 routing accuracy,折完之后改看“有没有加载对的 skill、有没有调对的 tool”。
然后三种折法,从轻到重:
合并——把经常一起被调用的专家合成一个。判断依据是生产流量,如果大量请求都是 A 之后紧跟 B,那这就是一对紧耦合,可以直接并。
当工具调——保留 subagent,但主 agent 用 tool call 的方式调它,对话还握在主 agent 手里。这个好处是零改动就能拿到 baseline。代价是那些老问题还在:每个专家还是有自己的 prompt 和 owner,每次调用还是一次有损摘要加一层嵌套循环。
真折叠——把 prompt 变成 skill,把 API 调用变成 tool,一次一个,前后对比 eval。
折叠这一步有个注意事项,我看完之后后背有点凉。
文章说:对比的时候别只看总分,要看哪些任务翻转了。他们测样例客服 agent 的时候,折叠之后延迟降了,但有个原本一直通过的流程挂了。原因是主 agent 手里本来就有订单查询工具,它自己查完就答了,没去问物流专家要送达日期。
这个 bug 很典型。它不是崩溃,不是报错,是 agent 变得更“高效”了,自己把活干完了,只是少问了一句本来必须问的话。你如果只看总分,可能整体还涨了两个点,就把这次改动合了。
更麻烦的是这句话:这个回归两次里只出现了一次。
所以他们的建议是,动手之前先给生产里每一条会一起跑的 agent 链、每一条绝不能破的规则都准备评测任务,而且每个任务要跑不止一遍。我之前那套回归是每个 case 跑一次就完事,现在想想纯粹是运气好。
多团队协作的部分,其实是这篇文章的暗线
这篇表面上在讲架构,我觉得它真正想说的是分工。
原来的分工是:每个领域团队做一个 agent,agent 是他们的交付物,也是他们的地盘。
文章建议的新分工是:团队交付的不再是 agent,而是 skill 和 tool。中央留一个小团队,端到端质量和 system prompt 归它管,所有新的 skill、tool、eval 上线前要经过它验一遍。领域团队继续拥有自己的 skill,也继续有自己的 DRI 保证质量。
这个转变的难点不在技术,在所有权。一个团队从“我有个 agent”变成“我有一段 prompt 和几个工具函数”,听起来是降级了。文章没怎么回避这一点,它给的办法是让维护 skill 的成本本身降下来——用 skill 去生成、测试、修剪 skill。/skill-creator 起草和审计,/skill-doctor 看每个 skill 到底花多少钱、被用了几次,然后把没人用的删掉。
关于工具那块有个数字挺有用:超过 30 到 50 个工具定义,模型选工具就开始退化。所以按用户意图分组,别一个 API 一个 tool。
还有个设计我觉得很值得抄:把权限校验放到 tool 内部。每个 tool 自己判断调用者能看什么能改什么,不行就返回一句人话给模型。这样一个循环就能服务不同权限的用户,不需要“一档权限一个 agent”。这个坑我们踩过。早期按角色复制了三份 agent,后面每改一次逻辑要改三遍。
我不太买账的地方
先说一个我觉得被轻描淡写的前提:你的任务大部分是“深而串行、共享上下文”的。如果你的场景天然是宽扇出,比如一次要扫上百个文件、并行验证十个假设、跑一堆互不依赖的子任务——那么 subagent 的价值不是摘要,是吞吐。文章里也承认了这点(“research frontier”),但措辞很轻。我觉得这可能会让一批人误伤自己的系统。
渐进披露也是要付账的。skill 描述写得不好,模型就不知道该加载哪个。这时候你省了上下文,换来的是“选错 skill”。文章里承认这需要纪律,但“描述要能触发”这件事本身很难评测,比传统 prompt 的调优更玄。我的实际体会是,skill 的描述要写得像“什么时候该用我”而不是“我是什么”,这个差别对触发率影响很大。
至于 eval 这件事,说得轻巧。文章自己都承认,在内部系统难以回放、用户行为难以模拟的环境里,做 task-completion eval 非常麻烦。它给的办法是记录关键事件的时间戳,事后回放。这个技巧是实用的,但它意味着你得先把埋点做起来。也就是说,要迁移到单循环,你得先有能力度量现在的系统。这个前置条件的门槛,比“折叠 subagent”本身高得多。
我见过不少团队卡在这儿:架构的道理都懂,但拿不出一个有说服力的数字,于是讨论就变成了品味之争。
最后
文章结尾那段话我觉得比正文更值得记住:
随着模型进化,我们对怎么用它的理解也在变。这意味着任何单一架构都没有背后的原则重要:测量,一次只改一件事,保留经得起验证的东西。
我把它贴在了自己的备忘里。因为“要不要用 subagent”这个问题,未来一定还会被反复问,答案还会再变一次。但“先量一下再改”这件事不会过时。
顺便说,他们放了个配套的参考实现 anthropics/single-agent-loop-kit,把审计、baseline、合并、折叠、当工具调、日常维护串成一个 Claude Code 的 skill,每一步都停下来给你看结论,问你一遍再继续。里面还有个十分钟能跑完的客服 agent 样例,用 KIT_MODEL=fake 可以不花一分钱先验证管道通不通。
如果你手上还没有 subagent,别用这个 kit,直接从一个循环开始写。这话是它 README 自己说的,我觉得挺坦率的。