第5课:多 Agent 系统
⭐⭐⭐⭐ 高频↔ Hermes 源码
一、为什么需要多个 Agent?
单个 Agent 有明确的局限:
- 上下文窗口有限 —— 一个人处理所有事情,记忆会爆
- 专注力分散 —— 一个 Agent 既要写代码、又要查资料、又要发邮件,工具列表太长 LLM 反而困惑
- 串行瓶颈 —— 查资料和写代码不能同时进行,效率低
- 缺乏分工 —— 没有"专家"角色,一个 Agent 什么都做,但什么都做不精
多 Agent 系统的核心思路:把复杂任务拆成子任务,分配给专门的子 Agent,每个子 Agent 专注一件事。
二、两大模式:编排器 vs 蜂群
┌─── 模式 A:编排器(Orchestrator) ───────────┐
│ │
│ ┌──────────────────┐ │
│ │ Orchestrator │ │
│ │ (主管Agent) │ │
│ └────────┬─────────┘ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Worker │ │ Worker │ │ Worker │ │
│ │ Agent A │ │ Agent B │ │ Agent C │ │
│ │ (代码) │ │ (搜索) │ │ (测试) │ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 特点:集中控制、任务分发、结果汇总 │
│ 代表:Hermes delegate_task │
└──────────────────────────────────────────────┘
┌─── 模式 B:蜂群(Swarm) ─────────────────┐
│ │
│ Agent A ─── Agent B │
│ │ │ │
│ │ │ │
│ Agent C ─── Agent D │
│ │
│ 特点:去中心化、Agent 相互发现、自由协作 │
│ 代表:CrewAI、AutoGen、A2A 协议 │
└──────────────────────────────────────────────┘
三、模式 A:编排器(Orchestrator)
3.1 核心流程
用户:"帮我研究一下 Agent 框架的对比,然后写成文章"
编排器 Agent 的思考:
Step 1: 我需要拆成 3 个子任务
├── 研究任务:搜索 LangChain, CrewAI, AutoGen 的优缺点
├── 整理任务:把搜索结果整理成结构化对比表
└── 写作任务:基于对比表写成文章
Step 2: 并行派发前两个任务
delegate_task(goal="搜索 LangChain 优缺点", ...)
delegate_task(goal="搜索 CrewAI 优缺点", ...)
Step 3: 等结果回来,综合分析
"根据两个子任务的结果,LangChain 生态好但臃肿,
CrewAI 简洁但生态小..."
Step 4: 派发写作任务
delegate_task(goal="基于对比分析写文章", ...)
Step 5: 输出最终结果给用户
3.2 Hermes 的 delegate_task 实现
你在使用 Hermes 时调用的 delegate_task 工具,就是编排器模式的标准实现。它的架构:
// Hermes delegate_task 架构
delegate_task(
goal="子任务目标",
context="背景信息", // 父 Agent 提供上下文
toolsets=["web","terminal"], // 限制子 Agent 可用的工具
role="leaf" // leaf=不能进一步委托
) -> 返回子任务结果
// 子 Agent 的生命周期(从 agent_init.py 源码)
class AIAgent:
def __init__(self, ...):
self.max_iterations = 90 // 父 Agent 预算
self.iteration_budget = IterationBudget(
max_total=max_iterations
)
// 子 Agent 的预算独立(来自 delegation.max_iterations=50)
// 父子 Agent 的 iteration budget 互相独立
// 这意味着父 Agent 可以花 50 轮委托,子 Agent 再花 50 轮
// 代理合计可以超过父 Agent 的 90 轮上限
// —— async_delegation.py(386行)
// 后台委托:子 Agent 在独立线程运行
// 完成后通过 completion_queue 通知父 Agent
// 结果包含完整的 task-source block:
// original goal + context + toolsets + model +
// dispatch_time + status + full result summary
和 Hermes 的对照:
你刚才调用了 3 次 delegate_task 来并行调研 EDA 公司招聘——
这就是编排器模式!
每次 delegate_task 都产生了 1 个子 Agent:
- 子 Agent 1:调研国际三巨头(花了很多步尝试各种方法)
- 子 Agent 2:调研 A 股上市 EDA 公司
- 子 Agent 3:调研独角兽 EDA 公司
3 个子 Agent 并行运行,总共花了 ~500 秒但实际等效串行要 1500+ 秒。
然后我(编排器)汇总了所有结果。
3.3 编排器模式的设计考量
面试重点:设计编排器时需要考虑什么?
| 考量点 | 说明 |
| 委托粒度 | 任务拆太大 → 子Agent又要委托(嵌套);拆太小 → 通信开销 > 收益 |
| 上下文传递 | 父 Agent 给子 Agent 传 context,子 Agent 返回 summary。传多了浪费 token,传少了子 Agent 不知道背景 |
| 并发控制 | 同时跑多少个子 Agent?Hermes 默认 3(delegation.max_concurrent_children) |
| 嵌套深度 | 子 Agent 能不能再委托?Hermes 支持 max_spawn_depth 控制 |
| 超时与预算 | 子 Agent 跑太久怎么办?独立 iteration budget + timeout |
| 结果验证 | 子 Agent 可能产生幻觉。父 Agent 应验证再采用(我在 EDA 调研中检查了子 Agent 输出) |
| 错误隔离 | 一个子 Agent 失败不影响其他。父 Agent 可以决定重试或跳过 |
四、模式 B:蜂群(Swarm)
4.1 什么场景适合蜂群?
- 复杂协作 —— 多个 Agent 需要来回讨论、迭代(如多轮辩论式研究)
- 去中心化 —— 没有明显的"主管"角色,每个 Agent 有独立决策权
- 动态发现 —— Agent 数量和角色不固定,根据需要动态加入
- A2A 协议适用 —— 跨组织的 Agent 需要通过标准协议通讯
4.2 编排器 vs 蜂群:选型决策
选型决策树:
任务需要并行处理子任务吗?
├── 是 → 子任务依赖关系明确吗?
│ ├── 是 → 编排器(主管分配任务)
│ └── 否 → 蜂群(自由协作)
│
├── 否 → 需要一个"主管"角色吗?
│ ├── 是 → 编排器
│ └── 否 → 单 Agent 就够了
│
需要跨组织协作吗?
├── 是 → A2A 协议 + 蜂群模式
└── 否 → 内部单系统,编排器就够了
4.3 蜂群的工程挑战
- 收敛难 —— 多个 Agent 自由讨论可能永远不结束
- 可观测性差 —— 没有中心节点,追踪困难
- Token 爆炸 —— N 个 Agent 互相传上下文,开销大
- 死锁/活锁 —— Agent A 等 B,B 等 A 的循环依赖
五、A2A 协议与多 Agent 系统
第 3 课我们讲过 A2A(Agent-to-Agent Protocol)。和多 Agent 系统的关系:
- 编排器模式 + A2A = 编排器发现子 Agent → Agent Card 握手 → 发任务 → 收结果
- 蜂群模式 + A2A = Agent 通过 Agent Card 广播能力 → 其他 Agent 按需调用
- 跨组织 = 你的 Agent 调用第三方 Agent(比如查天气、下单),通过 A2A 标准协议
六、综合案例:多 Agent 系统的设计
┌── 企业级智能客服系统 ──────────────────────┐
│ │
│ 用户问题 │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Router Agent │ ← 分析用户意图 │
│ │ (分类器) │ │
│ └──────┬───────┘ │
│ │ │
│ ┌───┼───┬───────┬───────┐ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ 售前│ │ 售后│ │ 技术│ │ 投诉│ │
│ │Agent│ │Agent│ │Agent│ │Agent│ │
│ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │ │ │ │ │
│ └───────┴───┬───┴───────┘ │
│ ▼ │
│ ┌──────────┐ │
│ │ Escalation│ ← 复杂问题升级 │
│ │ Manager │ │
│ └──────────┘ │
│ │
└──────────────────────────────────────────────┘
Router Agent: 分析用户意图 → 路由到正确的子 Agent
子 Agent: 各自有专门的 tools/knowledge/context
Escalation Manager: 超出能力范围时升级到人工
七、面试问答
🎯 Q1:"设计一个多 Agent 系统,你会选择编排器还是蜂群?为什么?"
回答框架:
1. 先分析任务特征:子任务依赖关系是否明确?是否需要集中控制?
2. 选编排器如果:任务可拆分成独立子任务,需要主管角色汇总结果,需要精确控制执行顺序
3. 选蜂群如果:任务需要自由探索和迭代,没有固定流程,多个 Agent 需要互相协作才能完成
4. 实际折衷:多数生产系统用编排器 + 有限的子 Agent 自主权(混合模式)
补充:我实际使用 Hermes 的 delegate_task 时,发现编排器更适合我——因为任务拆分明细、结果需要集中汇总。蜂群模式更适合开放式研究场景。
🎯 Q2:"子 Agent 跑超时了或者失败了怎么办?"
5 层容错:
1. 独立超时:每个子 Agent 有独立的 iteration budget + 时间上限
2. 错误隔离:一个子 Agent 失败不影响其他子 Agent 和父 Agent
3. 选择性重试:父 Agent 根据失败原因决定是否重试(网络错误重试,逻辑错误不重试)
4. 降级输出:子 Agent 挂了 → 父 Agent 用自己的能力补位(虽然慢但能出结果)
5. 部分结果:如果 5 个子任务 4 个成功,先输出 4 个的结果并标注"第 5 个失败"
🎯 Q3:"多 Agent 系统的 token 成本怎么控制?"
框架:
1. Token 预算分层:父 Agent 和子 Agent 各有独立预算(Hermes 父 90 轮,子 50 轮)
2. 上下文隔离:子 Agent 的上下文互不相通,各自独立 → 不会 N 倍膨胀
3. 精简 context 传递:父 Agent 给子 Agent 传 context 时要精炼,不要整个对话历史
4. 子 Agent 结果摘要:子 Agent 返回完整结果,但父 Agent 可以要求"只给我摘要"
5. 避免循环调用:设定最大嵌套深度(Hermes 默认 1 层,即子 Agent 不能进一步委托)
八、课后行动
- ✅ 区分编排器和蜂群两种模式,理解各自的适用场景
- ✅ 回忆今天的 EDA 调研 —— 3 个并行子任务就是编排器模式
- ✅ 准备 Q1(多 Agent 选型)和 Q3(Token 成本控制)的面试回答
- ⏭ 下节课:Go 框架架构设计——完整的框架接口定义
📁 0005-multi-agent.html
📁 源码参考:/usr/local/lib/hermes-agent/tools/async_delegation.py (386行)
📁 源码参考:/usr/local/lib/hermes-agent/agent/agent_init.py (delegate_task 派发)
📁 相关概念:第3课 A2A 协议 | 你在本 session 中的 3 次 delegate_task 调用
📝 有问题随时问。