子代理不是越多越好:先管理上下文,再谈并行

过去一段时间,代理架构流行一种做法:能拆就拆,能并行就并行。一个任务分给多个子代理,看起来更“先进”,也更容易在演示中显得能力强。但越来越多团队在实践中发现,子代理数量增加并不自动带来质量提升,反而常常让系统更慢、更贵、更难维护。

问题的根源在于:很多人把子代理当成了分工工具,而不是上下文管理工具。一旦动机从“隔离上下文”变成“划分领地”,架构就会开始变形。

子代理的本质:隔离上下文,而不是划分领地

每轮对话结束都可以看作一个分支点:继续、回退重试、清空重开、压缩历史,或者把下一块工作交给子代理。除了“继续”,其他动作本质上都在管理上下文。

为什么要管理上下文?因为上下文越长,模型越容易被早期无关信息带偏,出现所谓的“上下文腐化”。超长上下文在达到数十万 token 后,可能开始出现明显衰减,具体取决于任务,并没有统一硬规则。

从这个角度看,子代理的价值是:启动一个干净上下文去处理杂乱工作,只把结论带回来。判断是否适合交给子代理,有一个简单问题:

之后还需要查看原始中间输出,还是只需要一个结论?

只有“只需要结论”的工作,才适合交给子代理。如果理由是“这属于另一个团队”或“这是另一类问题”,那通常不该拆。按问题类型拆分,很容易导致有损交接。

拆得太多,为什么会变差

子代理过多常见几类代价:

  • 有损交接。 代理之间通过摘要来回传递信息,每次交接都会丢细节,最后变成传话游戏。
  • 子代理泛滥。 每个团队都发布自己的子代理,功能重叠、标准不一、无人负责整体。
  • 系统提示冲突。 每个团队往提示词里加规则,规则互相矛盾,对外表现不一致。
  • 评估碎片化。 每个团队只评估自己那一块,局部分数很好,但没人对端到端质量负责。
  • 延迟叠加。 每多一层代理就多一轮模型调用,多代理设置常常比单循环更慢。
  • 架构映射组织图。 每个团队一个代理、每类问题一个代理,架构变成组织架构的翻版。

反过来,单主循环在今天更有竞争力,原因也很实际:

  1. 共享上下文,答案更完整。 主代理看过每一步原始结果,能直接连接信息,不依赖多次摘要交接。
  2. 按需加载,上下文不会爆炸。 技能、规则和工具只在需要时完整加载,平时只暴露简短描述。过去拆子代理的一个重要理由是怕提示词装不下,现在这个理由大多不再成立。
  3. 模型能力在提升。 新模型在单循环内能处理的事情比多数团队预期更多。硬编码工作流越多,模型发挥空间反而越小。

还有一个容易忽略的工程细节:工具定义超过 30–50 个后,模型选择工具的质量会下降。应围绕用户意图合并工具,而不是一个 API 对应一个工具。

什么时候仍然应该拆

默认使用主循环,只有在以下条件明确满足时才考虑拆分:

  1. 单循环因上下文增长出现可测量的质量下降。 需要评估数据,不能只靠感觉。
  2. 有多项可并行、可丢弃的工作,每项都需要干净上下文。 例如互不相关的研究线程。
  3. 主代理反复选错工具,或系统提示中的指令互相冲突。

即使决定拆分,边界也很重要:沿上下文切,不要沿问题类型切。 好的子任务几乎不依赖系统其余部分,并返回紧凑结果,例如一个判定、一个列表、一个小型结构化对象。独立研究、接口清晰的组件、黑盒验证,都是合适的切分点。

拆出的子代理最好作为工具暴露给主代理,让主代理继续掌握与用户的对话。只有子代理确实需要直接面对用户时,才值得把整个对话交出去。

拆分前,先找更便宜的修复

在启动子代理之前,先检查三件事:

  • 工具太多? 按用户意图合并工具,把不常用的工具延迟到工具搜索之后。
  • 提示词太大? 把流程和规则转成按需加载的技能,把操作和实时数据转成工具,把参考资料转成按需读取的内容。
  • 担心丢状态? 把计划、决策和审查结论写进设计文档或进度文档。状态一旦落在文件里,会话就可以安全清空,“为了保护上下文而拆分”的冲动也会大幅减少。

两个通用实践

独立审查:写代码和审代码不共享上下文

AI 写代码越来越快,代码质量如何守住?一个有效做法是:写代码的代理和审查代码的代理不共享上下文。

原因是,编码代理一路上做了很多决定,并说服自己接受这些决定。如果审查者继承同一段对话,就会沿着同一推理线看代码,作者漏掉的问题,审查者也很可能漏掉。只有从干净上下文开始,审查者才能真正从外部看变更。

具体可以这样做:

  • 只给审查者三样东西:变更 diff、需求、测试结果。
  • 不给作者对话和中间推理。审查者要回答的是“变更是否满足需求”,不是“作者推理是否成立”。
  • 结论以结构化反馈返回主循环,例如列出问题、位置和理由。主代理不照单全收,而是对照真实代码和测试逐点复核,只修复站得住脚的问题。

一个典型例子:编码代理早期设定“这个函数的调用方都会做空值检查”,之后所有推理都建立在这个前提上。让它自审,它会沿同一前提看问题;独立审查者只拿 diff 和需求,就会直接问:如果这个值为空会怎样?

这就是黑盒验证:干净的子任务边界,紧凑的结论返回,典型地沿上下文切分。

日常开发:一个主循环,技能按需加载

日常编码中,尽量一个会话只做一个任务,不额外拆子代理。团队反复使用的工作流和诀窍,写成技能或项目规则文档,平时只暴露一行描述,真正需要时再完整加载。主循环始终能看到需求、计划和每一步原始结果,不依赖来回传递的摘要。

通常值得沉淀的内容包括:

  • 编码规范:命名、目录结构、错误处理。
  • 发布流程:发布前跑哪些检查,按什么顺序。
  • 内部库用法和坑:哪个接口有隐藏前置条件,哪个模式以前出过问题。
  • 验证和测试步骤:改动后如何跑测试,如何确认真的修好。

这些内容放进按需加载的技能,而不是让一个专职子代理“负责规范”或“负责发布”,主代理需要时自己读,少一次交接。

另外,不要让重要状态只存在于对话中。长任务开始时创建设计或进度文档,持续写入计划、关键决策、被否决的选项和审查结论。新会话开始或别人接手时,读文档就能继续,不必翻聊天记录。状态已经在文档里,也可以放心清空会话重新开始。

已经有一堆子代理,如何合并回来

如果系统已经有很多子代理,不建议一夜重写,可以按步骤收敛:

  1. 先做小型端到端评估。 少量黄金示例就足够起步。合并前检查路由准确率,合并后检查主代理是否加载正确技能、调用正确工具。
  2. 先合并最常用、耦合最紧的。 经常背靠背调用、读写同一数据、或一个输出喂给另一个输入的子代理,优先合并。
  3. 过渡期把剩余子代理包装成主代理的工具。 不必先重写,同时获得基线。
  4. 一次只合并一个。 把它的提示词改写成技能,把外部调用改造成工具,比较合并前后评估。
  5. 不要只看总分,要看哪些任务发生翻转。 有的问题会表现为延迟下降但某个流程坏掉,例如主代理手里有查询工具就直接回答,跳过了原本必要的专业步骤。
  6. 每个任务多跑几次。 有些问题只在两次运行中的一次出现。生产环境中每个关键代理链、每条不能破的规则,都应有对应评估任务。

核心原则是:先测量,一次只改一件事,保留通过测试的东西。 只有当合并版本可测量地变差时,才保留子代理;否则继续合并下一个。

拆分前自检清单

  • 这个子任务的中间输出之后还会被需要吗?只有只需要结论时才适合拆分。
  • 拆分的理由是上下文管理,而不是“这是另一个团队”或“另一类问题”。
  • 有评估数据表明单循环确实变差,而不只是直觉。
  • 工具定义是否已经超过 30–50 个?先按用户意图合并,并做延迟加载。
  • 工作流和规则是否已经转成按需加载的技能?操作和实时数据是否已经工具化?参考资料是否按需读取?
  • 计划、决策和审查结论是否写进了设计或进度文档,而不是只留在对话里?
  • 合并前后是否跑了端到端评估,是否查看了发生翻转的任务,是否每个任务运行不止一次?

结语

是否拆子代理只是表面问题。底层只有一件事:在正确的时间,把正确的信息放进上下文。属于主循环的放主循环,该沉淀到技能和文档的沉淀下来,只把真正需要隔离的工作交给子代理。

模型仍在快速进步,今天合理的架构几个月后未必合理。比具体结构更值得坚持的是方法:先测量,一次只改一件事,保留通过测试的东西。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容