(十三)多Agent协同

(十三)多Agent协同 --- 1+1>2

系列第13篇

作者:挖AI金矿


截至上一篇文章,我们一直在讨论单个Hermes Agent的能力。单个Agent已经很强了------它可以访问工具、调用Skill、管理记忆、切换模型。但在真实的大型项目中,单个Agent往往力不从心。

想想看:你要同时做三件事------调研数据库选型、写初版API代码、设计部署方案。如果只有一个Agent,它会顺序处理,要么你干等着,要么上下文被不同任务的内容撑爆。

多Agent协同就是解决方案。单个Agent是"一个人的团队",多Agent是你指挥的"一个团队"。

1.什么时候需要多Agent?大任务拆解

不是所有场景都需要多Agent。单Agent能搞定的事情,强行拆成多Agent反而增加复杂度。那什么时候该用?

1.1适合多Agent的场景

场景1:高度平行的子任务

比如你要同时评估Three.js、WebGL和Canvas2D三个前端图形方案。用单Agent,你得一个个问,效率很低。用多Agent,三个子Agent同时去调研,你在主会话中汇总结果。

场景2:角色分工不同的任务

比如开发一个API接口:A Agent负责写handler和业务逻辑,B Agent负责写单元测试,C Agent负责写集成测试。每个Agent只需要关注自己的角色。

场景3:上下文敏感的复杂流程

比如你修复一个bug:先让A Agent分析问题根因,B Agent基于分析结果写修复代码,C Agent验证修复是否正确。每个Agent收到的上下文是精简的------A只需看错误日志,B只需看A的输出和代码库,C只需看B的变更。

场景4:需要独立工具权限的任务

假设你需要同时查询生产环境日志和开发环境配置。单Agent切换上下文很麻烦。两个子Agent各持有不同的工具集------一个只读生产数据库,一个只读开发配置------互不干扰。

1.2不适合多Agent的场景

不需要拆的场景:简单问答、格式化输出、快速代码生成------Agent一轮对话就能搞定,拆成多Agent纯粹是过度设计。

不适合拆的场景:高度依赖前后文连续性的任务------比如逐步调试一个复杂bug,每一步都依赖上一步的精确结果。这种情况下,单Agent的完整上下文窗口比多Agent的碎片化上下文更有用。

1.3决策原则

如果两个任务之间需要频繁同步中间结果,用单Agent。
如果两个任务可以独立运行到底,只在最后合并,用多Agent。

在实际工作中,我通常这样判断:如果需要创建的中间文件超过3个,或者需要访问的工具权限差异很大,或者需要并行获取多个信息源,就考虑用多Agent。

2.delegate_task:把任务分配给子Agent

Hermes的多Agent协作核心命令是 delegate_task。你可以把它理解成"委托"------把一项子任务派发给另一个Agent实例去独立完成。

2.1基本用法

bash 复制代码
delegate_task --name "调研-PostgreSQL-vs-TiDB" \
--instruction "对比PostgreSQL 16和TiDB 8.1在以下维度的差异:\n1. 一致性模型\n2. 水平扩展能力\n3. 事务支持\n4. 运维复杂度\n5. 适用场景\n\n输出一个markdown格式的对比表。" \
--tools database_search,web_search

参数说明:

  • --name:子任务名称(用于后续引用)
  • --instruction:给子Agent的完整指令,越详细越好
  • --tools:子Agent可以使用的工具集(逗号分隔)
  • --model:(可选)指定子Agent使用的模型,不指定则用默认模型
  • --context:(可选)传给子Agent的附加上下文,比如相关代码片段

2.2子Agent的执行过程

当你执行 delegate_task 后:

  1. Hermes创建一个新的Agent实例(子Agent)
  2. 子Agent收到你的指令和工具集
  3. 子Agent独立运行,使用自己的上下文窗口
  4. 子Agent完成任务后,结果返回给主Agent
  5. 主Agent将结果展示给你,或继续处理

整个过程是异步的------你不需要等待。子Agent在后台运行,你可以继续和主Agent对话。

2.3查看子任务状态

bash 复制代码
# 列出所有活跃的子任务
delegate_task list

# 输出
# 任务ID │ 名称           │ 状态   │ 进度  │ 耗时
# t-001  │ 调研-PostgreSQL │ 运行中 │ 65%   │ 2m30s
# t-002  │ 写API代码       │ 已完成 │ 100%  │ 1m15s
# t-003  │ 写测试          │ 待分配 │ 0%    │ -

# 查看某个子任务的详细进展
delegate_task status t-001

# 获取已完成任务的结果
delegate_task result t-002

2.4在一个任务中引用另一个任务的结果

这是多Agent协同的关键能力------子任务之间可以传递结果:

bash 复制代码
# 子任务A:分析日志
delegate_task --name "分析错误日志" \
--instruction "分析以下日志,找出错误根因" \
--context "$(cat /var/log/app/error.log)"

# 等待A完成后
delegate_task --name "写修复代码" \
--instruction "基于错误分析结果,写修复代码" \
--context "$(delegate_task result t-001)"

子任务B会收到子任务A的输出作为上下文,实现链式处理。

3.子Agent的上下文隔离 + 独立工具集

多Agent模式最容易被忽视但最重要的特性就是上下文隔离。

3.1为什么需要上下文隔离

假设你的主Agent已经聊了很多轮,上下文窗口里塞满了各种信息:项目背景、技术栈讨论、之前的代码修改记录。

如果在这个上下文中分配"写单元测试"这个子任务,子Agent会继承主Agent的全部上下文吗?

答案:不会。 这也是正确的设计。

子Agent的上下文是干净的 ------它只看到你通过 --instruction--context 参数显式传给它的信息。这带来几个好处:

  1. 减少干扰:子Agent不会因为主会话中的无关讨论而"分心"
  2. 节省tokens:子Agent的上下文只包含与其任务相关的内容
  3. 信息隔离:敏感信息(如生产数据库密码)不会传递到不需要它的子Agent

3.2独立工具集

每个子Agent可以配置独立的工具集:

bash 复制代码
# 子Agent A:只能读数据库
delegate_task --name "查询用户数据" \
--instruction "查询最近一周的活跃用户数" \
--tools database_read

# 子Agent B:只能写代码
delegate_task --name "生成数据报表" \
--instruction "基于查询结果生成HTML报表" \
--tools file_write

# 子Agent C:只能访问网络
delegate_task --name "搜索最佳实践" \
--instruction "搜索Go并发编程的最佳实践" \
--tools web_search

通过限制工具集,你可以精确控制每个子Agent的能力边界,避免意外操作(比如一个负责写代码的Agent不小心删了生产数据库)。

3.3工具集配置

可用的工具类型包括:

3.4上下文空间管理

子Agent也有自己的上下文限制。你可以给它分配更多或更少的上下文容量:

bash 复制代码
# 给子Agent 32K的上下文(适用于需要处理大量日志的分析任务)
delegate_task --name "分析大量日志" \
--instruction "...
--context_limit 32000

# 给子Agent 8K的上下文(适用于简单的查询任务)
delegate_task --name "简单查询" \
--instruction "...
--context_limit 8000

合理分配上下文容量,让系统资源用在刀刃上。

4.实操:让子Agent写代码,自己继续需求分析

这是一个实际生产中我会反复使用的场景------让你真正体会"多Agent"的效率。

4.1场景说明

你在开发一个用户认证服务,需要同时做两件事:

  1. 继续完善需求分析(你亲自和主Agent讨论)
  2. 写注册接口的代码(交给子Agent)

两步可以完全并行。

4.2第一步:分配代码任务

bash 复制代码
delegate_task --name "写注册接口" \
--instruction "实现用户注册API接口,包含以下功能:
1. POST /api/v1/register 接收 email, password, nickname
2. 密码使用bcrypt加密存储
3. 验证email格式和密码强度(最少8位,含大小写字母和数字)
4. 返回201状态码和用户ID
5. 如果email已存在,返回409冲突

技术要求:
- Go + Gin框架
- GORM操作PostgreSQL
- 使用testify写单元测试
- 错误使用中文返回

输出文件:
- handlers/register.go
- services/register_service.go
- models/user.go
- handlers/register_test.go" \
--tools code_write,code_read,git_operations \
--model anthropic/claude-3-5-sonnet-20241022

4.3第二步:继续和主Agent讨论

在子Agent写代码的同时,你可以继续和主Agent讨论需求:

bash 复制代码
你: "我们还需要考虑密码重置流程,你觉得用邮箱验证码还是安全问题好?"

主Agent: "建议用邮箱验证码方案,原因如下:
1. 安全性更高(安全问题容易被暴力破解)
2. 用户体验更好(不用记住额外的答案)
3. 和注册流程的邮箱验证逻辑可以复用

流程设计:
1. 用户请求重置 -> 发送6位验证码到邮箱
2. 用户提交验证码 -> 验证通过后进入重置页面
3. 用户提交新密码 -> 更新数据库

你觉得这个方案怎么样?"

4.4第三步:获取子Agent结果

当子Agent完成后:

bash 复制代码
delegate_task status t-001
# 状态: 已完成

delegate_task result t-001

子Agent返回的结果包括它生成的所有代码文件内容。你可以审查后合并到项目:

bash 复制代码
# 或者让主Agent帮你审查子Agent的输出
"帮我看一下子Agent写的注册接口代码,重点检查安全性"

4.5第四步:继续分配更多任务

基于讨论结果和子Agent的代码,可以继续分配新任务:

bash 复制代码
delegate_task --name "写密码重置接口" \
--instruction "基于以下需求实现密码重置API:
[粘贴刚才讨论的邮箱验证码方案]

数据库需要新增表:
- password_reset_tokens (email, token, expires_at)

输出文件:
- handlers/reset_password.go
- services/reset_service.go
- models/reset_token.go
" \
--context "$(delegate_task result t-001)" \
--tools code_write,code_read

注意 --context 参数传入了第一个子Agent的输出,这样第二个子Agent可以基于已有代码继续开发,保持代码风格和结构一致。

4.6效果对比

单Agent模式(串行):

bash 复制代码
1. 讨论需求(10轮对话)→ 15分钟
2. 写注册接口(Agent写代码)→ 5分钟(这段时间你发呆)
3. 讨论密码重置方案(5轮对话)→ 8分钟
4. 写密码重置接口(Agent写代码)→ 5分钟
总计: 33分钟(你实际干活25分钟,等Agent 8分钟)

多Agent模式(并行):

bash 复制代码
1. 子Agent写注册接口(后台运行)
同时:你讨论密码重置方案 → 10分钟
2. 密码重置方案确定后,分配第二个子Agent写接口
同时:你审查第一个子Agent的代码 → 5分钟
3. 所有子Agent完成 → 你汇总结果
总计: 15分钟(你全程在干活,没有等待时间)

效率提升50%以上,而且你的注意力没有被中断。

5.子Agent能力边界(什么不能做)

子Agent虽然强大,但也有明确的边界。了解这些边界可以帮助你合理分配任务。

5.1子Agent不能做的事

1. 不能创建新的子Agent

子Agent不能递归委派任务。这是一个安全设计------防止无限递归和资源耗尽。

bash 复制代码
# ❌ 子Agent的内部不能执行 delegate_task
# 如果你需要多层级委派,只能从主Agent层面发起

2. 不能修改主Agent的配置

子Agent不能更改主Agent的记忆、Skills、配置等。它对主Agent工作区是只读的。

3. 不能访问主会话的未共享上下文

子Agent只能看到你通过参数显式传递的信息。主会话中之前讨论的内容,如果没有传给子Agent,它不知道。

4. 不能执行交互式操作

子Agent不能要求用户输入、不能打开交互式编辑器。它只能基于给定的指令和工具执行任务。

5.2子Agent的局限性

除了明确的"不能做",还有一些实际局限性:

上下文上限:子Agent默认使用较小的上下文窗口(通常是16K-32K)。如果任务需要分析100万行日志,你可能需要拆分或使用支持长上下文的模型。

工具范围受限:子Agent只能使用你明确授予的工具。如果某个任务中途需要额外的工具,你必须重新分配任务。

结果大小限制:子Agent的输出结果默认限制在几千行内。如果要求生成一个完整的Rails项目(上百个文件),结果可能被截断。这种情况下,应该让子Agent直接写入文件系统,而不是返回全部文本。

5.3安全边界

yaml 复制代码
# 在 config.yaml 中配置子Agent的安全策略
subagent:
security:
# 允许子Agent访问的路径(白名单)
allowed_paths:
- /home/user/projects/
# 禁止子Agent执行的命令(黑名单)
forbidden_commands:
- "rm -rf"
- "DROP TABLE"
# 禁止子Agent访问的网络
forbidden_hosts:
- "10.0.0.*"  # 内网

6.并行 vs 串行的选择

这是多Agent协同中最需要权衡的设计决策。

6.1并行模式

多个子Agent同时运行,互不依赖。

bash 复制代码
# 三个调研任务并行执行
delegate_task --name "调研Three.js" --instruction "..." &
delegate_task --name "调研WebGL" --instruction "..." &
delegate_task --name "调研Canvas2D" --instruction "..." &

# 等待所有完成
delegate_task wait-all

优点:总耗时 = 最慢子任务的耗时,吞吐量最大化

缺点:如果子任务需要共享资源(比如都写同一个文件),可能产生冲突

适用场景

  • 独立调研任务
  • 不相关的代码生成
  • 数据采集

6.2串行模式

子任务顺序执行,后一个依赖前一个的输出。

bash 复制代码
# 第一步:分析问题
delegate_task --name "分析Bug" --instruction "分析堆栈..."

# 等第一步完成
delegate_task --name "修复Bug" \
--context "$(delegate_task result t-001)" \
--instruction "基于分析结果写修复代码..."

# 等第二步完成
delegate_task --name "验证修复" \
--context "$(delegate_task result t-002)" \
--instruction "验证修复是否正确..."

优点:保证数据一致性,后续任务基于完整的前置结果

缺点:总耗时 = 所有子任务耗时之和

适用场景

  • CI/CD流水线
  • 逐层代码审查
  • 依赖链式输出

6.3混合模式

大多数实际场景采用的是混合模式------某些子任务并行,某些串行。

bash 复制代码
# 阶段1:并行调研
delegate_task --name "调研数据库" --instruction "..." &
delegate_task --name "调研缓存方案" --instruction "..." &

delegate_task wait-all

# 阶段2:基于调研结果写设计方案
delegate_task --name "写设计文档" \
--context "$(delegate_task result t-001)\n$(delegate_task result t-002)" \
--instruction "基于数据库和缓存方案调研结果,写设计文档..."

# 阶段3:基于设计文档并行实现
delegate_task --name "实现数据库层" --context "$(delegate_task result t-003)" --instruction "..." &
delegate_task --name "实现缓存层" --context "$(delegate_task result t-003)" --instruction "..." &

delegate_task wait-all

这种模式既发挥了并行的效率优势,又保证了阶段间的依赖关系。

7.实战:用多Agent同时调研3个技术方案

纸上谈兵这么多,我们来一个完整的实战案例。

7.1任务描述

你要为一个新的电商后端做技术选型。需要在1小时内完成三个技术模块的初步调研和推荐方案:

  1. 消息队列: RabbitMQ vs Kafka vs Redis Streams
  2. 搜索引擎: Elasticsearch vs Meilisearch vs Typesense
  3. 监控方案: Prometheus+Grafana vs Datadog vs New Relic

7.2第一步:分配三个并行调研任务

bash 复制代码
# 任务1:消息队列调研
delegate_task --name "调研-MQ" \
--instruction "对比 RabbitMQ、Kafka 8.0、Redis Streams 以下维度:
1. 消息可靠性(持久化、ACK机制)
2. 吞吐量(每秒可处理多少消息)
3. 运维复杂度(需要几个组件、维护成本)
4. Go SDK成熟度
5. 典型场景(什么场景选哪个)

最后给出推荐:对于中等规模的电商后端(日均100万订单),推荐哪个?为什么?

输出为markdown格式。" \
--tools web_search \
--model deepseek/deepseek-chat

# 任务2:搜索引擎调研
delegate_task --name "调研-搜索" \
--instruction "对比 Elasticsearch 8.x、Meilisearch 1.6、Typesense 0.26 以下维度:
1. 搜索速度(特别是中文分词效果)
2. 索引构建速度
3. 资源消耗(内存/CPU)
4. 高可用方案
5. Go客户端

场景需求:电商商品搜索,日均500万搜索请求,需要支持拼音搜索、拼写纠错、分类过滤。

输出为markdown格式。" \
--tools web_search \
--model deepseek/deepseek-chat

# 任务3:监控方案调研
delegate_task --name "调研-监控" \
--instruction "对比 Prometheus+Grafana、Datadog、New Relic 以下维度:
1. 部署方式(自建 vs SaaS)
2. 成本估算(日均10万指标点)
3. 告警能力
4. APM支持
5. 自定义Dashboard灵活性
6. 和Go应用的集成度

输出为markdown格式。" \
--tools web_search \
--model deepseek/deepseek-chat

7.3第二步:监控进展

bash 复制代码
while true; do
clear
delegate_task list
sleep 10
done

输出:

bash 复制代码
t-001 | 调研-MQ    | 已完成  | 100% | 1m45s
t-002 | 调研-搜索   | 运行中  | 70%  | 2m10s
t-003 | 调研-监控   | 运行中  | 50%  | 1m30s

7.4第三步:最早完成的任务先审核

任务1最快完成。不等其他两个,先看结果:

bash 复制代码
delegate_task result t-001

假设结果中推荐了 Kafka,但你的团队对Kafka不熟悉,你可以继续和主Agent讨论:

bash 复制代码
你: "任务1推荐了Kafka,但团队对Kafka不熟悉,RabbitMQ的经验更丰富"

主Agent: "基于团队的技术栈考虑,RabbitMQ也是合理的选择。
不过可以折中:先用RabbitMQ,预留Kafka迁移路径。
建议在消息处理层做抽象,未来可以无缝切换。

具体建议:
1. 使用RabbitMQ Streams插件(支持消息回溯)
2. 消息处理接口抽象化(interface定义)
3. 预留Kafka的topic设计(分区键策略)

7.5第四步:汇总所有结果

三个子任务都完成后,让主Agent汇总:

bash 复制代码
"把三个调研结果汇总成一个技术选型报告,包含:
1. 每个模块的推荐方案
2. 推荐理由
3. 备选方案
4. 实施建议(优先级、风险点)
5. 团队需要提前学习的技术

输出格式为markdown,保存到 docs/tech-stack-report.md"

最终产出的一份完整报告,包含了消息队列、搜索引擎和监控方案的选型建议,而且三个子任务的调研是并行完成的------总耗时约3分钟,而不是串行的9分钟。

8.多Agent的高级模式

除了基本的委派模式,还有一些高级用法值得了解。

8.1辩论模式

让两个子Agent从不同角度分析同一个问题,然后汇总:

bash 复制代码
delegate_task --name "正方-用微服务" \
--instruction "从架构灵活性、团队协作、技术多样性角度,论证为什么应该采用微服务架构" \
--model gpt-4o

delegate_task --name "反方-用单体" \
--instruction "从开发效率、运维复杂度、性能角度,论证为什么应该采用单体架构" \
--model deepseek/deepseek-chat

delegate_task wait-all

"综合正反两方的分析,给出最终建议。考虑项目实际情况:5人团队,开发周期6个月,预期1年后用户量增长10倍。"

这种模式能避免单一视角的局限性,特别是对于复杂的技术决策。

8.2审查模式

一个Agent写代码,另一个Agent审查:

bash 复制代码
# Agent A:写代码
delegate_task --name "写订单模块" \
--instruction "实现订单创建和查询功能..." \
--tools code_write

delegate_task wait t-001

# Agent B:审查代码
delegate_task --name "审查订单模块" \
--context "$(delegate_task result t-001)" \
--instruction "代码审查,重点关注:
1. SQL注入风险
2. 并发安全问题(订单状态更新)
3. 错误处理是否完备
4. 是否符合Go最佳实践

给出审查报告和修改建议。" \
--tools code_read

8.3看门狗模式

主Agent负责协调,子Agent负责监控:

bash 复制代码
# 一个持续运行的任务
delegate_task --name "监控日志" \
--instruction "每分钟检查一次应用日志,
如果发现ERROR级别且包含'panic'或'fatal'的日志,
立即报告给主Agent" \
--tools file_read \
--persist true

--persist true 让子Agent长期运行,持续监控。

9.注意事项与陷阱

9.11. 不要过度拆分

三个独立调研任务并行跑是好的,但把一个"写注册接口"拆成"写handler"、"写service"、"写model"三个子任务就过头了------Agent写这三部分通常在一段上下文中完成,拆分反而增加了沟通开销。

经验法则:如果子任务的指令少于100字,说明拆得太细了。

9.22. 注意子Agent的数量限制

同时运行的子Agent数量有限制(默认3-5个,取决于配置)。超过限制的任务会排队等待。

yaml 复制代码
# 在config.yaml中配置
subagent:
max_concurrent: 5     # 最大并行数
queue_size: 10        # 队列长度
timeout: 300          # 单任务超时(秒)

9.33. 避免循环依赖

bash 复制代码
# ❌ 错误:循环引用
delegate_task --name A --context "$(delegate_task result B)"
delegate_task --name B --context "$(delegate_task result A)"

# ✅ 正确:线性依赖
delegate_task --name A
delegate_task --name B --context "$(delegate_task result A)"

9.44. 子Agent失败处理

任何子Agent都可能失败(超时、工具出错、模型异常)。要有容错机制:

bash 复制代码
# 重试失败的任务
delegate_task retry t-001

# 查看失败原因
delegate_task log t-001

# 如果某个子任务不重要,可以忽略
delegate_task cancel t-001

10.总结

多Agent协同是Hermes Agent最接近"团队协作"的功能。它让你从一个AI助手的使用者,变成一个AI团队的指挥者。

今天的关键点:

  1. 何时用:大任务中有多个独立子任务时使用
  2. 怎么用delegate_task 分配任务,独立上下文+独立工具集
  3. 并行vs串行:独立任务并行,依赖任务串行
  4. 实战案例:并行调研技术方案、边写代码边讨论需求
  5. 高级模式:辩论、审查、看门狗
  6. 注意事项:不过度拆分、注意数量和依赖关系

下一篇文章,我们将讨论Hermes Agent的安全与权限控制------如何安全地让AI访问你的代码和系统。

作者:挖AI金矿

系列:Hermes Agent 从小白到高级 --- 第 13/18 篇

下一篇:安全与权限控制 --- 把Agent关进笼子里

相关推荐
追逐时光者2 小时前
白嫖小米 MiMo 百万亿 Token,附 Claude Code 配置全流程!
ai编程
笨笨饿2 小时前
69_如何给自己手搓一个串口
linux·c语言·网络·单片机·嵌入式硬件·算法·个人开发
Techlin3 小时前
Claude Opus 4.7 编程实战:怎么用最新旗舰模型写复杂业务代码?完整配置 + 踩坑记录
ai编程·claude
DogDaoDao3 小时前
【GitHub】andrej-karpathy-skills:让 AI 编程助手告别三大通病
人工智能·深度学习·程序员·大模型·github·ai编程·andrej-karpathy
易生一世3 小时前
自动化Pipeline中的Kiro CLI详解
自动化·pipeline·key·headless·kiro
程序员鱼皮5 小时前
狂烧 40 亿 tokens,公开我的 7 套 AI 工作流!
计算机·ai·程序员·编程·ai编程
Hello_Embed6 小时前
Windows 安装 Claude Code 并接入 模型
windows·笔记·ai编程
sunneo6 小时前
专栏D-团队与组织-03-产品文化
人工智能·产品运营·aigc·产品经理·ai编程
薛定猫AI6 小时前
【深度解析】Kimi K2.6 的长上下文 Agentic Coding 能力与 OpenAI 兼容 API 接入实践
人工智能·自动化·知识图谱