Hermes SubAgent 编排知识库

一句话理解

Hermes 的 SubAgent 编排可以理解为:

主 Agent 接到一个复杂任务后,临时叫几个专员分别调查不同部分;专员把报告交回来,最后由主 Agent 统一判断、验证和回复用户。

它不是一群 agent 永久在线开会,而是一次任务中的临时分工:

用户提出任务

主 Agent 判断任务能不能拆

主 Agent 调用 delegate_task

Hermes 临时创建一个或多个 SubAgent

SubAgent 各自完成独立任务

SubAgent 返回 summary

主 Agent 综合结果并最终回答

和 Agent Loop 的关系

SubAgent 编排不是独立于 agent loop 的另一套系统。它本质上是主 Agent loop 中的一次工具调用。

也就是说,在 Hermes Agent Loop 技术知识与执行流程 里,模型本来可以调用 read_fileterminalwrite_file 等工具;当任务适合拆分时,模型也可以调用:

delegate_task

于是主 Agent loop 会暂时停在这个 tool call 上,等待 SubAgent 完成任务。

主 Agent loop

模型返回 tool_calls: delegate_task

Hermes 执行 delegate_task

启动 SubAgent 小循环

SubAgent 返回结果

结果作为 tool message 回填给主 Agent

主 Agent 继续 loop

生活化比喻

假设你问:

帮我分析这个项目为什么测试失败,并给出修复方向。

主 Agent 可能会这样分工:

SubAgent A:看失败日志和测试输出
SubAgent B:看相关模块代码
SubAgent C:看最近 git diff 和历史改动

这三个 SubAgent 就像三个临时专员。它们不会互相聊天,也不会知道完整聊天历史。它们只知道主 Agent 给它们的任务卡。

等它们回来后,主 Agent 可能收到:

A:失败集中在 gateway approval 流程。
B:代码里存在 base adapter 和 gateway runner 两层 guard。
C:AGENTS.md 提醒 approval/control commands 必须绕过两层 guard。

然后主 Agent 才做最终综合:

根因是新增命令只绕过了 runner guard,没有绕过 base adapter guard。
修复应同时处理两个入口,并补并发 approval 测试。

主 Agent 怎么决定开几个 SubAgent

主 Agent 不是知道一个固定答案,而是根据任务形状判断。

适合开 SubAgent 的信号

任务能拆成几条相互独立的线索:

看日志
看代码
看配置
看历史提交
比较多个方案
分别检查前端、后端、测试

这些线索彼此不强依赖,可以并行调查,就适合派 SubAgent。

不适合开 SubAgent 的情况

如果任务很小,主 Agent 自己做更好:

改一个函数名
解释一个概念
读一个文件
跑一个简单命令

如果任务强顺序依赖,也不适合一次开很多:

先改 schema
再改 API
再改 UI
最后补测试

这种情况通常由主 Agent 先推进关键路径,必要时只派一个 SubAgent 做旁路调查。

粗略判断公式

SubAgent 数量 ≈ 独立问题数量

但还要受三个限制:

1. 并发配置上限
2. 成本是否值得
3. 主 Agent 是否能有效综合结果

Hermes 默认:

delegation.max_concurrent_children = 3

所以一个健康的默认心智模型是:

小任务:0 个 SubAgent
中等任务:1 个 SubAgent 做旁路调查
复杂且可并行:2-3 个 SubAgent
大型任务:分批派,不一次铺太开

SubAgent 的任务卡必须清楚

SubAgent 没有主对话历史。因此主 Agent 必须把必要信息写进 goalcontext

不好的任务卡:

去看看怎么回事。

好的任务卡:

你负责调查 tests/gateway/test_approve_deny_commands.py 中
parallel_subagent_approvals 失败的原因。
 
上下文:我们怀疑 gateway 有两层 message guard:
base adapter 和 gateway runner。控制命令需要绕过两层。
 
请只读代码和测试,返回:
- 根因
- 相关文件
- 建议补测点

任务卡越清楚,SubAgent 越像专员;任务卡越模糊,SubAgent 越像随机游走。

默认编排结构:扁平 fan-out / fan-in

Hermes 默认是扁平结构:

主 Agent
  ├─ SubAgent A
  ├─ SubAgent B
  └─ SubAgent C

这个过程叫 fan-out / fan-in:

fan-out:主 Agent 把任务拆出去
fan-in:SubAgent 把结果收回来

默认 SubAgent 是 leaf,也就是叶子节点。叶子 SubAgent 不能继续派发新的 SubAgent。

Orchestrator 模式:允许 SubAgent 再拆任务

在特殊情况下,Hermes 支持让某个 SubAgent 变成 orchestrator。

结构会变成:

主 Agent
  └─ Orchestrator SubAgent
       ├─ Worker SubAgent A
       └─ Worker SubAgent B

但这不是默认行为。需要同时满足:

role = "orchestrator"
delegation.max_spawn_depth >= 2
delegation.orchestrator_enabled = true

默认配置是:

delegation.max_spawn_depth = 1

所以默认不允许嵌套。这样设计是为了避免:

成本爆炸
递归失控
上下文混乱
结果难以验证

SubAgent 能用哪些工具

SubAgent 会继承或被分配一组受限工具。

默认情况下,leaf SubAgent 不能使用这些工具:

delegate_task
clarify
memory
send_message
execute_code

原因分别是:

delegate_task:避免无限递归
clarify:SubAgent 不能直接打断用户问问题
memory:避免写共享长期记忆
send_message:避免跨平台副作用
execute_code:避免子代理用脚本绕过推理和控制边界

Orchestrator SubAgent 可以保留 delegate_task,但仍然不能使用 clarifymemorysend_messageexecute_code

SubAgent 的生命周期

SubAgent 是临时创建、临时关闭的。

创建 child AIAgent

运行 child.run_conversation()

生成 summary

返回给 parent

关闭 child

它不是后台常驻进程,也不会在父任务结束后继续运行。

如果父 Agent 被用户打断,例如 /stop、新消息或中断,Hermes 会把 interrupt 传给正在运行的 SubAgent。

上下文隔离

SubAgent 的一个重要特点是:

SubAgent 不会自动继承主对话历史。

这有两个好处:

1. 不污染主上下文
2. 节省 token

但也带来一个要求:

主 Agent 必须显式传递必要上下文。

如果用户要求中文回答,主 Agent 也应该在 context 里告诉 SubAgent:

用户使用中文,请用中文返回摘要。

否则 SubAgent 可能默认用英文总结,污染最终输出风格。

结果可信度

SubAgent 返回的是 summary,本质上是自报告。

所以主 Agent 不应该盲信这类说法:

文件已经写好
测试已经通过
接口已经发布成功
远程资源已经上传

对于有外部副作用的任务,主 Agent 应该要求 SubAgent 返回可验证证据:

绝对路径
URL
HTTP 状态码
文件内容摘要
测试命令和关键输出
对象 ID

然后主 Agent 自己再验证。

一个可靠流程是:

SubAgent:我写入了 /path/to/file
主 Agent:重新 read/stat 这个文件
主 Agent:确认内容存在后再告诉用户成功

代码入��

SubAgent 编排的核心代码在:

/Users/huapai/OpenSourceProject/hermes-agent/tools/delegate_tool.py

重点函数:

delegate_task()
  - 入口函数
  - 解析单任务或批量 tasks
  - 读取 delegation 配置
  - 控制并发、深度、角色
 
_build_child_agent()
  - 构造 child AIAgent
  - 注入子任务 system prompt
  - 设置工具集、模型、provider、session、回调
 
_run_single_child()
  - 真正运行 child.run_conversation()
  - 处理 timeout、interrupt、heartbeat、结果摘要

主 Agent 调用位置:

/Users/huapai/OpenSourceProject/hermes-agent/run_agent.py
 
_dispatch_delegate_task()
  - 把 parent_agent=self 传入 delegate_task
 
_execute_tool_calls_sequential()
  - 遇到 delegate_task 时启动 spinner 并执行

工具注册位置:

/Users/huapai/OpenSourceProject/hermes-agent/toolsets.py
  - delegation toolset
 
/Users/huapai/OpenSourceProject/hermes-agent/tools/delegate_tool.py
  - registry.register(name="delegate_task")

关键配置

Hermes 的 SubAgent 配置在 config.yamldelegation 下。

常见配置:

delegation:
  model: ""                    # 空 = 继承主 Agent 模型
  provider: ""                 # 空 = 继承主 Agent provider
  base_url: ""                 # 可指定 SubAgent 独立 API endpoint
  api_key: ""                  # base_url 模式下使用
  max_iterations: 50            # 每个 SubAgent 独立最大 loop 次数
  child_timeout_seconds: 600    # 单个 SubAgent 超时
  reasoning_effort: ""         # 空 = 继承主 Agent reasoning
  max_concurrent_children: 3    # 批量并发上限
  max_spawn_depth: 1            # 默认扁平,不允许嵌套
  orchestrator_enabled: true    # 是否允许 orchestrator 角色
  subagent_auto_approve: false  # 危险命令默认自动拒绝

可观测性和控制

TUI 可以观察和控制 SubAgent 树。

相关 RPC:

delegation.status
  - 查看活跃 SubAgent
  - 查看 paused 状态
  - 查看 max_spawn_depth 和 max_concurrent_children
 
delegation.pause
  - 暂停新的 SubAgent spawn
  - 已经运行中的 SubAgent 不会被暂停
 
subagent.interrupt
  - 按 subagent_id 中断某个正在运行的 SubAgent

相关代码:

/Users/huapai/OpenSourceProject/hermes-agent/tui_gateway/server.py
/Users/huapai/OpenSourceProject/hermes-agent/ui-tui/src/components/agentsOverlay.tsx

为什么不是越多 SubAgent 越好

SubAgent 有明显成本:

每个 SubAgent 都会自己调用模型
每个 SubAgent 都有自己的 token 消耗
每个 SubAgent 的结果都需要主 Agent 综合
SubAgent 越多,验证负担越重

所以好的编排不是“开很多”,而是:

每个 SubAgent 都有清楚、独立、可验证的产出。

适合 SubAgent 的任务模式

多线调查

A:查失败日志
B:查相关代码
C:查配置和历史提交

方案比较

A:研究方案 1
B:研究方案 2
C:研究方案 3

模块并行审查

A:看 frontend
B:看 backend
C:看 tests

大上下文隔离

A:读一大批文档并总结
主 Agent:只接收摘要,避免上下文爆炸

不适合 SubAgent 的任务模式

单个文件的小修改
简单命令执行
需要用户立即澄清的问题
强顺序依赖的实现链路
需要共享长上下文的细腻推理

这些场景主 Agent 自己做更稳。

Mermaid 流程图

flowchart TD
    A["用户任务"] --> B["主 Agent 判断是否可拆分"]
    B --> C{"有独立子问题?"}
    C -- "否" --> D["主 Agent 自己执行"]
    C -- "是" --> E["调用 delegate_task"]
    E --> F["构造 child AIAgent"]
    F --> G{"单任务还是批量?"}
    G -- "单任务" --> H["直接运行 child.run_conversation"]
    G -- "批量" --> I["ThreadPoolExecutor 并发运行多个 child"]
    H --> J["SubAgent 返回 summary"]
    I --> J
    J --> K["结果作为 tool message 回填主 Agent"]
    K --> L["主 Agent 综合、验证、最终回答"]

记忆口诀

主 Agent 拆任务,
SubAgent 查局部,
结果回到主 Agent,
主 Agent 做最终判断。

再压缩一句:

SubAgent 编排 = 主 Agent 的临时并行外包机制。

和长期多 Agent 系统的区别

Hermes 的 SubAgent 更像临时任务队列,不是长期组织架构。

不是:多个 Agent 长期在线协商
而是:主 Agent 临时派工,收报告,做总结

因此,设计重点不是“让 SubAgent 自由协作”,而是:

任务边界清楚
上下文传递完整
并发数量克制
结果可验证
主 Agent 负责最终综合

延伸阅读入口

优先看:

/Users/huapai/OpenSourceProject/hermes-agent/tools/delegate_tool.py
/Users/huapai/OpenSourceProject/hermes-agent/run_agent.py
/Users/huapai/OpenSourceProject/hermes-agent/toolsets.py
/Users/huapai/OpenSourceProject/hermes-agent/tui_gateway/server.py

相关笔记:

[[Hermes Agent Loop 技术知识与执行流程]]