子代理与并行任务:Hermes Agent 的多线程工作方式

目录

  1. 一个 Agent 不够用的时候
  2. spawn 机制
    1. 基本概念
    2. 一个实际的执行流程
  3. 什么时候用子代理
    1. 适合的场景
    2. 不适合的场景
  4. Worktree 并行
    1. 什么是 worktree 并行
    2. 实际例子
  5. 子代理的资源控制
    1. 最大并发数
    2. 子代理超时
    3. Token 预算
    4. 后端选择
  6. 子代理之间的通信
  7. 错误处理
  8. 实际使用方式
  9. 性能数据
  10. 嵌套子代理
  11. 子代理与技能系统
  12. 和记忆系统的关系
  13. 使用建议

一个 Agent 不够用的时候

单个 Agent 一次只能做一件事。当你面对一个需要多线并进的复杂任务时,排队等待不是个好选择。

举个例子:你让 Hermes Agent 「对这个项目做一次全面的代码审查」。一个 Agent 去看的话,要先审核 auth 模块,再审核数据库层,再审核 API 层,再审核前端……挨个来,可能要好几分钟。

但这些审核之间其实没有依赖关系。auth 模块的审核不需要等数据库层审核完才开始。

Hermes Agent 的解决方案是:spawn 子代理(Sub-Agent)。主 Agent 把任务拆分成多个子任务,每个子任务分配一个独立的子代理并行执行,最后汇总结果。

spawn 机制

基本概念

spawn 是 Hermes Agent 创建子代理的方式。主 Agent(parent)可以 spawn 一个或多个子代理(child),每个子代理:

  • 有自己独立的 ReAct 循环
  • 有自己的执行上下文
  • 可以使用工具
  • 执行完后把结果返回给主 Agent

子代理之间互相隔离——A 子代理不知道 B 子代理在干什么,也不能直接和 B 通信。所有的协调都通过主 Agent 进行。

一个实际的执行流程

假设你说:「帮我同时检查三台服务器的系统状态」

主 Agent 的处理过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
主 Agent 推理: 需要检查三台服务器,任务互相独立,可以并行

主 Agent 行动:
spawn 子代理 A → 检查 server-1 的系统状态
spawn 子代理 B → 检查 server-2 的系统状态
spawn 子代理 C → 检查 server-3 的系统状态

[三个子代理并行执行中...]

子代理 A 返回: server-1 状态正常,CPU 23%,内存 45%
子代理 B 返回: server-2 发现磁盘使用 91%,需要关注
子代理 C 返回: server-3 状态正常,CPU 15%,内存 38%

主 Agent 汇总: 整合三份报告,标注 server-2 的磁盘告警

三台服务器的检查几乎同时完成,而不是串行等待三次。

什么时候用子代理

子代理不是万能的。它适合特定类型的任务:

适合的场景

批量独立操作:同时检查多台服务器、同时处理多个文件、同时测试多个 API 端点。关键词是「独立」——各个子任务之间没有数据依赖。

代码审查:按模块拆分,每个子代理审查一个模块。

数据采集:同时从多个数据源抓取信息。比如你想了解某个技术栈的最新动态,让几个子代理分别搜索不同的信息源。

多方案评估:让不同的子代理用不同的方案解决同一个问题,然后主 Agent 比较各方案的优劣。

不适合的场景

强依赖的串行任务:后一步必须用前一步的结果。这种任务用子代理反而更慢(多了 spawn 和收集的开销)。

需要共享状态的任务:两个子任务需要读写同一个文件或数据库。并行操作可能导致冲突。

简单任务:检查一台服务器的状态,spawn 子代理的开销比直接执行还大。只有任务足够复杂或数量足够多时,并行才有收益。

Worktree 并行

在代码开发场景下,Hermes Agent 的子代理支持 Git worktree 并行。

什么是 worktree 并行

Git worktree 允许同一个仓库同时 checkout 多个分支到不同目录。Hermes Agent 利用这个特性,让多个子代理在同一个仓库的不同 worktree 中并行工作。

实际例子

你说:「我要同时给 auth、payment、notification 三个模块加单元测试」

主 Agent 的处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1. 为每个任务创建一个 Git worktree
git worktree add /tmp/hermes-auth-work auth-tests
git worktree add /tmp/hermes-payment-work payment-tests
git worktree add /tmp/hermes-notif-work notification-tests

2. spawn 三个子代理,每个在自己的 worktree 中工作
子代理 A → /tmp/hermes-auth-work/ 编写 auth 模块测试
子代理 B → /tmp/hermes-payment-work/ 编写 payment 模块测试
子代理 C → /tmp/hermes-notif-work/ 编写 notification 模块测试

3. 三个子代理并行编写测试代码

4. 所有子代理完成后,主 Agent 合并结果
git merge auth-tests
git merge payment-tests
git merge notification-tests

5. 清理 worktree

三个模块的测试代码同时编写,不会互相干扰(因为在不同的 worktree 目录里),写完后合并到主分支。

这在大型项目中特别有用。如果你有一个紧急的重构任务需要改动十几个文件,让子代理并行处理不同的文件组,效率能提升好几倍。

子代理的资源控制

并行执行意味着更多的资源消耗。Hermes Agent 提供了控制机制:

最大并发数

1
2
agent:
max_sub_agents: 5

限制同时运行的子代理数量。超过这个数的子任务会排队等待。

子代理超时

1
2
agent:
sub_agent_timeout: 120 # 秒

单个子代理的最大执行时间。超时后会被强制终止,主 Agent 会收到超时通知。

Token 预算

1
2
agent:
sub_agent_max_tokens: 5000

每个子代理的最大 token 消耗。防止某个子代理在一个奇怪的任务上烧掉太多 token。

后端选择

子代理默认继承主 Agent 的后端配置。但你也可以给子代理指定不同的后端:

1
2
agent:
sub_agent_backend: docker

这在安全场景下很有用——主 Agent 用 Local 后端(方便协调),子代理用 Docker 后端(隔离执行)。想了解更多关于后端选择的内容,可以看六大执行后端解析

子代理之间的通信

前面说了子代理之间不直接通信。但有些场景确实需要子代理之间交换信息。

Hermes Agent 的做法是通过主 Agent 中转:

1
2
3
子代理 A: 我发现 config.py 里的数据库连接字符串有问题
主 Agent: [收到 A 的发现,判断可能影响 B 的工作]
主 Agent → 子代理 B: 注意,数据库配置可能有变动,你检查 payment 模块时考虑一下

这种间接通信虽然没有直接通信快,但避免了子代理之间的耦合。主 Agent 作为协调者,能做更高层面的判断——比如 A 发现的问题是否真的影响 B。

错误处理

子代理执行过程中可能出错。Hermes Agent 的处理策略:

单个子代理失败:不影响其他子代理。主 Agent 收到失败通知后,可以决定是重试、跳过,还是用其他方式补救。

多个子代理失败:主 Agent 评估整体状况。如果大部分子代理都失败了,可能是系统性问题(比如网络断了),这时候会暂停所有子代理并告知用户。

子代理超时:强制终止并回收资源。主 Agent 可以选择用更大的超时重试,或者把超时的子任务拆得更小。

结果冲突:如果多个子代理的工作成果有冲突(比如都修改了同一个配置项),主 Agent 会识别冲突并让你决定用哪个。

实际使用方式

你不需要显式地「创建子代理」。在大多数情况下,Hermes Agent 会自己判断什么时候需要 spawn 子代理。

当你说「帮我查三台服务器的状态」,Agent 会自己判断:这三个任务独立、可以并行,于是 spawn 三个子代理。

但你也可以显式要求并行执行:

1
hermes "并行做以下三件事:1. 检查 server-1 状态 2. 备份数据库 3. 清理日志"

关键词「并行」会触发 Agent 使用子代理。

或者在交互模式中:

1
你: /parallel "检查 auth 模块的单元测试覆盖率" "检查 payment 模块的覆盖率" "检查 user 模块的覆盖率"

/parallel 是一个内置命令,显式地让多个任务并行执行。

性能数据

子代理带来的效率提升取决于任务类型和并发数:

场景 串行执行 3 子代理并行 提升
3 台服务器巡检 ~45 秒 ~18 秒 60%
5 个模块代码审查 ~3 分钟 ~50 秒 72%
10 个 API 端点测试 ~2 分钟 ~30 秒 75%

注意这不是线性加速——spawn 和汇总有开销,子代理之间也会竞争 API 调用资源(大部分 LLM API 有 rate limit)。

实际提升通常在 50%-75% 之间,取决于子任务的规模和并发数。

嵌套子代理

子代理自己能不能再 spawn 子代理?可以,但有深度限制:

1
2
agent:
max_spawn_depth: 2 # 最多嵌套 2 层

默认限制 2 层。也就是说:主 Agent → 子代理 → 孙代理,但孙代理不能再 spawn。

嵌套子代理适合递归式的任务。比如你说「帮我审查整个项目」,主 Agent 按目录拆分成多个模块,每个子代理拿到一个模块后,又按文件拆分成更小的子任务。

但嵌套太深会导致协调成本爆炸式增长。两层嵌套通常已经够用了。

子代理与技能系统

子代理也能利用技能系统。当子代理执行任务时,它会搜索技能库找匹配的技能。如果找到了,执行效率更高。

反过来,子代理成功完成的任务也可能触发技能生成。但这里有个设计考量:子代理生成的技能是否要存入主技能库?

当前的策略是:子代理成功完成且主 Agent 对结果满意时,才会存入主技能库。这避免了质量不佳的子代理执行结果污染技能库。

和记忆系统的关系

子代理的会话不会独立存入记忆系统。它们的执行轨迹会被合并到主 Agent 的会话中一起归档。

从记忆的角度看,子代理是透明的——你之后回忆这次任务时,看到的是一个完整的过程,不会分成主 Agent 和子代理的片段。

使用建议

  1. 让 Agent 自己决定是否并行。大部分情况下不需要你显式指定。Agent 的判断通常是合理的。

  2. 控制并发数。并行越多,API 调用越密集。如果你的 LLM API 有 rate limit,太多并发可能导致限流。建议 max_sub_agents 设为 3-5。

  3. 关注 token 消耗。子代理多了,token 消耗也线性增长。monitor 好你的 API 用量。

  4. Docker 后端更安全。多个子代理并行操作文件系统可能有冲突。Docker 后端让每个子代理在独立容器中工作,天然避免冲突。

  5. 复杂编排考虑写脚本。如果你的并行任务有复杂的依赖关系和分支逻辑,可能写一个编排脚本比纯靠 Agent 推理更可靠。cocoloop 社区有人分享过结合 Hermes Agent 和 Make/Taskfile 的方案,在 Agent 的灵活性和脚本的确定性之间取得平衡。

参与讨论

对这篇文章有疑问或想法?cocoloop 社区有不少开发者在讨论 Hermes 相关话题,欢迎加入交流。

前往 cocoloop 社区 →