任务是:「审查一个开源项目最近 10 个 PR,找出其中改动了核心权限逻辑的 PR,为每一个这样的 PR 写一段风险说明。」请回答:
Level 1:给一次代码审查任务画出编排者和子代理的分工- 编排者应该做哪些事?
- 这个任务该怎么扇出——拆成几块、每块大概是什么?
- 子代理完成后,应该往回传什么?编排者收到后要做的「汇总」具体是什么?
学习目标:
- 说清楚编排者-子代理架构里,编排者和子代理各自负责什么
- 解释「上下文隔离」具体隔离的是什么,为什么它能缓解上一课讲的上下文污染和注意力稀释
- 说明为什么子代理应该只把结论回传给编排者,而不是把自己积累的全部思考过程都塞回去
前置要求:完成第 1 课,理解「多 Agent 系统」的定义和适用边界 | 上一课 第 1 课 << | 下一课 第 3 课 >>
上一课判断出「调研三家云服务商定价」这类任务适合拆给多个 Agent,但没细讲这个「拆」具体怎么运作。常见的一种结构叫编排者-子代理架构:官方定义是「一个中心 LLM 动态地拆解任务、把任务委派给多个工作 LLM、再把它们的结果整合起来」。1
这句定义里有三个动作,分别对应编排者要做的三件事:拆解——把一个大任务判断出能拆成哪几块;委派——把每一块连同必要的背景,交给一个子代理去做;整合——等子代理们都返回结果后,把这些结果合成最终答案。编排者自己不下场去读云服务商的定价页面,它的工作是判断怎么分工、分给谁、以及最后怎么把几份结果拼成一份说得通的答案。
子代理这一侧,运作方式和编排者很不一样。官方说得很明确:「每个子代理都从一个全新、独立的上下文窗口开始。它看不到你的对话历史、你已经调用过的技能、以及已经读过的文件。」2 也就是说,子代理不知道你一开始跟编排者说了什么、编排者内部是怎么权衡「要不要拆」「拆成几份」的,它能看到的只有编排者交给它的这一份任务说明。
这一点看起来像是限制,其实正是上一课那两个问题的解药。子代理的上下文里没有编排者的完整对话历史,自然也就没有编排者在别处踩过的坑、看到过的无关信息——上下文隔离:把每个 Agent 的工作范围限定在一个独立的上下文窗口内,一个 Agent 里发生的上下文污染,不会传染到另一个 Agent 里。子代理手上只有自己那一份任务要处理的资料,不用同时兼顾三家公司的全部内容,注意力稀释的压力也跟着降下来。至于怎么把一份任务说明写得足够清楚、让子代理不用看到对话历史也能独立把活干好,下一课会具体讲。
回到调研三家云服务商定价的例子。编排者拆解出「查第一家」「查第二家」「查第三家」三块任务之后,不是排队一个一个做,而是同时把这三块任务派发出去——官方系统里的做法正是如此:主导 Agent 并行启动 3 到 5 个子代理,而不是串行一个个来3。这个「同时往外派」的动作就叫扇出:编排者把拆好的几块子任务,并行分发给对应数量的子代理,让它们各自独立、同时开始工作,而不是等第一个子代理做完了再派第二个。
扇出带来的好处很直接:三个子代理并行工作,总耗时接近做完一份调研的时间,而不是三份调研时间的总和——官方系统在引入这类并行化改进后,复杂查询的调研耗时最多缩短了 90%3。但扇出不是把任务硬切成几份就完事——切法本身有讲究,比如三家公司天然独立,切三份很自然;如果换成「审查一份 20 页的合同」,条款之间可能互相引用、互相制约,切法不当反而会让子代理各自缺失关键上下文,做出前后矛盾的判断。判断怎么切、切多细,仍然要回到上一课的判断标准:切出来的每一块,是不是真的能独立处理、不依赖其他块的中间结果。
三个子代理各自查完自己那一家公司的定价,把结果交回来之后,编排者要做的不是把三段文字原样拼在一起。子代理返回的是各自视角下的调研结论,编排者要做的是汇总:把几份独立产出的结果放在一起比较、消解掉可能存在的重复或矛盾之处、按最终要交付的形式重新组织,写出一份读起来是一个整体、而不是三段拼接痕迹很重的文档。
官方文档在讲子代理顺序接力时提到:「每个子代理完成自己的任务后,把结果返回给 Claude,Claude 再把相关的上下文传给下一个子代理。」2 由此可以看出,汇总不一定是「等所有子代理都交卷、编排者一次性收齐再处理」这么简单——有些场景下,前一个子代理的结果本身就是后一个子代理任务说明的一部分,编排者在扇出和汇总之间来回切换,直到所有子任务都有了结果。
结果的传递路径也不一定非要经过编排者中转。当子代理产出的内容本身体量很大、又需要被原样保留时,官方提到过一种做法:「让子代理把输出直接写入文件系统,以此把『层层转述』的信息损耗降到最低——某些类型的结果可以绕过主协调者直接产出,这样既保真又省性能开销。」3 直接写文件系统这一步,本质上是在避免结果在「子代理→编排者→最终输出」这条链路上被转述、压缩、丢失细节。
子代理为了完成任务,中间可能读了很多页无关紧要的内容、试过几条走不通的思路、甚至犯过几次小错误又自己纠正回来。这些过程本身不需要——也不应该——原样塞回编排者的上下文里。编排者需要的是子代理最终站得住脚的结论,以及支撑这个结论的关键依据,而不是那段完整的、包含弯路的推理过程。
原因回到第 1 课讲过的道理:编排者自己也有一个上下文窗口,也会经历上下文污染和注意力稀释。官方文档对此有直接提醒:子代理完成后结果会返回主对话,多个子代理各自回传详细结果,会消耗可观的上下文2。如果三个子代理各自几千字的完整思考过程都原样塞回编排者,编排者反而在自己这一层重新遇到了当初想靠多 Agent 缓解的问题。结果回传应该只携带结论本身,把「怎么得出这个结论」的细节留在子代理自己已经用完、即将丢弃的上下文里。
这不代表所有委派场景都从零开始。官方文档里还提到一种特殊的子代理类型——fork:「fork 是一种继承了目前为止全部对话历史的子代理,而不是从零开始……fork 自己的工具调用仍然不会进入你的主对话,只有它的最终结果会被带回来,这样你的主上下文窗口能保持干净。」2 也就是说,即便一个子代理罕见地需要看到完整历史(比如需要基于此前的全部讨论做一次深度总结),它中间的思考过程依然不会原样进入编排者的上下文——「只回传结论」这条原则是稳定的,变的只是子代理起步时手上有没有历史背景。
「编排者-子代理」不是某一家的专属说法。OpenAI 的 Agents SDK 文档里把同样的结构称为 Manager 模式:「一个中心管理者/编排者把专门的子代理当作工具来调用,并且始终掌控着整个对话。」4 换了个词——manager 对应编排者、agents-as-tools 对应子代理——描述的仍然是同一件事:一个中心节点负责拆任务、派工、掌控全局,具体执行交给专门的下级去做,下级做完把结果交回来,中心节点继续掌控接下来的走向。认出这套分工的本质,比记住某一家框架的具体术语更重要——你会在几乎所有多 Agent 框架的文档里看到这套逻辑的某种变体。
Building effective agents(Anthropic Engineering) — https://www.anthropic.com/engineering/building-effective-agents ↩ ↩2
Create custom subagents(Claude Code Docs) — https://code.claude.com/docs/en/sub-agents ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
How we built our multi-agent research system(Anthropic Engineering) — https://www.anthropic.com/engineering/multi-agent-research-system ↩ ↩2 ↩3 ↩4
Agents(OpenAI Agents SDK) — https://openai.github.io/openai-agents-python/agents/ ↩ ↩2
Jot down thoughts, sticking points, things you didn't get. Written to this course's appendix only — the lesson file is never touched.