第 11 章 Sub-Agent 协作与编排

核心命题:当单 Agent 的认知带宽逼近物理极限,分工不再是工程优化项,而是长程任务得以完成的唯一路径。Sub-Agent 不是"多挂几个工具"那么简单,它是一套关于职责切分、上下文隔离、结果整合的完整工程哲学。本章将从原理到实现,把 Sub-Agent 协作与编排的全貌拆解给你看。


11.0 引子:一个人写不完一本书

让我们从一个真实的场景说起。

你在写一本 30 万字的技术书。全书 15 章,每章平均 2 万字,每章内部又有 8-12 个小节,每个小节里要穿插代码、图表、案例、引文。如果你一个人顺序写下去,每天写 5000 字,需要 60 天;如果再算上调研、改稿、润色、推翻重来,保守估计 4-6 个月。

更致命的是:写到第 8 章时,你已经记不清第 2 章的细节;写到第 12 章时,前面章节的术语命名、章节风格、论证脉络早已在上下文里被压缩成模糊的影子。单 Agent 的"个人英雄主义"在长程任务面前,是一种物理上不可持续的工作方式

这本书的写作过程,本身就是一个长程任务的缩影:

  • 认知带宽受限:人脑(或单 Agent 的工作记忆)同时能处理的概念数量有限
  • 上下文窗口有限:前文信息会被压缩、遗忘或失真
  • 专业分工必要:调研、写作、审校、配图、排版,是不同的技能栈
  • 并行机会存在:第 3 章和第 7 章之间如果没有强依赖,可以并行推进

解决这个问题的工程答案,就是 Sub-Agent 协作与编排。把一个长程任务,按职责、按阶段、按依赖关系切分给多个专职 Agent,每个 Agent 拥有独立的上下文、独立的工具、独立的会话,最后由一个协调者把结果整合起来——这本质上是把人类组织架构的智慧搬到 Agent 系统里

但这里有一个深刻的不对称:人类组织架构是几千年试错沉淀的产物,而 Agent 编排是个新事物,我们还没有足够的时间去沉淀"最佳实践"。本章要做的,就是把已有的认知(包括 Claude Code、AutoGen、LangGraph、OpenAI Swarm 等框架的实践)系统化、原理化,让你能据此设计自己的 Sub-Agent 系统。


11.1 为什么需要 Sub-Agent

11.1.1 单 Agent 的认知带宽限制

我们先做一个思想实验。假设你有一个拥有 200K token 上下文窗口的强大 Agent,你让它完成一个复杂任务:“调研 5 个 AI 框架的最新进展,对比它们的架构差异,写一份 5000 字的评估报告,并给出选型建议”。

这个任务看起来不大,但展开后其实包含:

  1. 5 次独立的调研子任务(每个框架一次 web 搜索 + 文档阅读 + 信息抽取)
  2. 1 次横向对比(把 5 份调研结果放在一起做矩阵分析)
  3. 1 次报告撰写(按用户指定的结构组织输出)
  4. 1 次选型推理(基于对比矩阵做决策)

每一步都消耗上下文。光是 5 次调研,把搜索结果原文都塞进上下文,可能就吃掉了 80K token。等到要写报告时,前面的细节已经模糊;等到要做选型推理时,对比矩阵的某些单元格已经被覆盖。

这就是认知带宽限制的本质:单 Agent 在长程任务中,不是"能力不足",而是"注意力不足"。模型参数足够大、推理能力足够强,但上下文窗口是物理边界,超过这个边界的信息要么被压缩、要么被遗忘、要么根本进不来。

金句:单 Agent 的极限不是模型能力,是上下文窗口。Sub-Agent 不是用来"变强"的,是用来"扩容"的。

11.1.2 上下文窗口的物理约束

让我们把上下文窗口这件事讲透。

模型 上下文窗口 等价于多少页书
GPT-3 (2020) 4K token 约 8 页
Claude 2 (2023) 100K token 约 200 页
GPT-4 Turbo (2024) 128K token 约 256 页
Claude Sonnet 4 (2025) 200K token 约 400 页
Gemini 1.5 Pro (2024) 1M token 约 2000 页
Claude (with auto compact) 实际有效 ~1M 约 2000 页

看起来很大?不。我们来看看真实任务的上下文消耗:

任务类型 单次上下文消耗 备注
一次简单问答 1-3K 几乎不消耗
一次代码修改(读 1 文件 + 改 + 写) 5-15K 中等
一次 web 搜索(含搜索结果原文) 10-30K 单次搜索就吃掉
一次多文件重构(10 个文件) 50-150K 接近窗口上限
一次端到端 bug 修复(含日志、堆栈、相关代码) 30-80K 中等偏上
一次长文档生成(30K 字 + 引用资料) 80-200K 极易触顶

也就是说,即便你有 200K 的窗口,做一个像样的多步骤任务,也常常逼近上限。一旦逼近上限,会发生什么?

  1. 自动压缩(auto-compact)触发:早期的对话被总结成几句话,细节丢失
  2. 注意力衰减:即便信息还在窗口里,模型对靠前位置的细节注意力下降("lost in the middle"现象)
  3. 指令遵循降级:当上下文里塞满参考资料,模型对原始指令的遵循度下降
  4. 幻觉概率上升:找不到的信息,模型可能"脑补"补齐

Sub-Agent 的价值,就在于把一个 200K 都装不下的任务,切成 5 个 40K 能装下的子任务。每个 Sub-Agent 在自己的窗口里干净利落地完成本职工作,主 Agent 只需要接收"结果摘要"而非"原始资料"。

金句:上下文窗口是"房间大小",Sub-Agent 是"分房间办公"。与其让一个人挤在一间屋子里处理所有资料,不如分给五个人各占一间,每间屋子里只放该做的事。

11.1.3 专业分工的工程必然

工程世界里,分工从来不是奢侈品,是必需品。看看软件工程的组织方式:

时代 组织方式 分工粒度
1950s 一个程序员包打天下 无分工
1970s 系统分析师 + 程序员 2 个角色
1990s PM + 架构师 + 开发 + 测试 + 运维 5 个角色
2010s 前端 + 后端 + DBA + SRE + 安全 + 数据 6+ 个角色
2020s 全栈 + DevOps + SRE + 安全 + ML + 平台 更细

为什么分工越来越细?不是因为人越来越懒,而是因为系统复杂度上升,单一角色的认知带宽撑不住。一个"全栈工程师"在 2010 年还能 cover 一个小项目的前后端,到 2024 年的微服务 + K8s + 前端框架升级 + 安全合规 + 数据中台,全栈已经是不可能完成的任务。

Agent 系统正在重走这条路。早期的 Agent 是"一个 Agent 包打天下"——一个 Claude/GPT 加上几个工具,就能处理大部分任务。但随着任务复杂度上升:

  • 需要搜索?加 web 工具
  • 需要执行代码?加 Python runtime
  • 需要改文件?加 fs 工具
  • 需要看图?加 vision
  • 需要长记忆?加 retrieval
  • 需要多步推理?加 chain-of-thought

工具越加越多,问题随之而来:

  1. 工具描述本身就吃掉大量上下文(每个工具 schema 200-500 token,30 个工具就是 6-15K)
  2. 模型在工具选择上出错(30 个工具里选 1 个比 5 个工具里选 1 个难得多)
  3. "工具膨胀"导致决策质量下降(心理学上的"选择悖论"在 LLM 上同样存在)

Sub-Agent 是分工的工程答案:与其让一个 Agent 拿着 30 个工具样样都做,不如让 5 个 Sub-Agent 各拿 6 个工具各做一样。这就是"专业分工的工程必然"在 Agent 世界的投射。

金句:工具数量和上下文消耗是一对矛盾。Sub-Agent 不是把工具变多,是把工具分门别类地装进不同的脑袋

11.1.4 “一个人写不完一本书”——多 Agent 并行分工

回到开头的"写书"例子。这件事特别能体现 Sub-Agent 的两大价值:

价值一:并行。一本书 15 章,如果章与章之间弱耦合,理论上可以 15 个 Sub-Agent 同时开写。即使每个 Sub-Agent 写一章需要 1 小时,15 章顺序写要 15 小时,并行写只要 1 小时多。并行带来的不是边际加速,是数量级加速

价值二:隔离。第 3 章的 Sub-Agent 不需要知道第 11 章在写什么,它的上下文里只有"第 3 章的提纲 + 第 3 章的参考资料 + 第 3 章的写作要求"。这种隔离让每个 Sub-Agent 都能在自己的窗口里充分展开,不会因为"全书上下文"而被压缩。

并行和隔离都是有代价的

  • 并行需要结果合并策略(15 份初稿怎么拼成一本连贯的书?)
  • 隔离需要接口规范(每章的 Sub-Agent 必须遵守统一的术语、风格、引文格式)
  • 失败需要统一处理(第 7 章 Sub-Agent 写崩了怎么办?整本书卡住还是跳过?)

这些代价,正是"Sub-Agent 协作与编排"要解决的核心问题。本章后半部分会逐一展开。


11.2 Sub-Agent 的设计哲学

哲学不是空话。Sub-Agent 的设计哲学决定了你写出来的代码长什么样、能扛多大任务、出问题时怎么排错。这一节是全章的"道",后面的"术"都从这里推导。

11.2.1 单一职责原则

Single Responsibility Principle, SRP——这个概念来自软件工程的 SOLID 原则,原意是"一个类应该只有一个引起它变化的原因"。把它迁移到 Sub-Agent 上:

一个 Sub-Agent 应该只承担一类职责,只对一类任务负责。

"一类职责"是什么粒度?看下表:

粒度 例子 评价
过粗 “代码 Sub-Agent” 一个 Agent 既写代码、又审代码、又部署,等于没分
适中 “code-reviewer Sub-Agent” 专门做代码审查,输出审查意见
适中 “web-researcher Sub-Agent” 专门做 web 调研,输出结构化调研报告
过细 “Python-函数-命名-Sub-Agent” 只负责给 Python 函数起名,过度细化

判断粒度是否合适的经验法则:

  1. 能否一句话描述这个 Sub-Agent 的职责? 不能 → 过粗
  2. 这个 Sub-Agent 的输出是否能被主 Agent 直接使用? 不能 → 过细
  3. 它是否需要多个工具协同? 不需要 → 可能不需要 Sub-Agent
  4. 它是否拥有独立的"专业知识"(系统提示)? 没有 → 可能不需要 Sub-Agent

金句:单一职责不是"只做一件事",是"只对一类目标负责"。code-reviewer 可能做很多事(读代码、跑 lint、查规范),但它的目标只有一个——给出审查意见。

11.2.2 松耦合通信

Sub-Agent 之间不应该"互相窥探对方的脑子"。松耦合意味着:

  • 主 Agent 与 Sub-Agent 之间通过明确的消息通信,而非共享变量
  • Sub-Agent 之间默认不直接通信,需要时通过主 Agent 中转或共享黑板
  • Sub-Agent 的内部状态不暴露给外部,只暴露输入/输出契约

看一个对比:

紧耦合(反模式)

主 Agent 调用 coder Sub-Agent
  → coder 直接读取 reviewer 的内部 reasoning
  → reviewer 直接修改 coder 的代码文件
  → 两个 Sub-Agent 共享同一份工作内存

松耦合(正模式)

主 Agent 调用 coder Sub-Agent
  → coder 返回代码 diff
主 Agent 调用 reviewer Sub-Agent(输入:coder 的 diff)
  → reviewer 返回审查意见
主 Agent 调用 coder Sub-Agent(输入:审查意见 + 原 diff)
  → coder 返回修改后的 diff

松耦合的代价是消息往返开销,但收益是可推理、可重放、可独立测试。当一个 Sub-Agent 出问题,你不需要看其他 Sub-Agent 的状态,只需要看输入和输出。

11.2.3 独立上下文

每个 Sub-Agent 应该有:

  • 独立的 session id:不复用主 Agent 的对话历史
  • 独立的系统提示:根据职责定制
  • 独立的工具集:只装它需要的工具
  • 独立的工作目录(如果涉及文件):避免互相覆盖
  • 独立的 token 配额:避免一个 Sub-Agent 把预算吃光

独立上下文最深刻的价值,是"心态隔离"。一个 Agent 在做"创意发散"时,它的系统提示、温度参数、上下文都倾向于"打开思路";而做"严格审查"时,又倾向于"挑刺"。如果把两个角色塞进同一个 Agent,模型会在两种心态之间来回切换,结果是既发散得不彻底,也审查得不到位。

金句:Agent 也有"心态"。把发散者和收敛者放进同一个脑子,等于让一个人同时扮演天使和魔鬼——结果必定是平庸的折中。

11.2.4 可独立验证

一个设计良好的 Sub-Agent,应该能够被单独调用、单独测试、单独评估。这意味着:

  • 它的输入是结构化的(JSON schema 或明确的文本契约)
  • 它的输出是结构化的(可被程序解析或下一个 Agent 直接使用)
  • 它有独立的测试用例(golden case + edge case)
  • 它有独立的可观测性(日志、metrics、trace)

如果某个 Sub-Agent 必须依赖主 Agent 的"前置思考"才能工作,那它不是一个好的 Sub-Agent,应该重新设计接口。

┌──────────────────────────────────────────────────────────┐
│  Sub-Agent 设计四原则的依赖关系                            │
│                                                          │
│     单一职责 ──┐                                          │
│                ├──> 独立上下文 ──> 可独立验证              │
│     松耦合 ────┘                                          │
│                                                          │
│  单一职责是前提;松耦合是手段;                            │
│  独立上下文是结构保证;可独立验证是工程落地。              │
└──────────────────────────────────────────────────────────┘

11.3 Sub-Agent 的角色分类

Sub-Agent 不是"随便切几刀"。根据职责性质,可以归为四大类。不同类别的 Sub-Agent,设计要点完全不同。

11.3.1 执行型 Sub-Agent

特征:负责"把事情做出来",输出是产物(代码、文档、数据)。

代表角色 输入 输出 典型工具
coder 需求描述 + 文件路径 代码 diff / PR fs, bash, git
researcher 调研问题 调研报告 web_search, fetch
tester 代码 + 测试要求 测试用例 + 执行结果 bash, pytest
doc-writer 主题 + 大纲 文档 fs, web_search
data-analyst 数据集 + 分析目标 分析报告 + 图表 python, pandas

执行型 Sub-Agent 的设计要点:

  1. 工具集要"够用且只够用":coder 不需要 web_search(除非要查 API 文档),researcher 不需要 fs 写权限
  2. 输出契约要明确:coder 输出 diff 还是完整文件?researcher 输出 markdown 还是 JSON?提前定死
  3. 失败要可识别:执行型 Sub-Agent 失败是常态(代码跑不通、搜索没结果),必须有明确的失败信号

11.3.2 验证型 Sub-Agent

特征:负责"检查别人做的事对不对",输出是判断 + 理由

代表角色 输入 输出 设计要点
code-reviewer 代码 diff 审查意见 + approve/request_changes 不能修改代码,只能给意见
critic 论证或方案 批评意见 + 改进建议 系统提示偏"挑刺",温度低
judge 多个候选方案 排序 + 选择理由 需要明确评分标准
fact-checker 声明 + 来源 真伪判定 + 证据 必须给可验证的证据
security-auditor 代码 / 配置 漏洞列表 + 修复建议 专注于安全维度

验证型 Sub-Agent 的设计要点:

  1. 只读权限:验证型 Sub-Agent 默认不应有写权限,否则它会"自己改自己批"
  2. 独立的系统提示:偏严格、偏挑刺、低温(0-0.3)
  3. 必须给理由:不能只输出"通过/不通过",必须给可追溯的依据
  4. 可对抗:让验证型 Sub-Agent 和执行型 Sub-Agent 形成对抗,避免合谋

金句:验证型 Sub-Agent 的核心价值,是给系统装上"怀疑的镜子"。它不是来夸你的,是来照出你看不到的瑕疵的。

11.3.3 协调型 Sub-Agent

特征:负责"调度其他 Agent",输出是任务分派 + 结果整合

代表角色 输入 输出 设计要点
orchestrator 总任务 子任务列表 + 分派计划 需要规划能力
planner 模糊目标 可执行的步骤树 需要拆解能力
router 用户请求 路由到哪个 Agent 需要分类能力
summarizer 多份结果 整合后的最终输出 需要归纳能力

协调型 Sub-Agent 的设计要点:

  1. 不做具体活:协调型 Agent 不应该自己写代码、自己搜索,它只调度
  2. 拥有全局视图:它需要看到所有 Sub-Agent 的状态和结果摘要
  3. 决策可解释:分派决策要可追溯(“为什么把这个子任务给 coder 而不是 researcher”)

协调型 Sub-Agent 是最玄学的一类。协调得好,整个系统丝滑顺畅;协调得差,整个系统陷入"Agent 互相对话死循环"。AutoGen 早期的多 Agent 对话模式,就常常出现两个 Agent 互相客套十几个回合还没干正事的现象。

11.3.4 专项型 Sub-Agent

特征:针对特定领域特定工具进行深度定制,输出是该领域的专业产出

代表角色 专项领域 为什么独立
web-researcher 网页搜索 + 内容抽取 搜索结果原文巨大,必须独立窗口处理
browser-agent 浏览器自动化 需要状态机式的页面操作
vision-agent 图像理解 需要多模态能力
sql-agent 数据库查询 需要 schema 感知 + SQL 生成专精
devops-agent 部署运维 需要 K8s/Docker 专业知识
legal-agent 法律文本 需要法律领域知识库

专项型 Sub-Agent 的设计要点:

  1. 领域知识注入:系统提示里要塞领域知识(“你是一个资深 SRE,熟悉 K8s…”)
  2. 领域工具配套:sql-agent 配 SQL 执行器,devops-agent 配 kubectl
  3. 领域边界明确:不要让 sql-agent 去写代码,也不要让 devops-agent 去查数据库

11.3.5 四类角色的对比

维度 执行型 验证型 协调型 专项型
主要产出 产物 判断 调度 专业产出
工具数量 少(只读) 少(无业务工具) 多(领域工具)
系统提示风格 务实 严格 全局 专业
温度参数 中(0.3-0.7) 低(0-0.3) 中低(0.2-0.5) 领域相关
失败概率
是否可并行
典型数量 少(1-2) 1 视任务

金句:四类角色不是"四种 Agent",是"四种职责"。一个真实的 Sub-Agent 可能同时具备多个职责(如 coder 兼具执行 + 自验证),但主职责必须只有一个


11.4 编排模式谱系

有了 Sub-Agent,还要决定怎么把它们组织起来。这就是"编排模式"。编排模式决定了系统的复杂度、可靠性、延迟、成本——它是 Sub-Agent 系统的"骨架"。

11.4.1 串行编排(Pipeline)

形态:Sub-Agent 顺序执行,前一个的输出是后一个的输入。

[主 Agent]
   │
   ▼
[coder] ──diff──> [reviewer] ──review──> [fixer] ──final──> [主 Agent]

适用场景

  • 任务有天然的阶段顺序(写→审→改)
  • 每阶段的输出是下阶段的明确输入
  • 不需要并行加速

优点

  • 简单,最容易实现
  • 每阶段可独立调试
  • 失败定位容易(卡在哪一阶段一目了然)

缺点

  • 总延迟 = 各阶段延迟之和
  • 没有并行加速
  • 任意阶段失败会阻塞整条流水线

典型例子

  • 写代码 → 代码审查 → 修复 → 再次审查
  • 调研 → 写稿 → 润色 → 校对
  • 数据采集 → 清洗 → 分析 → 报告

11.4.2 并行编排(Fan-out / Fan-in)

形态:主 Agent 把任务拆成多个独立子任务,分派给多个 Sub-Agent 并行执行,最后汇总结果。

                ┌── [researcher-A] ──┐
                │                     │
[主 Agent] ────┼── [researcher-B] ──┼──> [summarizer] ──> [主 Agent]
                │                     │
                └── [researcher-C] ──┘

适用场景

  • 子任务之间相互独立(不强依赖)
  • 子任务粒度相似(避免长尾拖累整体)
  • 需要并行加速

优点

  • 总延迟 ≈ 最慢子任务的延迟(而非总和)
  • 吞吐量高
  • 容错性好(一个 Sub-Agent 挂了不影响其他)

缺点

  • 结果合并复杂(5 份调研怎么去重、消歧、整合?)
  • 主 Agent 的整合负担重
  • 子任务粒度不均时容易"短板效应"

典型例子

  • 多源调研(5 个框架各派一个 researcher)
  • 多文件并行修改(10 个文件分给 10 个 coder)
  • 多语言翻译(一份文档分给多种语言的 translator)

11.4.3 层级编排(Hierarchical)

形态:Sub-Agent 嵌套,主 Agent 调用中层 Agent,中层 Agent 再调用底层 Agent,形成树状结构。

                [主 Agent / orchestrator]
                /                       \
       [planner-A]                 [planner-B]
       /        \                  /        \
  [coder]   [tester]          [researcher] [doc-writer]

适用场景

  • 任务复杂度极高,单层编排装不下
  • 存在天然的层级结构(“项目 → 模块 → 任务”)
  • 不同层级需要不同的协调粒度

优点

  • 可扩展性强(可以无限嵌套)
  • 局部失败局部处理,不污染全局
  • 每层只关心自己这层的事,认知负担小

缺点

  • 实现复杂度激增
  • 调用链长,端到端可观测性差
  • 容易过度设计(“为了编排而编排”)
  • token 消耗大(每层协调都要消耗)

典型例子

  • 大型软件项目的"总指挥 → 模块负责人 → 工程师"结构
  • 多 Agent 写书:“主编 → 章节编辑 → 段落作者”
  • 复杂科研:“总研究方向 → 子课题 → 具体实验”

11.4.4 对抗编排(Maker-Checker)

形态:两个角色对立的 Sub-Agent 互相博弈,一个生成、一个挑战,多轮迭代直到收敛。

   ┌───────> [maker 生成] ───────┐
   │                              │
   │                              ▼
[主 Agent]                    [checker 挑战]
   ▲                              │
   │                              │
   └────── [修改并迭代] <─────────┘

适用场景

  • 任务质量要求高,单次生成不可靠
  • 存在明确的"好坏标准"可被 checker 验证
  • 愿意为质量付出多轮迭代成本

优点

  • 输出质量高(多轮打磨)
  • 自动收敛到质量标准
  • 自带质量保证(checker 就是质量门禁)

缺点

  • 成本高(多轮调用)
  • 可能不收敛(maker 一直改不好,checker 一直不满意)
  • 需要明确的收敛条件(否则死循环)

典型例子

  • 代码生成 + 安全审计的对抗
  • 论文写作 + 同行评审的对抗
  • 翻译 + 母语审校的对抗

11.4.5 黑板模式(Blackboard)

形态:所有 Sub-Agent 共享一个"黑板"(共享内存 / 共享文件 / 共享消息队列),每个 Agent 根据黑板上的当前状态决定是否行动,结果写回黑板。

              ┌─────────────────────────┐
              │     共享黑板(黑板)       │
              │  ┌───────────────────┐  │
              │  │ fact-1: ...       │  │
              │  │ fact-2: ...       │  │
              │  │ hypothesis-1: ... │  │
              │  │ open-questions: . │  │
              │  └───────────────────┘  │
              └─┬──────┬──────┬──────┬──┘
                │      │      │      │
                ▼      ▼      ▼      ▼
            [A-1]  [A-2]  [A-3]  [A-4]
            (各自订阅黑板变化,按需行动)

适用场景

  • 任务没有固定的执行顺序
  • 多个 Agent 需要异步协作
  • 信息是逐步积累的(不是一次性输入)

优点

  • 极度灵活(Agent 可以随时加入、退出)
  • 异步协作,不阻塞
  • 适合"探索性"任务

缺点

  • 收敛不可控(可能永远不结束)
  • 黑板状态管理复杂(并发写、冲突解决)
  • 调试困难(谁在什么时候改了什么)

典型例子

  • 复杂故障诊断(多个 Agent 各贡献一条线索)
  • 多源情报融合(每个 Agent 提供一种情报)
  • 创意头脑风暴(多个 Agent 提想法、互评、迭代)

11.4.6 编排模式对比表

维度 串行 并行 层级 对抗 黑板
复杂度
延迟 高(求和) 低(取最大) 高(多轮) 不可控
吞吐量
容错性
实现难度 简单 复杂 复杂
适用规模 2-5 Agent 3-10 Agent 10+ Agent 2 Agent N Agent
收敛性 必收敛 必收敛 必收敛 需条件 不保证
典型场景 流水线 多源调研 大项目 高质量 探索性
调试难度 极难

11.4.7 编排模式谱系图

┌────────────────────────────────────────────────────────────────────────┐
│                     Sub-Agent 编排模式谱系                              │
├────────────────────────────────────────────────────────────────────────┤
│                                                                        │
│   控制力强                                                控制力弱      │
│   ←──────────────────────────────────────────────────────────→         │
│                                                                        │
│   [串行]   ──>   [并行]   ──>   [层级]   ──>   [对抗]   ──>   [黑板]    │
│   Pipeline      Fan-out      Tree         Maker-       Black-          │
│                  /Fan-in                   Checker      board           │
│                                                                        │
│   ─────────  ─────────  ─────────  ─────────  ─────────                │
│   阶段顺序   任务独立   层级嵌套   角色对立   异步协作                   │
│   失败阻塞   短板效应   过度设计   死循环    收敛难                      │
│   易调试     中等       难调试     中等       极难                       │
│                                                                        │
│   现实系统通常是多种模式的混合:                                         │
│   - 顶层用层级,中层用并行,底层用串行                                   │
│   - 关键质量环节嵌入对抗                                                 │
│   - 探索性环节用黑板                                                     │
└────────────────────────────────────────────────────────────────────────┘

金句:编排模式不是"选一种",是"组合用"。真实的复杂系统,是层级嵌套着并行,并行里串着对抗,对抗中挂着黑板——就像人类组织既有部门树、又有项目组、又有评审委员会、又有意见箱。


11.5 通信机制

编排模式决定了"谁和谁说话",通信机制决定了"怎么说话"。Sub-Agent 系统的通信设计,本质上是分布式系统的通信设计——只不过节点不是进程,是 LLM 实例。

11.5.1 主 Agent → Sub-Agent:任务委派

主 Agent 向 Sub-Agent 发起的通信,核心是任务委派。一次完整的委派应包含:

字段 含义 示例
task_id 任务唯一标识 task-007
subagent_id 目标 Sub-Agent code-reviewer
input 任务输入(结构化) { diff: "...", context: "..." }
expected_output 期望输出契约 { verdict: "approve|reject", comments: [...] }
deadline 超时(毫秒) 30000
priority 优先级 high
context_ref 共享上下文引用 shared://task-007/context.md

实际工程中,多数框架并没有把所有字段都显式化。但显式化是工程成熟度的标志——隐式的契约在 dev 时能跑,到了 prod 一定会爆。

委派的两种语义:

  1. 同步委派(blocking call):主 Agent 阻塞等待 Sub-Agent 返回。简单但失去并行机会。
  2. 异步委派(fire-and-track):主 Agent 发出后继续干别的活,Sub-Agent 完成后通过回调或黑板通知。复杂但能并行。

HappyClaw 的 Sub-Agent 走的是同步委派——通过 SDK 的 agents 选项注册,主 Agent query() 时由 SDK 内部决定何时调用 Sub-Agent。这种实现的优点是简单、可靠;缺点是并行度受限。

11.5.2 Sub-Agent → 主 Agent:结果返回

Sub-Agent 完成任务后,要把结果返回给主 Agent。返回的结果应该满足:

  • 结构化:JSON 或明确的文本格式,主 Agent 可直接解析
  • 可判定:明确包含"成功/失败"信号
  • 可追溯:包含 Sub-Agent 的执行元信息(耗时、token 消耗、调用的工具)

一个理想的返回结构:

{
  "task_id": "task-007",
  "subagent_id": "code-reviewer",
  "status": "completed",
  "result": {
    "verdict": "request_changes",
    "comments": [
      {"file": "src/auth.ts", "line": 42, "issue": "未处理 null 分支"},
      {"file": "src/auth.ts", "line": 87, "issue": "SQL 注入风险"}
    ]
  },
  "metadata": {
    "duration_ms": 12450,
    "tokens_in": 3200,
    "tokens_out": 850,
    "tools_called": ["read_file", "grep"]
  }
}

现实中,多数 LLM 框架的 Sub-Agent 返回是纯文本——这给主 Agent 的解析带来负担。改进方法:

  • 在 Sub-Agent 系统提示里强制要求"以 JSON 输出"
  • 主 Agent 拿到返回后做一次解析,失败则降级为纯文本处理
  • 用 structured output / tool use 来强制结构化

11.5.3 Sub-Agent ↔ Sub-Agent:直接通信

默认禁止。原因:

  1. 直接通信导致拓扑复杂化(N 个 Agent 之间有 N² 条边)
  2. 责任分散(A 给 B 发了错误指令,谁负责?)
  3. 死锁风险(A 等 B,B 等 A)
  4. 可观测性差(侧信道通信不在主链路上)

但有些场景必须直接通信:

  • 流式协作:coder 实时把代码流给 reviewer,reviewer 实时反馈
  • 协商:两个 Agent 需要就某个共享资源达成共识
  • 路由:一个 Agent 把任务转给另一个更合适的 Agent

允许直接通信时,要遵守:

  • 通过显式的 message-passing 接口,不要共享内存
  • 通信内容写入 trace,便于事后追溯
  • 设置通信预算(如每个 Agent 最多发 5 条消息),防止无限对话

11.5.4 共享黑板:异步通信

黑板模式下的通信是异步的。Agent A 把信息写到黑板,Agent B 不知道什么时候会读,也不关心。这种解耦带来了灵活性,也带来了不确定性。

黑板的实现形式:

形式 优点 缺点 适用场景
共享文件 简单、持久、可审计 并发写有冲突 跨进程 Agent
共享内存 进程内才行 单进程多 Agent
消息队列 解耦、可扩展 引入中间件 分布式 Agent
数据库 强一致、可查询 需要查询的场景
Vector Store 支持语义检索 最终一致 知识积累型黑板

HappyClaw 的"记忆"机制(memory/CLAUDE.md + data/groups/.../CLAUDE.md)本质上就是一种持久化的黑板——主 Agent 和 Sub-Agent 都能读写,通过文件系统异步通信。

11.5.5 Sub-Agent 通信时序图

下面用一个典型场景展示通信时序:主 Agent 委派 code-reviewer 审查一段代码,reviewer 给出意见,主 Agent 再让 coder 修复。

  主 Agent         code-reviewer        coder
     │                  │                  │
     │  1.委派审查       │                  │
     ├─────────────────>│                  │
     │                  │                  │
     │                  │  2.读代码、查规范 │
     │                  │  (调用工具)       │
     │                  │                  │
     │  3.返回审查意见   │                  │
     │<─────────────────│                  │
     │                  │                  │
     │  4.委派修复       │                  │
     │  (含审查意见)     │                  │
     ├──────────────────────────────────-->│
     │                                     │
     │                                     │ 5.读代码、改代码
     │                                     │  (调用工具)
     │                                     │
     │  6.返回修复结果                     │
     │<────────────────────────────────────│
     │                                     │
     │  7.主 Agent 整合,输出最终结果       │
     ▼                                     ▼

注意几个关键点:

  • 主 Agent 是唯一的协调者,reviewer 和 coder 不直接对话
  • 每次委派都是同步阻塞(主 Agent 等待返回)
  • 每次返回都是结构化的(审查意见 + 修复 diff)
  • 主 Agent 在第 7 步做整合,不是简单拼接,是基于两份结果的综合判断

金句:通信设计的第一原则是"显式"。隐式契约是 bug 的温床——你以为 Sub-Agent 会返回 JSON,它偏偏返回了 markdown;你以为它会处理 null,它偏偏没处理。显式契约 + 强制校验 = 工程化


11.6 Sub-Agent 的上下文隔离

通信解决了"怎么说话",隔离解决"各自在什么房间里说话"。上下文隔离是 Sub-Agent 工程的结构保证——没有隔离,Sub-Agent 就是个伪概念。

11.6.1 独立 session

每个 Sub-Agent 应该有独立的 session id,不复用主 Agent 的对话历史。为什么?

反例:主 Agent 的对话历史里有用户的各种问题、上下文、错误信息。如果 Sub-Agent 复用这段历史,相当于让一个新员工"看完公司所有的会议纪要再开始干活"——既有用不上的噪声,也有干扰判断的偏见。

正例:Sub-Agent 拿到的是一个全新的、干净的 session,只包含"本次任务的输入 + 系统提示"。它不知道主 Agent 跟用户聊过什么,也不需要知道——它只需要把眼前的事干好。

独立 session 的工程含义:

  1. session id 需要持久化映射:主 Agent 调用 Sub-Agent 时,要为 Sub-Agent 分配并记住一个 session id
  2. 同一 Sub-Agent 多次调用可复用 session:让 Sub-Agent 保持跨调用的记忆(比如同一个 coder 修同一个文件,可以记住上次改了什么)
  3. 不同 Sub-Agent 的 session 互不可见:coder 的 session 不能被 reviewer 看到,反之亦然

HappyClaw 在 sessions 表里以 (group_folder, agent_id) 为主键持久化 session 映射,每个 Sub-Agent 拥有独立的 session 文件,互不干扰。

11.6.2 独立工作目录

涉及文件操作的 Sub-Agent,应该有独立的工作目录或文件命名空间。否则:

  • coder-A 和 coder-B 同时改 src/auth.ts,互相覆盖
  • researcher 把下载的资料塞在工作目录根,污染其他 Agent 的视图
  • Sub-Agent 的中间产物和主 Agent 的产物混淆

解决方案:

方案 适用 缺点
子目录隔离 同一项目内多个 Agent 路径管理复杂
Worktree 隔离 多个 Agent 改同一仓库 Git 操作开销
完全独立工作目录 多个不相关任务 资源浪费
文件锁 共享文件场景 死锁风险

HappyClaw 的"会话工作目录"(data/groups/{folder}/)就是会话级隔离——每个会话有独立的工作目录,不同会话的 Sub-Agent 不互相干扰。

11.6.3 独立工具权限

最小权限原则在 Sub-Agent 系统里同样适用。一个 Sub-Agent 应该只拥有完成本职工作所必需的工具,不多不少。

Sub-Agent 应有工具 不应有
code-reviewer read_file, grep, lint write_file, bash, web_search
coder read_file, write_file, bash web_search, send_message
web-researcher web_search, fetch write_file, bash
tester bash, read_file write_file
doc-writer read_file, write_file bash, web_search

为什么不给所有 Sub-Agent 所有工具?因为:

  1. 降低误用概率:reviewer 不小心执行了 bash 命令可能破坏环境
  2. 降低 prompt 注入风险:攻击面减少
  3. 减少 token 消耗:每个工具的 schema 都占 token
  4. 强制单一职责:工具集本身就是职责的边界

11.6.4 防止"心态污染"

这是上下文隔离最微妙的一点。LLM 的"心态"(reasoning style、temperature、attention pattern)会被上下文塑造。一个 Agent 在做创意发散时,如果上下文里塞满了"严格审查"的指令,它的发散就会被压抑。

心态污染的典型场景

  • 主 Agent 跟用户聊了很多"严格遵循规范"的话题,然后委派 coder 写代码——coder 受上下文影响,写得过于保守
  • Sub-Agent A 输出了"挑刺"风格的审查意见,主 Agent 把它原样转给 Sub-Agent B,B 进入防御模式
  • 多个 Sub-Agent 的输出在主 Agent 上下文里混合,主 Agent 的判断风格被"平均化",失去锐度

对策

  1. 每个 Sub-Agent 独立 session(前面已说)
  2. 主 Agent 转述时重写语气:把 reviewer 的"挑刺"语言,改写成中性的"任务"语言给 coder
  3. 不同角色的 Sub-Agent 用不同温度:发散型 0.7+,收敛型 0.2
  4. 系统提示强化角色:在 Sub-Agent 系统提示里明确"你是 X,只关心 Y,不被其他话题影响"

11.6.5 上下文隔离架构图

┌────────────────────────────────────────────────────────────────────────┐
│                       Sub-Agent 上下文隔离架构                          │
├────────────────────────────────────────────────────────────────────────┤
│                                                                        │
│   ┌─────────────────────┐                                              │
│   │   主 Agent 上下文    │  ← 用户对话 + 任务规划 + Sub-Agent 结果汇总  │
│   │   session: main      │                                              │
│   │   tools: 全部         │                                              │
│   │   workdir: /group    │                                              │
│   └──────┬──────┬──────┬─┘                                              │
│          │      │      │                                                 │
│      委派│  委派│  委派│  (各自独立 session / 独立工作目录 / 独立工具)    │
│          ▼      ▼      ▼                                                 │
│   ┌─────────┐ ┌─────────┐ ┌─────────┐                                  │
│   │ Agent-A │ │ Agent-B │ │ Agent-C │                                  │
│   │session:A│ │session:B│ │session:C│                                  │
│   │tools: t1│ │tools: t2│ │tools: t3│                                  │
│   │wd: /a   │ │wd: /b   │ │wd: /c   │                                  │
│   └─────────┘ └─────────┘ └─────────┘                                  │
│                                                                        │
│   隔离边界:                                                            │
│   - session 互不可见(A 看不到 B 的对话历史)                            │
│   - 工作目录互不可写(A 不能改 /b 下的文件)                             │
│   - 工具集互不重叠(reviewer 没有 write_file)                          │
│   - 心态互不污染(A 的发散不影响 B 的收敛)                              │
│                                                                        │
│   通信边界:                                                            │
│   - 只能通过主 Agent 中转                                                │
│   - 或通过显式的共享黑板                                                  │
│   - 不能直接读对方的 session / 工作目录                                  │
└────────────────────────────────────────────────────────────────────────┘

金句:隔离不是"防着 Sub-Agent",是"保护 Sub-Agent"。一个干净的、不被打扰的 Sub-Agent,比一个被全局上下文污染的 Sub-Agent,输出质量高得多。


11.7 HappyClaw 的 Sub-Agent 实现

理论讲完,来看一个真实实现。HappyClaw 在 container/agent-runner/src/agent-definitions.ts 中定义了两个内置 Sub-Agent:code-reviewerweb-researcher。这一节深入源码,讲清楚实现细节。

11.7.1 整体架构

HappyClaw 的 Sub-Agent 通过 Claude Agent SDK 的 agents 选项注册到 query() 会话。整体架构:

┌──────────────────────────────────────────────────────────────────────┐
│                  HappyClaw Sub-Agent 注册与调用流程                  │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  1. 启动阶段(agent-runner 进程启动)                                 │
│  ┌────────────────────────────┐                                      │
│  │ agent-definitions.ts        │                                      │
│  │ - code-reviewer 定义        │                                      │
│  │ - web-researcher 定义       │                                      │
│  └─────────────┬──────────────┘                                      │
│                │                                                      │
│                ▼                                                      │
│  2. query() 调用阶段(每轮对话)                                      │
│  ┌────────────────────────────┐                                      │
│  │ index.ts query()           │                                      │
│  │   agents: [codeReviewer,   │  ← 注册到 SDK                        │
│  │            webResearcher]  │                                      │
│  └─────────────┬──────────────┘                                      │
│                │                                                      │
│                ▼                                                      │
│  3. SDK 内部决策(是否调用 Sub-Agent)                                │
│  ┌────────────────────────────┐                                      │
│  │ Claude Agent SDK           │                                      │
│  │ - 主 Agent 推理             │                                      │
│  │ - 决定调用 Sub-Agent        │                                      │
│  │ - 路由到对应 agent 定义     │                                      │
│  └─────────────┬──────────────┘                                      │
│                │                                                      │
│                ▼                                                      │
│  4. Sub-Agent 执行(独立 session + 独立工具集)                       │
│  ┌────────────────────────────┐                                      │
│  │ code-reviewer / web-...     │                                      │
│  │ - 独立 session id           │  ← 从 sessions 表加载                │
│  │ - 独立 provider_id          │  ← 避免 OAuth 签名失效              │
│  │ - 独立工具集                │                                      │
│  └─────────────┬──────────────┘                                      │
│                │                                                      │
│                ▼                                                      │
│  5. 结果返回主 Agent,主 Agent 整合后输出                              │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

11.7.2 code-reviewer Sub-Agent 定义

code-reviewer 是 HappyClaw 内置的代码审查 Sub-Agent。它的职责是:对主 Agent 产出的代码进行独立审查,给出结构化的审查意见

定义的核心要素:

要素 取值 设计理由
名称 code-reviewer 简洁明确,符合命名规范
描述 “Code reviewer agent…” SDK 根据描述决定何时调用
系统提示 严格、挑刺、引用规范 验证型角色心态
工具集 只读(read、grep、glob) 最小权限
温度 低(默认 0.2) 收敛型推理
session 独立 隔离主 Agent 上下文
provider_id 独立 sticky 避免跨 OAuth 账号签名失效

设计要点解析:

1. 系统提示的角色注入。系统提示要明确告诉 Sub-Agent “你是谁、你做什么、你不做什么”。例如:

You are a senior code reviewer with 10 years of experience.
Your ONLY job is to review code and provide structured feedback.

You DO NOT:
- Modify code yourself
- Suggest vague improvements ("could be cleaner")
- Approve without giving specific reasons

You DO:
- Read the relevant code thoroughly
- Check against common pitfalls (null handling, error paths, security)
- Provide line-level comments with file path and line number
- Give a final verdict: approve / request_changes / reject

2. 工具集的"只读"约束。code-reviewer 拿到的工具是 read_filegrepglob——没有 write_file、没有 bash。这是结构性的安全保证:即便 Sub-Agent 被恶意指令污染,它也改不了代码。

3. 输出契约的强制。系统提示里要求"final verdict: approve / request_changes / reject",这是强制结构化输出。主 Agent 拿到返回后,能直接解析 verdict 字段做后续决策。

11.7.3 web-researcher Sub-Agent 定义

web-researcher 是 HappyClaw 内置的网页调研 Sub-Agent。它的职责是:对给定的调研问题,进行多轮 web 搜索,输出结构化调研报告

要素 取值 设计理由
名称 web-researcher 简洁明确
描述 “Web researcher agent…” SDK 路由依据
系统提示 务实、结构化、引用来源 执行型 + 专项型
工具集 web_search、fetch、read_file 调研专用
温度 中(0.4) 调研需要一定发散
session 独立 隔离
输出契约 markdown 报告 + 引用列表 主 Agent 可直接整合

为什么 web-researcher 必须独立 Sub-Agent?因为 web 搜索的结果原文极其庞大。一次 web_search 返回的 10 条结果,原文可能 20-50K token。如果主 Agent 自己做搜索,几次下来上下文就爆了。让 web-researcher 在自己的窗口里消化搜索结果,输出"摘要 + 引用",主 Agent 只需要看摘要——这就是隔离的价值。

11.7.4 通过 SDK agents 选项注册

HappyClaw 使用 Claude Agent SDK 的 agents 选项注册 Sub-Agent。注册的代码结构(伪代码):

import { query } from '@anthropic-ai/claude-agent-sdk';
import { codeReviewerAgent } from './agent-definitions';
import { webResearcherAgent } from './agent-definitions';

const result = query({
  prompt: userInput,
  options: {
    agents: [codeReviewerAgent, webResearcherAgent],
    // ...其他选项
  }
});

SDK 内部的决策逻辑:

  1. 主 Agent 接收到 prompt
  2. 主 Agent 推理:这个任务需要 Sub-Agent 吗?
  3. 如果需要,主 Agent 选择合适的 Sub-Agent(基于 description)
  4. SDK 把任务委派给 Sub-Agent,等待返回
  5. Sub-Agent 在独立 session 中执行
  6. Sub-Agent 返回结果给主 Agent
  7. 主 Agent 整合后继续推理

关键点:SDK 提供的是"机制",不是"策略"。什么时候调用哪个 Sub-Agent,是主 Agent 自己推理决定的。这意味着 Sub-Agent 的 description 字段极其重要——它就是主 Agent 的"路由依据"。

11.7.5 独立会话 ID 映射

HappyClaw 在 sessions 表中以 (group_folder, agent_id) 为主键持久化每个 Sub-Agent 的 session id:

CREATE TABLE sessions (
  group_folder TEXT NOT NULL,
  agent_id     TEXT NOT NULL,
  session_id   TEXT,
  provider_id  TEXT,
  updated_at   INTEGER,
  PRIMARY KEY (group_folder, agent_id)
);

设计要点:

  1. 主键是 (group_folder, agent_id):同一会话的同一 Sub-Agent 复用 session;不同会话或不同 Sub-Agent 独立 session
  2. session_id 持久化:Sub-Agent 的对话历史跨进程重启可恢复
  3. provider_id 持久化:见下一节

主 Agent 的 agent_id 通常是 default 或主 Agent 的标识;Sub-Agent 的 agent_idcode-reviewerweb-researcher 等明确标识。

11.7.6 独立 provider_id:避免 OAuth 签名失效

这是一个深刻而微妙的工程细节

背景:HappyClaw 支持多个 OAuth 账号(“provider pool”),主 Agent 和 Sub-Agent 都可能被路由到任意一个 OAuth 账号。OAuth 账号之间是隔离的——每个账号有自己的 thinking block 签名。

问题:如果 Sub-Agent 第一次调用用账号 A,第二次调用用账号 B,会出现什么?

  • 账号 A 的 session 里可能有 thinking blocks(扩展思考过程),这些 blocks 用账号 A 的密钥签名
  • 账号 B 拿到这个 session,无法验证账号 A 签的 thinking blocks
  • SDK 报错"thinking block 签名失效",Sub-Agent 无法继续之前的对话

解决方案:Sub-Agent 的 provider_id 必须持久化,后续调用 sticky 到同一个 provider

┌──────────────────────────────────────────────────────────────────┐
│            provider_id sticky 的必要性与实现                       │
├──────────────────────────────────────────────────────────────────┤
│                                                                  │
│  场景:Sub-Agent 跨调用需保持 session 连续性                      │
│                                                                  │
│  第一次调用:                                                     │
│  Sub-Agent (session=S1) ──> Provider Pool ──> 账号 A              │
│                            (sticky 选 A)                         │
│                                                                  │
│  sessions 表记录:                                                │
│  (group=main, agent=code-reviewer) -> session=S1, provider=A    │
│                                                                  │
│  第二次调用:                                                     │
│  Sub-Agent (session=S1) ──> Provider Pool                        │
│                            │                                      │
│                            │ 查 sessions 表:provider=A           │
│                            │ sticky 到 A                          │
│                            └──> 账号 A(同一个)                  │
│                                                                  │
│  这样 thinking block 签名一致,session 可连续。                   │
│                                                                  │
│  如果不 sticky:                                                  │
│  Sub-Agent ──> Provider Pool ──> 账号 B                          │
│  账号 B 收到 S1(含账号 A 签名的 thinking block)                 │
│  → 签名验证失败 → 报错 → Sub-Agent 退化为新 session              │
│  → 上下文丢失 → 多轮对话能力丧失                                  │
└──────────────────────────────────────────────────────────────────┘

这个细节是 HappyClaw 在生产环境踩坑后总结出来的。它体现了一个核心理念:Sub-Agent 的"独立"不是"每次都从零开始",是"有控制的连续性"——独立的边界要清晰,边界内的连续性要保证。

11.7.7 Sub-Agent 注册流程图

┌──────────────────────────────────────────────────────────────────────┐
│                    HappyClaw Sub-Agent 注册流程                      │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  [启动]                                                              │
│    │                                                                 │
│    ▼                                                                 │
│  agent-runner 进程启动                                                │
│    │                                                                 │
│    ▼                                                                 │
│  import { codeReviewerAgent, webResearcherAgent }                    │
│    │                                                                 │
│    ▼                                                                 │
│  收到 stdin 输入(ContainerInput)                                    │
│    │                                                                 │
│    ▼                                                                 │
│  从 sessions 表加载                                                   │
│   (group_folder, agent_id=default) -> 主 Agent session              │
│   (group_folder, agent_id=code-reviewer) -> reviewer session        │
│   (group_folder, agent_id=web-researcher) -> researcher session     │
│    │                                                                 │
│    ▼                                                                 │
│  query({                                                            │
│    prompt,                                                          │
│    options: {                                                       │
│      agents: [codeReviewerAgent, webResearcherAgent],               │
│      // SDK 自动处理:                                                │
│      // - 何时调用 Sub-Agent(主 Agent 推理决定)                     │
│      // - Sub-Agent 用哪个 session(从 sessions 表取)                │
│      // - Sub-Agent 用哪个 provider(sticky 到持久化的 provider_id)  │
│    }                                                                │
│  })                                                                 │
│    │                                                                 │
│    ▼                                                                 │
│  流式输出 → stdout → OUTPUT_MARKER → container-runner → WebSocket   │
│    │                                                                 │
│    ▼                                                                 │
│  query() 返回                                                        │
│    │                                                                 │
│    ▼                                                                 │
│  更新 sessions 表:                                                  │
│   - 主 Agent new session_id                                         │
│   - 各 Sub-Agent new session_id                                     │
│   - 各 Sub-Agent provider_id(sticky)                              │
│    │                                                                 │
│    ▼                                                                 │
│  [结束]                                                              │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

金句:HappyClaw 的 Sub-Agent 实现体现了一个工程信条——“机制在 SDK,策略在主 Agent,状态在数据库”。三者各司其职,系统才稳。


11.8 典型 Sub-Agent 工作流

理论、设计、实现都讲完了,这一节通过一个完整的端到端案例,把所有概念串起来。

11.8.1 场景:用户请求"重构 auth 模块并审查"

用户在 HappyClaw 的 Web 聊天里输入:

“请帮我重构 src/auth.ts,提取密码哈希逻辑到独立模块,并让 code-reviewer 审一下。”

这是一个复合任务,包含:

  1. 理解需求:提取密码哈希逻辑
  2. 代码修改:重构 src/auth.ts
  3. 代码审查:调用 code-reviewer
  4. 整合输出:把修改和审查意见综合呈现给用户

11.8.2 工作流时序

用户              主 Agent            code-reviewer        工具
  │                  │                      │                 │
  │  1. 输入请求     │                      │                 │
  ├─────────────────>│                      │                 │
  │                  │                      │                 │
  │                  │  2. 读 src/auth.ts                       │
  │                  ├──────────────────────────────────────>  │
  │                  │  3. 文件内容返回                          │
  │                  │<──────────────────────────────────────  │
  │                  │                                          │
  │                  │  4. 规划重构方案                          │
  │                  │  (内部推理)                               │
  │                  │                                          │
  │                  │  5. 写新模块 src/password.ts              │
  │                  ├──────────────────────────────────────>  │
  │                  │                                          │
  │                  │  6. 修改 src/auth.ts (调用旧逻辑)         │
  │                  ├──────────────────────────────────────>  │
  │                  │                                          │
  │                  │  7. 决定调用 code-reviewer                │
  │                  │  (SDK 路由)                              │
  │                  ├──┐                                       │
  │                  │  │ 委派:审 src/auth.ts 和 src/password.ts │
  │                  │  ▼                                       │
  │                  │  ┌─────────────┐                         │
  │                  │  │ code-reviewer│                        │
  │                  │  │ 独立 session │                        │
  │                  │  │ 独立 provider│                        │
  │                  │  │ 只读工具     │                        │
  │                  │  └──────┬──────┘                        │
  │                  │         │                                │
  │                  │         │ 8. 读相关文件、查规范            │
  │                  │         ├────────────────────────────>  │
  │                  │         │ 9. 返回审查意见                  │
  │                  │         │  (verdict + 行级 comments)     │
  │                  │<────────┘                                │
  │                  │                                          │
  │                  │ 10. 整合:把审查意见转成用户友好的输出    │
  │                  │     (主 Agent 推理)                      │
  │                  │                                          │
  │  11. 最终回复    │                                          │
  │<─────────────────│                                          │
                                                                     │

11.8.3 关键节点解析

节点 2-3:主 Agent 读文件。主 Agent 自己用 read_file 工具读取 src/auth.ts,不委派。这是合理的——读文件是轻量操作,没必要 Sub-Agent。

节点 4:主 Agent 规划重构方案。这一步是主 Agent 的"独立思考",不调用任何 Sub-Agent。主 Agent 在自己的上下文里推理:哪些代码是密码哈希、要提取什么函数、新模块叫什么。

节点 5-6:主 Agent 写代码。主 Agent 用 write_file 创建新模块,用 edit_file 修改原文件。这一步也不委派——代码生成是主 Agent 的核心能力,委派给 coder 反而增加通信开销。

节点 7:主 Agent 决定调用 code-reviewer。这是关键路由决策。主 Agent 在系统提示里有 code-reviewer 的 description,知道"代码审查"是该 Sub-Agent 的职责。SDK 根据这一决策,把审查任务委派给 code-reviewer。

节点 8-9:code-reviewer 独立执行。code-reviewer 在自己的 session 里,用只读工具读相关文件,对照规范做审查,返回结构化意见。它的 session 隔离,不被主 Agent 的"重构上下文"污染——它就是一个独立的、严格挑刺的审查员。

节点 10:主 Agent 整合。主 Agent 拿到审查意见,不是简单转贴,而是做综合判断:

  • 哪些意见必须修(严重 bug)
  • 哪些意见可以忽略(风格偏好)
  • 是否需要再委派 coder 修复

最终输出给用户的是"修改 + 审查 + 整合判断"的合集。

11.8.4 时序图体现的几个原则

回看时序图,能提炼几条原则:

  1. 不是所有事都要委派。读文件、写代码这类主 Agent 能轻松搞定的,不要委派。委派有通信开销,过度委派是反模式。
  2. 委派时机由主 Agent 推理决定。SDK 不强制委派,主 Agent 根据任务性质和 Sub-Agent description 自己判断。
  3. Sub-Agent 的输出必须回到主 Agent。code-reviewer 的意见不直接发给用户,必须经过主 Agent 整合——这是"单一协调者"原则。
  4. 整合不是拼接,是判断。主 Agent 要对 Sub-Agent 的输出做"二次推理",决定如何使用。

金句:Sub-Agent 工作流的精髓在"何时委派"和"如何整合"。前者考验路由能力,后者考验综合判断能力。这两者,才是主 Agent 真正的硬功夫。


11.9 并行 Sub-Agent 的设计

并行编排能带来数量级的加速,但也带来复杂的工程问题。这一节专门讲并行。

11.9.1 任务可分性判断

不是所有任务都能并行。判断一个任务能否并行,要看四个条件:

条件 说明 例子
输入独立 各子任务的输入互不依赖 5 个框架调研:每个的输入是独立的框架名
输出独立 各子任务的输出互不覆盖 5 份调研报告:每份独立
无共享状态 子任务不读写同一资源 各自搜索各自的,不共享工作目录
结果可合并 子任务输出有合并策略 5 份报告可以拼成一份综合报告

四个条件全满足 → 可并行;任一不满足 → 不可并行或需改造。

改造例子:把"修改一个文件里的 10 个函数"改造成并行任务?看起来输入输出都依赖同一文件,不可并行。但可以用 worktree 隔离:每个 Sub-Agent 在自己的 git worktree 里改自己的函数,最后由主 Agent 合并 commit。这就是把"不可并行"改造成"可并行"的工程手段。

11.9.2 结果合并策略

并行执行完,要合并结果。合并策略分几类:

策略 适用 实现难度 例子
拼接 输出互不重叠 5 章拼接成书
去重合并 输出有重叠 多源调研去重
优先级选择 输出有优劣 多模型回答选最好的
投票 输出是判断 多 reviewer 投票决定是否合并
综合 输出需要推理整合 多份方案综合成最终方案
矛盾标记 输出有冲突 多源数据冲突时标记给人工

合并的难度不在"拼",在"消歧"。5 份调研报告都说"AutoGen 是微软开源的多 Agent 框架",但其中一份说"由 Microsoft Research 发布",另一份说"由 Microsoft 发布"——这种细微差异要不要统一?怎么统一?这是合并的真正难点。

实践建议:

  1. 让 Sub-Agent 输出结构化:JSON 比 markdown 容易合并
  2. 主 Agent 做二次推理:不要简单拼接,让主 Agent 读所有结果后输出综合
  3. 保留溯源:合并后的每一项都标注来自哪个 Sub-Agent,便于事后核查

11.9.3 失败处理

并行执行时,部分 Sub-Agent 失败是常态。处理策略:

策略 适用场景 风险
全部回滚 强一致任务 一个失败全盘皆输
部分成功 容忍缺失的任务 用户看到不完整结果
重试失败 偶发失败 拖延总时长
降级 有 fallback 方案 质量下降
标记失败 用户可自行处理 体验差

默认推荐:部分成功 + 明确标记。理由:

  • 全部回滚在长程任务里代价过大(10 个并行任务里 1 个失败,重跑全部 10 个?)
  • 部分成功让用户看到"已完成的 9 个 + 失败的 1 个",可以决定是否重试
  • 明确标记让用户知道哪里缺失,不会误以为全部成功

11.9.4 部分成功 vs 全部回滚:决策表

维度 部分成功 全部回滚
任务性质 弱一致 强一致
用户期望 看到部分结果 要么全有要么全无
重试成本
典型场景 多源调研 数据库事务
实现复杂度 高(需要补偿)
失败传播 局部 全局

11.9.5 并行 Sub-Agent 工作流图

┌──────────────────────────────────────────────────────────────────────┐
│                   并行 Sub-Agent 工作流(Fan-out/Fan-in)            │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│   T0: 主 Agent 拆解任务                                               │
│   ┌─────────────────────────────────────────────────┐                │
│   │ "调研 5 个 AI 框架" ->                          │                │
│   │   子任务 1: 调研 AutoGen                        │                │
│   │   子任务 2: 调研 LangGraph                      │                │
│   │   子任务 3: 调研 CrewAI                         │                │
│   │   子任务 4: 调研 Swarm                          │                │
│   │   子任务 5: 调研 HappyClaw                      │                │
│   └─────────────────┬───────────────────────────────┘                │
│                     │                                                │
│   T1: Fan-out(同时分派)                                            │
│   ┌─────────────────────────────────────────────────┐                │
│   │   ┌──[r-A]──┐ ┌──[r-B]──┐ ┌──[r-C]──┐           │                │
│   │   │ 调研 A  │ │ 调研 B  │ │ 调研 C  │ (各自独立 │                │
│   │   │ session │ │ session │ │ session │  session)│                │
│   │   │ provider│ │ provider│ │ provider│          │                │
│   │   └────┬────┘ └────┬────┘ └────┬────┘           │                │
│   └────────┼───────────┼───────────┼────────────────┘                │
│            │           │           │                                  │
│   T2: 各自执行(搜索、读文档、整理)                                  │
│   ...                                                                │
│            │           │           │                                  │
│   T3: Fan-in(结果汇总)                                              │
│   ┌─────────────────────────────────────────────────┐                │
│   │   主 Agent 收集 5 份调研报告                     │                │
│   │   做消歧、去重、综合                             │                │
│   │   输出最终综合报告                               │                │
│   └─────────────────────────────────────────────────┘                │
│                                                                      │
│   失败处理:                                                         │
│   - r-C 失败?标记缺失,综合时注明"框架 C 调研失败"                  │
│   - 重试 r-C 一次,仍失败则降级                                      │
│   - 不影响 r-A、r-B 的结果                                          │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

金句:并行的真正难点不是"同时跑",是"跑完之后怎么合"。前者是机制,后者是智慧。


11.10 多 Agent 协作的反模式

讲完正例,必须讲反例。这一节列出多 Agent 系统常见的"工程坑",每一个都是真实踩出来的。

11.10.1 反模式 1:Agent 数量膨胀

症状:开发者一时兴起,给每个小职责都建一个 Sub-Agent。从"web 调研"到"web 调研-中文"到"web 调研-技术文档",Sub-Agent 数量从 3 个膨胀到 30 个。

危害

  1. 系统提示维护成本爆炸:30 个 Sub-Agent 的系统提示都要调
  2. 路由决策变难:主 Agent 要在 30 个里选,选错率高
  3. 工具 schema 总量过大:每个 Sub-Agent 工具描述在 SDK 注册时都占 token
  4. 测试覆盖不了:30 个 Sub-Agent 的组合路径无法穷举

根因:把 Sub-Agent 当成"代码函数"来切,没意识到每个 Sub-Agent 都是一个完整的、有上下文成本的 Agent 实例。

对策

  • 一个新 Sub-Agent 上线前,问自己:“这个职责能不能让现有 Sub-Agent 兼任?”
  • 如果不能兼任,再问:“这个职责出现频率高吗?值得维护一个独立 Agent 吗?”
  • 两个问题都通过,才建新的

经验阈值:一个系统的 Sub-Agent 数量,3-7 个为佳,10 个为限。超过 10 个,就该考虑用 Sub-Agent 的 Sub-Agent(层级编排),而不是平铺。

11.10.2 反模式 2:通信开销 >> 计算开销

症状:主 Agent 把一个简单任务委派给 Sub-Agent,Sub-Agent 又委派给另一个 Sub-Agent,三层下来,每个 Sub-Agent 只干了 1 秒的活,但通信花了 10 秒。

危害

  1. 延迟激增:用户等一个简单回答等了好几秒
  2. token 浪费:每次委派都要重新构造上下文
  3. 可靠性下降:每多一层委派,就多一个失败点

判断公式

通信开销 = 委派次数 × (序列化成本 + 路由成本 + 等待成本)
计算开销 = Sub-Agent 实际推理时间
若 通信开销 >> 计算开销 → 反模式

对策

  • 能在主 Agent 一轮推理里做完的,绝不委派
  • 委派的粒度要"够重"——至少让 Sub-Agent 干的活是通信开销的 5 倍以上
  • 减少层级,能用并行就不用串行层级

11.10.3 反模式 3:责任分散

症状:多个 Sub-Agent 都"参与"了一个决策,但出问题时没人负责。

经典场景

  • coder 写了有 bug 的代码
  • reviewer 没审出来
  • tester 没测出来
  • 上线后爆雷

每个 Sub-Agent 都说"我做了我该做的",但系统整体失败了。这就是社会心理学里的"旁观者效应"在 Agent 系统的重演。

对策

  1. 每个决策有明确的责任 Agent:在系统提示里写明"你是 X 的最终责任人"
  2. 责任链可追溯:每次决策记录由哪个 Agent 做出、基于什么信息
  3. 责任倒查机制:出问题时能定位到具体 Agent 的具体决策

11.10.4 反模式 4:协调死锁

症状:Agent A 等 Agent B 的结果,Agent B 等 Agent C 的结果,Agent C 等 Agent A 的结果——三方互相等待,系统卡死。

典型触发条件

  • 黑板模式下,每个 Agent 都"等其他 Agent 先贡献"
  • 对抗模式下,maker 和 checker 互相不接受对方的输出
  • 层级模式下,子 Agent 等父 Agent 给输入,父 Agent 等子 Agent 给输出

对策

  1. 设置超时:每个委派必须有 deadline,超时即降级
  2. 避免循环依赖:依赖图必须是 DAG(有向无环图)
  3. 默认行为:Agent 在等待时必须有默认 fallback(“如果 N 秒内没收到,就基于现有信息决策”)

11.10.5 反模式 5:过度编排

症状:开发者把"编排"当成炫技,简单的任务也搞个三层编排 + 黑板 + 对抗。代码量激增,可维护性暴跌。

危害

  • 实现复杂度 >> 任务复杂度
  • 调试困难
  • 后期维护成本高

对策

  • 编排复杂度应匹配任务复杂度,不超过 1.5 倍
  • 简单任务用单 Agent + 工具调用就够了
  • 编排层级 ≤ log2(子任务数) + 1

11.10.6 多 Agent 反模式树

┌────────────────────────────────────────────────────────────────────────┐
│                      多 Agent 协作反模式树                              │
├────────────────────────────────────────────────────────────────────────┤
│                                                                        │
│  多 Agent 反模式                                                       │
│  ├── 数量类                                                            │
│  │   ├── Agent 数量膨胀(>10 个)                                       │
│  │   └── 工具数量膨胀(单 Agent >30 工具)                              │
│  │                                                                      │
│  ├── 通信类                                                            │
│  │   ├── 通信开销 >> 计算开销                                          │
│  │   ├── 侧信道通信(绕过主链路)                                       │
│  │   └── 消息风暴(Agent 间高频对话)                                   │
│  │                                                                      │
│  ├── 责任类                                                            │
│  │   ├── 责任分散(多个 Agent 都参与,无人负责)                        │
│  │   ├── 责任倒置(Sub-Agent 凌驾主 Agent)                            │
│  │   └── 责任链断裂(出问题查不到谁)                                   │
│  │                                                                      │
│  ├── 协调类                                                            │
│  │   ├── 协调死锁(循环等待)                                           │
│  │   ├── 协调活锁(一直退让不进展)                                     │
│  │   └── 永不收敛(多轮对抗不收敛)                                     │
│  │                                                                      │
│  ├── 隔离类                                                            │
│  │   ├── 上下文污染(Sub-Agent 共用主上下文)                          │
│  │   ├── 工作目录冲突(多 Agent 改同一文件)                            │
│  │   └── 心态串扰(发散和收敛混杂)                                     │
│  │                                                                      │
│  └── 架构类                                                            │
│      ├── 过度编排(简单任务上重编排)                                   │
│      ├── 编排不足(复杂任务用单 Agent)                                 │
│      └── 模式错配(黑板场景用了串行)                                   │
│                                                                        │
└────────────────────────────────────────────────────────────────────────┘

金句:反模式不是"做错了",是"做过头"。Sub-Agent 系统的失败,多数不是技术问题,是工程品味问题——知止,是一种美德。


11.11 Sub-Agent vs 单 Agent + 工具调用:决策树

并不是所有任务都需要 Sub-Agent。很多场景下,单 Agent + 工具调用就足够了。这一节给一个决策树,帮你判断"该不该拆"。

11.11.1 何时该拆(用 Sub-Agent)

满足以下任一条件,就该拆:

  1. 上下文消耗大:单次任务预计消耗 > 50% 上下文窗口
  2. 职责清晰可分:能明确画出"X 做 A、Y 做 B"的边界
  3. 并行机会:子任务之间无依赖,可并行
  4. 专业差异大:不同子任务需要截然不同的系统提示、工具、温度
  5. 质量需要对抗:需要 maker-checker 式的质量保证
  6. 复用价值:某个 Sub-Agent 能在多个任务里复用

11.11.2 何时不该拆(用单 Agent + 工具)

满足以下任一条件,就不该拆:

  1. 任务简单:单 Agent 一轮推理能搞定
  2. 职责边界模糊:拆出来的 Sub-Agent 不知道自己该干啥
  3. 强依赖:子任务之间必须顺序、紧密耦合
  4. 通信开销大:拆开后的通信成本超过节省的计算成本
  5. 频次低:任务很少出现,不值得维护 Sub-Agent

11.11.3 决策树图

                        ┌─────────────────────┐
                        │  任务复杂吗?        │
                        │  (单 Agent 一轮能   │
                        │   搞定吗?)          │
                        └──────────┬──────────┘
                                   │
                  ┌────────────────┴────────────────┐
                  │ 否                               │ 是
                  ▼                                  ▼
        ┌─────────────────┐              ┌─────────────────────┐
        │ 任务有并行机会? │              │  用单 Agent + 工具  │
        │ 子任务独立?     │              │  调用即可            │
        └────────┬────────┘              └─────────────────────┘
                 │
        ┌────────┴────────┐
        │ 否               │ 是
        ▼                  ▼
   ┌───────────┐    ┌─────────────────┐
   │ 强依赖?  │    │ 用并行编排      │
   └─────┬─────┘    └─────────────────┘
         │
    ┌────┴────┐
    │ 是       │ 否
    ▼          ▼
┌────────┐  ┌─────────────┐
| 串行   │  │ 用层级编排  │
| 编排   │  └─────────────┘
└────────┘

更细的决策树:

                        ┌───────────────────────┐
                        │ 1. 上下文消耗大吗?   │
                        │    (>50% 窗口)        │
                        └──────────┬────────────┘
                                   │ 是
                                   ▼
                        ┌───────────────────────┐
                        │ 2. 职责清晰可分吗?   │
                        └──────────┬────────────┘
                                   │ 是
                                   ▼
                        ┌───────────────────────┐
                        │ 3. 子任务有专业差异? │
                        │ (不同 prompt/tool)    │
                        └──────────┬────────────┘
                                   │ 是
                                   ▼
                        ┌───────────────────────┐
                        │ 4. 频次高吗?         │
                        │ (值得维护 Sub-Agent)  │
                        └──────────┬────────────┘
                                   │ 是
                                   ▼
                            ┌──────────────┐
                            │ 用 Sub-Agent │
                            └──────────────┘

11.11.4 决策对照表

维度 单 Agent + 工具 Sub-Agent
实现复杂度 中-高
上下文消耗 集中在主 Agent 分散到各 Sub-Agent
调试 简单 复杂
复用 工具级复用 Agent 级复用
质量保证 主 Agent 自检 可引入对抗
并行 容易
适合任务 简单、单步骤 复杂、多步骤

金句:Sub-Agent 不是"高级",是"必要时的拆分"。能用单 Agent 解决的,就别上 Sub-Agent——简单性是工程美德,不是工程缺陷。


11.12 真实案例

理论讲完了,来看业界实践。这一节对比 5 个有代表性的多 Agent 系统,看它们各自的编排哲学。

11.12.1 Claude Code 的 Sub-Agent 系统

Claude Code(Anthropic 官方 CLI)内置了 Sub-Agent 机制,主要包含:

  • code-reviewer:代码审查 Sub-Agent
  • web-researcher:网页调研 Sub-Agent
  • 自定义 Sub-Agent:用户可在 .claude/agents/ 定义自己的 Sub-Agent

设计哲学:主 Agent 主导,Sub-Agent 专精。主 Agent 推理决定何时调用 Sub-Agent,Sub-Agent 在独立 session 中执行专精任务。

技术细节:

  • Sub-Agent 通过 SDK 的 agents 选项注册
  • 独立 session、独立工具集、独立系统提示
  • 输出结构化返回给主 Agent

11.12.2 Cursor 的多 Agent 模式

Cursor(AI 编程 IDE)的多 Agent 模式体现在:

  • Composer:主 Agent,负责代码生成
  • Tab 补全:轻量 Sub-Agent,负责行内补全
  • Cursor Chat:问答 Sub-Agent,负责侧栏对话
  • Background Agents:后台 Sub-Agent,负责长任务

设计哲学:按场景拆分。不同交互场景对应不同 Sub-Agent,每个 Sub-Agent 有自己的 UI 入口和工具集。

11.12.3 AutoGen 的多 Agent 框架

AutoGen(微软开源)是早期的多 Agent 框架,特点是:

  • 对话式编排:Agent 之间通过对话协调
  • 角色可定制:用户定义每个 Agent 的角色
  • 多种对话模式:sequential、group chat、nested

设计哲学:Agent 即角色。把人类组织里的角色抽象成 Agent,让它们对话解决任务。

典型反例(早期版本):两个 Agent 互相客套多轮不干活。后续版本引入了"终止条件"和"主持人 Agent"来收敛。

11.12.4 LangGraph 的图式编排

LangGraph(LangChain 出品)的核心抽象是有向图

  • 节点 = Agent / 工具
  • 边 = 控制流
  • 状态 = 图的共享内存

设计哲学:编排即图。把多 Agent 协作抽象成状态图,每条边都是显式的状态转移。

技术亮点:

  • 显式的状态管理(vs AutoGen 的隐式对话)
  • 可视化(图天然可画)
  • 可分析(图论工具可分析死锁、活锁、可达性)

11.12.5 OpenAI Swarm

OpenAI Swarm(OpenAI 出品,2024)是轻量级多 Agent 框架,特点是:

  • 极简抽象:Agent = (instructions, tools, handoff)
  • handoff 机制:Agent A 可以把对话"交给"Agent B
  • 无状态:框架本身不维护状态,状态在对话上下文里

设计哲学:轻量、显式、无状态。把多 Agent 协作简化为"Agent 之间互相 handoff",没有复杂的图、没有对话历史管理。

适用场景:原型、教学、轻量应用。不适合生产级长程任务。

11.12.6 五大框架对比表

维度 Claude Code Cursor AutoGen LangGraph Swarm
编排哲学 主+专 场景拆分 角色对话 状态图 handoff
抽象层级 SDK agents UI 入口 Agent + 对话 图节点 Agent + handoff
状态管理 显式 session 隐式 隐式 显式
并行支持
可观测性
生产就绪
学习曲线 极低
适合场景 编程 编程 IDE 通用 复杂工作流 原型

金句:每个框架都在"抽象力"和"易用性"之间做了权衡。LangGraph 抽象力强但难学,Swarm 易用但弱。没有银弹,只有适合


11.13 多 Agent 系统的可观测性

多 Agent 系统的调试比单 Agent 难一个数量级。单 Agent 出问题,看 trace 就行;多 Agent 出问题,要先把"谁在什么时候调用了谁、各自消耗了多少 token、谁失败了"梳理清楚。这一节讲可观测性的三大支柱。

11.13.1 调用链追踪

调用链(trace) 是多 Agent 系统的"案发现场重建"。一次完整的 trace 应包含:

字段 含义
trace_id 整个用户请求的唯一 ID
span_id 每个 Agent 调用的 span ID
parent_span_id 父 span(主 Agent 是根)
agent_id 哪个 Agent
input 输入摘要
output 输出摘要
start_time / end_time 起止时间
status 成功 / 失败 / 超时
tokens_in / tokens_out token 消耗
tools_called 调用了哪些工具

一个典型 trace:

trace_id: abc-123
└─ span-1 [main Agent] (15.2s, 4500 in, 1200 out)
   ├─ span-2 [coder Sub-Agent] (8.1s, 2200 in, 600 out)
   │  └─ tool: write_file (src/auth.ts)
   ├─ span-3 [code-reviewer Sub-Agent] (5.4s, 1800 in, 400 out)
   │  ├─ tool: read_file (src/auth.ts)
   │  └─ tool: read_file (src/password.ts)
   └─ span-4 [main Agent 整合] (1.7s, 500 in, 200 out)

从 trace 能看出:

  • 总耗时 15.2s,其中 coder 8.1s 占大头
  • coder 和 reviewer 串行执行(reviewer 在 coder 之后开始)
  • 各 Agent 的 token 消耗合理
  • 没有失败

如果 reviewer 失败,trace 会变成:

└─ span-1 [main Agent]
   ├─ span-2 [coder] ✓
   ├─ span-3 [code-reviewer] ✗ (timeout 30s)
   └─ span-4 [main Agent 整合,含失败处理]

trace 的可视化常用火焰图(flame graph),横向是时间,纵向是调用深度。

11.13.2 Token 用量归因

多 Agent 系统的成本控制,必须做到per-Agent 的 token 归因。否则你只知道"今天花了 100 万 token",但不知道哪个 Agent 是大头。

归因维度:

维度 例子
按 Agent coder: 50万,reviewer: 20万,main: 30万
按任务类型 编程: 60万,调研: 30万,对话: 10万
按用户 user-A: 70万,user-B: 30万
按模型 GPT-4: 80万,GPT-3.5: 20万
按时间 早高峰: 40万,晚高峰: 50万

HappyClaw 在 usage_records 表里按 per-model per-Agent per-Message 拆行存储,可以做任意维度的归因聚合。

11.13.3 失败传播分析

多 Agent 系统的失败传播是级联的:一个 Sub-Agent 失败,会导致主 Agent 的整合失败,进而导致整个任务失败。

失败传播分析要回答:

  1. 哪个 Sub-Agent 是失败源头?(root cause)
  2. 失败传播到了哪些 Agent?(blast radius)
  3. 传播路径是什么?(impact chain)
  4. 如何阻断传播?(mitigation)

例子

root cause: web-researcher 超时(30s 没返回)
  ↓ 主 Agent 收到 null 结果
  ↓ 主 Agent 试图基于 null 综合报告
  ↓ 主 Agent 输出"调研失败"
blast radius: 整个调研任务失败
mitigation: 给 web-researcher 设置更长超时 + 失败时降级为"基于已有知识回答"

11.13.4 火焰图示例

┌──────────────────────────────────────────────────────────────────────┐
│           多 Agent 调用火焰图(横向=时间,纵向=深度)                 │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  时间(s)  0    2    4    6    8   10   12   14   16   18   20        │
│          │    │    │    │    │    │    │    │    │    │    │          │
│  主Agt   ████████████████████████████████████████████████████████     │
│          │    │    │    │    │    │    │    │    │    │    │          │
│  coder   ─────█████████████████─────│    │    │    │    │            │
│          │    │    │    │    │    │    │    │    │    │    │          │
│  revw    ──────────────────────────────████████████───│    │         │
│          │    │    │    │    │    │    │    │    │    │    │          │
│  resch   ──────────────────────████████████████████████│    │        │
│          │    │    │    │    │    │    │    │    │    │    │          │
│  整合    ───────────────────────────────────────────────██████       │
│                                                                      │
│  解读:                                                               │
│  - 主 Agent 全程在线(顶层横条)                                      │
│  - coder 在 2-8s 执行(5个 hash 块)                                  │
│  - reviewer 在 8-14s 执行(在 coder 完成后开始,串行)               │
│  - researcher 在 6-16s 执行(与 reviewer 部分重叠,并行)             │
│  - 整合在 16-20s(所有 Sub-Agent 完成后)                            │
│  - 总耗时 20s,其中并行节省了约 6s                                    │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

金句:没有可观测性的多 Agent 系统,是黑盒里的黑盒。出问题时你只能"猜",而猜,是工程的大忌。


11.14 Agent 编排的未来

讲完当下,眺望未来。这一节是预测,不是断言——但趋势已经显现。

11.14.1 Agent 市场化

未来会出现Agent 市场:开发者把自己做的优质 Sub-Agent 上架,其他用户按需调用。

类比:

  • App Store → iOS 应用市场
  • Hugging Face → 模型市场
  • Agent Store → Sub-Agent 市场(未来)

市场化的含义:

  1. 价值流转:优质 Sub-Agent 可获得收益
  2. 专业化分工:全职"Sub-Agent 工程师"出现
  3. 质量信号:评分、下载量、可靠性指标
  4. 组合创新:用户从多个作者那里组合 Sub-Agent

11.14.2 标准 protocol:MCP、ACP

标准化是市场化的前提。当前两个值得关注的 protocol:

MCP(Model Context Protocol):Anthropic 主推,专注"Agent 与工具/数据源"的标准化。已经广泛落地。

ACP(Agent Communication Protocol):聚焦"Agent 与 Agent"的通信标准化。还在早期。

未来预测:MCP + ACP 会成为多 Agent 系统的"TCP/IP"——底层通信标准。基于这个标准,会涌现大量跨厂商的 Agent 协作场景。

11.14.3 Agent 身份与信誉

当 Agent 跨组织协作时,"身份"和"信誉"成为核心问题:

  • 身份:每个 Agent 有可验证的 DID(去中心化身份)
  • 信誉:基于历史调用记录计算的信誉分
  • 审计:每个 Agent 的关键决策可被追溯
  • 授权:用户授权某个 Agent 访问哪些资源

这块目前还很早期,但方向清晰——Agent 也会有"职业信誉",就像人有信用分一样。

11.14.4 未来编排趋势图

┌──────────────────────────────────────────────────────────────────────┐
│                  Agent 编排的未来趋势                                 │
├──────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  当前 (2026)                                                         │
│  ├── 单厂商 SDK 内编排(Claude Code、Cursor)                        │
│  ├── 框架式编排(AutoGen、LangGraph、Swarm)                         │
│  └── MCP 标准化工具接入                                               │
│                                                                      │
│  近期 (2027-2028)                                                    │
│  ├── ACP 跨厂商 Agent 通信标准化                                     │
│  ├── Agent 市场涌现                                                   │
│  ├── 跨组织 Agent 协作(你的 Agent 调用我的 Agent)                  │
│  └── 可观测性标准化(trace、metrics 跨厂商)                         │
│                                                                      │
│  远期 (2029+)                                                        │
│  ├── Agent 身份与信誉体系成熟                                         │
│  ├── Agent 自主交易(Agent-to-Agent 经济)                            │
│  ├── Agent 治理(合规、审计、问责)                                   │
│  └── Agent 联邦(多 Agent 自组织成"Agent 公司")                      │
│                                                                      │
│  终极愿景:Agent 网络成为人类社会的新型基础设施                       │
│                                                                      │
└──────────────────────────────────────────────────────────────────────┘

金句:今天的 Agent 编排,相当于 1995 年的互联网——协议刚出,应用刚冒,没人知道 30 年后会变成什么。但有一点确定:协议、市场、信誉这三件事,会成为下一代 Agent 工程的基石。


11.15 最佳实践 Tips

经过前面十几节的论述,这里汇总 10 条最佳实践。每条都是踩坑后的提炼。

  1. 从单 Agent 起步,确认不够再拆 Sub-Agent。不要一上来就多 Agent,简单性是工程美德。
  2. Sub-Agent 数量控制在 3-7 个。超过 10 个就该考虑层级编排。
  3. 每个 Sub-Agent 有明确的 description。这是 SDK 路由的依据,模糊的 description 会导致路由错乱。
  4. 每个 Sub-Agent 独立 session。隔离是质量保证,不是性能优化。
  5. 验证型 Sub-Agent 只读。结构上禁止它修改产物,避免"自审自批"。
  6. provider_id 持久化。Sub-Agent 跨调用必须 sticky 到同一 OAuth 账号,否则 thinking block 签名失效。
  7. 委派必须有 deadline。没有超时的委派,迟早会陷入死锁。
  8. 失败要部分成功 + 明确标记。长程任务里"全部回滚"代价过大,部分成功是更现实的选择。
  9. 每个 Sub-Agent 都要可独立测试。给每个 Sub-Agent 写 golden case,回归时能快速定位。
  10. 可观测性是底线。trace、metrics、logs 三位一体,缺一不可。没有可观测性的多 Agent 系统,是给未来的自己挖坑。

金句:最佳实践的本质,是"不要重新发明轮子"。前人踩过的坑,没必要再踩一遍——除非你想交自己的学费。


11.16 番外篇:生物学中的细胞分化——从干细胞到专职细胞

讲完工程,讲点生物学。Sub-Agent 的"专业分工"思想,在生命系统里有极其精妙的对应——细胞分化

11.16.1 干细胞与多能性

人体的起点是一个受精卵。它是全能干细胞——能分裂出人体的任何细胞。这就像一个"全能 Agent",理论上什么都能做。

但随着胚胎发育,细胞开始分化

阶段 细胞类型 能力
受精卵 全能干细胞 能发育成完整个体 + 胎盘
囊胚期 多能干细胞 能发育成所有组织,但不能成胎盘
三胚层期 专能干细胞 只能发育成某一胚层的细胞
终末分化 成熟体细胞 只做一种职能(神经、肌肉、上皮)

分化的本质是"放弃潜能换取专精"。神经元放弃了分裂能力,换取了极致的电信号传导;红细胞放弃了细胞核,换取了高效的氧气运输。

11.16.2 与 Sub-Agent 的对应

把这个模型映射到 Agent 系统:

生物学 Agent 系统
受精卵(全能) 单 Agent(理论全能)
多能干细胞 通用 Sub-Agent(如 coder 通用编程)
专能干细胞 专项 Sub-Agent(如 sql-agent 专精 SQL)
终末分化细胞 高度定制的 Sub-Agent(如 K8s-yaml-validator)
组织 多个同类 Sub-Agent 协作
器官 多个组织协作完成大功能
系统 多个器官协作维持生命
个体 整个 Agent 系统

11.16.3 分化的工程智慧

细胞分化给我们的工程启示:

  1. 不是越分化越好。干细胞太少,组织无法再生;分化细胞太多,组织失去灵活。Sub-Agent 同理——3-7 个为佳,10 个为限
  2. 保留少量干细胞。人体保留少量成体干细胞用于修复。Agent 系统也应保留"通用 Agent"做兜底,专精 Agent 不擅长时 fallback。
  3. 分化要可逆(部分)。诱导多能干细胞(iPS)让分化细胞重编程为干细胞。Agent 系统里,Sub-Agent 的系统提示可改、工具可换,这就是"重编程"。
  4. 每个细胞都有全套 DNA。即便分化了,神经细胞里仍然有完整的基因组。Agent 系统里,每个 Sub-Agent 仍然可以访问全局知识库,只是默认不激活——这是一种"潜力保留"。
  5. 细胞间通信靠信号分子。激素、神经递质、细胞因子——本质是消息。Agent 间的通信也是消息,松耦合是关键。

金句:生命系统是亿万年试错的产物,它的工程智慧远超我们的代码。Sub-Agent 的"专业分化",本质是生命系统在代码世界的投影。


11.17 番外篇:企业组织架构——从个人贡献者到矩阵管理

第二个番外篇讲组织。Sub-Agent 协作,本质是"AI 版的组织管理"。看懂人类组织,就看懂了 Agent 编排的边界。

11.17.1 组织形态演进

时代 主流组织 特点 对应 Agent 编排
手工业 个人工匠 一人全干 单 Agent
工厂制 流水线工人 串行分工 Pipeline 串行编排
职能制 部门制 职能分组(市场、研发、销售) 按职能拆 Sub-Agent
事业部制 BU 按产品/地域分组 层级编排
矩阵制 双线汇报 职能 + 项目 黑板 + 层级混合
敏捷制 小队自治 跨职能小队 对抗 + 并行
自组织 去中心化 个体自治 黑板模式

11.17.2 经验对照

组织痛点 Agent 痛点
部门墙(信息不流通) Sub-Agent 上下文隔离过度
责任分散(没人负责) 多 Agent 责任分散反模式
官僚主义(流程冗长) 过度编排反模式
微观管理(不信任员工) Sub-Agent 工具集过窄、不给决策权
山头主义(小团队利益) Sub-Agent 各自为政,缺乏整合

11.17.3 治理启示

  1. 给 Sub-Agent 适度自主权。像管员工一样——给目标、给工具、给边界,至于怎么干让 Sub-Agent 自己决定。
  2. 建立"绩效考核"。每个 Sub-Agent 的输出质量、调用频次、失败率要持续监控,做得差的优化或下线。
  3. 建立"晋升通道"。高频被调用的 Sub-Agent 值得投入更多优化(更好的系统提示、更精的工具)。低频的可以合并或下线。
  4. 跨组织协作要 protocol。不同厂商的 Agent 协作,必须靠标准 protocol(MCP、ACP),不能靠"默契"。
  5. 保持组织敏捷。Sub-Agent 的职责、工具、系统提示应能快速调整,不要固化成"不可动的石头"。

金句:管 Agent 像管组织——管得太死,失去敏捷;管得太松,陷入混乱。中庸之道,是工程,也是艺术。


11.18 本章小结

让我们把全章的核心要点收束一下。

11.18.1 全章核心论点

  1. Sub-Agent 的必要性:单 Agent 的上下文窗口是物理边界,长程任务必须靠 Sub-Agent “扩容”。
  2. 设计哲学四原则:单一职责、松耦合、独立上下文、可独立验证。
  3. 角色分类四类:执行型、验证型、协调型、专项型,各有设计要点。
  4. 编排模式五谱系:串行、并行、层级、对抗、黑板,按控制力强弱排列,现实系统多为混合。
  5. 通信机制四要素:主→Sub 委派、Sub→主 返回、Sub↔Sub 默认禁止、共享黑板异步通信。
  6. 上下文隔离四层:独立 session、独立工作目录、独立工具权限、防止心态污染。
  7. HappyClaw 实现:通过 SDK agents 选项注册,独立 session + 独立 provider_id(sticky 避免 thinking block 签名失效)。
  8. 典型工作流:主 Agent 拆解→委派→Sub-Agent 执行→返回→主 Agent 整合。
  9. 并行设计三难点:任务可分性、结果合并、失败处理。
  10. 五大反模式:数量膨胀、通信开销过大、责任分散、协调死锁、过度编排。
  11. 决策树:能单 Agent 解决就单 Agent,必要时才拆。
  12. 业界实践:Claude Code、Cursor、AutoGen、LangGraph、Swarm 各有哲学。
  13. 可观测性三支柱:调用链追踪、token 归因、失败传播分析。
  14. 未来趋势:市场化、protocol 标准化、Agent 身份与信誉。
  15. 生物学隐喻:细胞分化启示"专业分化 + 保留干细胞"。
  16. 组织学隐喻:组织演进对应 Agent 编排演进,治理智慧可互鉴。

11.18.2 一句话总结

Sub-Agent 不是"把一个 Agent 拆成多个"那么简单,它是一套关于职责切分、上下文隔离、结果整合的完整工程哲学。其核心,是把人类几千年的组织智慧,迁移到 AI 系统中。

11.18.3 与其他章的联系

  • 第 2 章讲的 Harness Engineering 是"单 Agent + 工具"的范式,本章是它的扩展与升级。
  • 第 4 章的上下文管理,是 Sub-Agent 隔离设计的物理基础。
  • 第 7 章的 Loop Engineering,是 Sub-Agent 在长程任务中持续协作的循环框架。
  • 第 9 章的工具调用,是 Sub-Agent 工具集设计的基础。
  • 第 12 章(如果有的话)会讲多 Agent 系统的安全与对齐,是本章的延伸。

11.19 思考题

  1. 场景题:你要构建一个"自动化数据分析 Agent",用户上传 CSV 后 Agent 自动清洗、分析、可视化、写报告。请设计这个系统的 Sub-Agent 架构:需要哪些 Sub-Agent?用什么编排模式?每个 Sub-Agent 的工具集是什么?

  2. 设计题:设计一个"maker-checker"对抗编排,用于"生成 SQL 查询 + 防注入审查"。给出 maker 和 checker 的系统提示大纲、工具集、收敛条件、失败处理策略。

  3. 分析题:分析 HappyClaw 的 code-reviewerweb-researcher 设计,找出 3 处可以改进的地方,并说明改进方案与代价。

  4. 辩论题:有人说"未来 Agent 系统会越来越倾向单 Agent + 海量工具,Sub-Agent 是过渡形态"。请论述正反方观点,并给出你的判断。

  5. 工程题:你接手一个有 30 个 Sub-Agent 的系统,发现路由决策错误率高、维护成本大。请给出"瘦身"方案:保留哪些、合并哪些、下线哪些?判断依据是什么?

  6. 开放题:如果让你设计一个跨厂商的 Agent 协作 protocol(ACP),你会规定哪些必填字段?为什么?

  7. 反思题:本章用"细胞分化"和"组织管理"做隐喻。这种隐喻的边界在哪里?哪些地方隐喻成立,哪些地方隐喻失效?


本章结束。Sub-Agent 不是终点,是 Loop Engineering 的起点。当 Sub-Agent 学会协作,长程任务才真正成为可能。下一章见。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐