§15一个 agent 指挥一群 agent
One Agent Commanding a Swarm of Agents
前面几节里 skill 一直是一份知识文档,告诉 agent「这事该怎么做」。这一节里它变成了另一种东西:
一根指挥棒。Hermes 把 Claude Code、Codex、OpenHands、OpenCode、Grok 全封装成可调用的skill,自己退到后面当总指挥。
一个画面:它不写代码,它派活
设想你让 Hermes 实现一个功能。它当然可以自己上手,调 terminal、写文件、跑测试。但从 v0.16.0 起它多了一个选择:把这单活外包出去。
在skills/autonomous-ai-agents/这个目录下,6月时源码里躺着四个内置 skill,到v0.22.2变成五个,多了一个computer-use (操控桌面应用)。§04的启动页右栏「autonomous-ai-agents: claude-code, codex, +3 more」指的就是它们。它们不是教 Hermes「怎么写 Python」,而是教它怎么调用另一个 coding agent 帮自己写。Claude Code 是一个,Codex 是一个,OpenCode 是一个,连 Hermes 自己也有一个(用来给本体贡献代码)。
| Skill | 版本 | 它指挥谁去干活 |
|---|---|---|
| claude-code | 2.2.1 | 委派编码给 Claude Code CLI(做 feature / 提 PR) |
| codex | 1.0.1 | 委派编码给 OpenAI Codex CLI |
| opencode | 1.2.0 | 委派编码给 OpenCode CLI(可挂多个 provider) |
| hermes-agent | 3.2.0 | 配置、扩展、给 Hermes 本体贡献代码 |
表里是v0.22.2的版本号。optional 目录里还有更多:OpenHands、Grok 的 Build CLI、antigravity-cli、blackbox,后来又加了 dynamic-workflow 和一个专门调解合并冲突的 agent-merge-conflict-arbiter。装上之后,Hermes 手里就握着一整排可以差遣的 coding agent。
你→ Hermes(总指挥)
挑一个 skill Claude Code / Codex / OpenHands…
代码 / PR 交回来这个结构有点反直觉。我们一直把 Claude Code、Codex 当成「终端」,那个你直接对它说话的 agent。可在Hermes 眼里,它们是「下属」。谁在最前面收下你的需求,谁就是指挥官;其他 agent 只是它工具箱里的一把扳手。
为什么要这么干?因为不同的 agent 各有各的脾气。Claude-native 的活交给 claude-code,OpenAI-native 的活交给 codex,需要换模型的场合再换别的。Hermes 不必把每家模型的特长都学一遍,它只要知道「这单该派给谁」就够了。指挥官的本事,是调度,不是亲手做。
拆一个范本:OpenHands skill 长什么样
这群编排 skill 里,OpenHands 那份写得最讲究,我想把它拎出来当标本。如果你想知道「一个好 skill 到底长什么样」,照着这份抄就对了。
先说它干的事:OpenHands 是 model-agnostic 的,背后能接任何 LiteLLM 支持的 provider,OpenAI、Anthropic、OpenRouter、DeepSeek、Ollama、vLLM 都行。所以这个 skill 的定位很清楚:要 Claude 原生就走 claude-code,要 OpenAI 原生就走 codex,要换着模型玩,才轮到 OpenHands。skill 开头就把这条选择题替你做了。这是第一个细节,好 skill 会告诉你它「什么时候不该用」。
往下看,它的工程化程度才是真正可怕的地方。我把它的几个关键设计列出来。
| 设计 | 具体做法 | 为什么是范本 |
|---|---|---|
| 真实 flag | 给出可用参数表,并标注「verified against openhands --help, CLI | 不是凭记忆瞎写,是对着帮 |
| 表 | 助文档逐条核对过的 | 1.16.0」 |
| 负向清单 | 明确写出哪些 flag 不存在(没有--model / --max-iterations / - | 主动告诉调用者「别试这 |
| 些,试了也是错」,省一整 | -workspace / --sandbox) | |
| 轮试错 | ||
| 一整段 | LiteLLM 的噪声 warning、banner 刷屏、model slug 是 LiteLLM 的不 | 把踩过的坑全写进去,后来 |
| Pitfalls | 是 provider 的、pip install openhands-ai装的是错包(那是 | 者直接绕过 |
| legacy V0) | ||
| 平台门控 | [linux, macos]门控,OpenHands 上游在 Windows 要 WSL | 不兼容的系统上这 skill 直 |
| 接隐身,不污染索引 |
调用方式也很克制:通过terminal工具 headless 调一行openhands --headless --json --override-with-envs --exit-without-confirmation 。没有花哨的封装,就是把命令行调对、把坑标清楚。
好 skill 的判据:不在于它写了多少「该做什么」,而在于它写了多少「别做什么」。负向清单、Pitfalls、「什么时候不用我」,这三样才是把一份文档从「看着像对的」变成「跑起来真的对」的分水岭。一个只列正确步骤的skill,等于一份没经过实战的说明书。
这里还藏着一个本节的关键转变。skill 不再只是「写给 agent 看的知识」,它也可以是对一个外部 CLI 的封装。
OpenHands skill 本质上是一层薄薄的胶水:把 agent 的意图,翻译成另一个 agent 听得懂的命令行。skill 的边界,被悄悄推宽了。
会进化的 skill:darwinian-evolver
编排别的 agent 是一种玩法,让 skill 帮你优化东西是另一种。optional 的 research 目录里有个darwinian-evolver ,薄封装了 Imbue 开源的 darwinian_evolver,一个 LLM 驱动的进化搜索循环。
它的用法是:你给它一个 fitness 函数(一个打分器),它就用进化的方式去优化某个 artifact,可以是一段prompt、一条 regex、一句 SQL、一小段代码。生成一批变体,打分,留下高分的,再变异,一轮一轮爬坡。
要分清它和 Hermes 自带的自进化不是一回事。内置自进化改的是 skill 库本身;darwinian-evolver 改的是你手里任何「有打分器的东西」。一个对内,一个对外。说起来,这套 hill-climbing 加独立评判加进化树的思路,和我自己做的 darwin skill 是同源的:给定一个客观分数,让机器自己一代代往上爬,比人手调要稳。
还有个细节我挺欣赏:它对上游用的是干净的 license 隔离。Imbue 那个库是 AGPL-3.0,skill 只通过subprocess 调它的命令行,刻意不去 import 上游的类,这样就只是「调用」而非「合并」,把传染性 license的边界划得清清楚楚。一个 skill 该怎么和一个许可证不友好的外部依赖打交道,这就是范例。
承上启下
把这一节往回看一步。前面我们讲 skill 是怎么被造出来、被改进、被开放标准白嫖来的。到这里,skill 显出了它的第二张脸:它不光是知识,也是 agent 之间互相调度的接口。
当一个 skill 可以是「调用另一个 agent」的封装,一个有意思的问题就浮上来了——如果 Hermes 能指挥Claude Code,那它能不能同时指挥一群 agent,让它们分工协作、并行干活?指挥棒握在手里之后,下一步自然是编队。
这正是后面 Part 6 要展开的:从delegate_task派一个隔离上下文的子 agent,到 Kanban 看板上一群 agent排队认领任务。skill 把「调度」这件事变得可调用,多 agent 编排把它变得可规模化。这一节是那一章的引子。