子代理跑偏了?现在可以直接中途纠正它——delegate_task 实时编排指南

周一下午,你让 Hermes 派了三个子代理去并行处理一次代码重构:一个改前端、一个改后端、一个写测试。半小时后你瞄了一眼进展,发现负责后端那个家伙正在往错误的方向狂奔——它还在对着旧版 API 写代码,而新 API 早就换了签名。以前遇到这种情况,你只能把整批任务停掉,把需求再讲一遍,重头再来;运气不好,另外两个干得好好的子代理也跟着遭殃。现在不用了:从 8 月 13 日起,delegate_task 拥有了实时控制面,你可以像指挥乐队一样,查看正在运行的子代理、转向跑偏的那个、或者提前终止已经没救的——全程不打断其他成员。
子代理的“指挥台”:三个控制动作
在讲用法之前,先搞清楚一个前提:子代理(subagent)是 Hermes 派出去独立干活的“分身”,有自己独立的对话上下文和终端会话。以前 delegate_task 只有“派出”这一个动作:发出任务,然后等结果回来。PR #85232 在这个工具上直接加了三个控制动作,没有新增任何工具,模型还是调 delegate_task,只是多了 action、subagent_id、message 三个参数:
| 动作 | 参数 | 作用 |
|---|---|---|
action='list' |
无 | 列出当前对话派生的、还在运行的所有子代理 |
action='steer' |
subagent_id + message |
向某个运行中的子代理注入纠正指令,不停止它 |
action='stop' |
subagent_id |
提前中断某个子代理,部分结果仍会正常返回 |
省略或 action='spawn' |
goal/tasks 等 |
原来的派出模式,行为不变 |
这三个控制动作是同步执行的——它们不会进入后台派发队列,调用后立刻返回结果,所以你在对话里能看到即时的“当前有哪些子代理”清单。
怎么用:一次完整的“发现 → 转向 → 终止”演练
假设你刚派出了三个子代理,现在想看看它们的运行状态:
{
"tool": "delegate_task",
"action": "list"
}
返回的清单里,每个子代理都带 subagent_id、parent_id、depth(嵌套深度)、goal(任务目标)、model、started_at、accepting_steer(是否接受转向)等字段——通过 goal 你一眼就能认出哪个是“正在对着旧 API 写代码”的那个。
发现跑偏的那个后,给它发一条纠正指令:
{
"tool": "delegate_task",
"action": "steer",
"subagent_id": "sa-7f3k9",
"message": "注意:后端 API 签名已经变了,请改用新的 /v2/users 端点,字段名是 userId 而不是 id。"
}
steer 的机制很优雅:它把这段文字排进目标子代理的待处理队列,等子代理执行到下一个工具边界时再注入——也就是说,它不会粗暴打断子代理正在进行的操作,而是让它在合适的位置“看到”你的纠正。如果子代理在它完成前都没能消费这条指令(比如任务刚好结束了),这条指令也不会凭空消失,它会以 missed_steer 字段的形式出现在该子代理的完成记录里,让你知道“转向没送达”。
如果那个子代理已经彻底没救了,直接终止它:
{
"tool": "delegate_task",
"action": "stop",
"subagent_id": "sa-7f3k9"
}
stop 走的是中断机制:子代理会在下一个迭代边界停下来,它已经完成的部分结果会作为一条正常的完成消息返回——不会白干,也不会留下一堆悬空状态。你拿到部分结果后,可以重新派一个子代理接手剩下的部分。
边界与安全:你能控制的只有“你自己的”
这套控制面设计上有几个值得注意的边界,理解了它们你才不会踩坑:
- 所有权链:一个对话只能控制自己派生的子代理树。Hermes 通过
_delegate_parent_ref弱引用链做身份校验——你没法从对话 A 去 steer 对话 B 派出去的子代理。这也是“多开几个 Hermes 会话互不干扰”的保证。 - 控制动作不吃配额:每轮对话对子代理的“派出数量”是有上限的,但
list/steer/stop不消耗这个配额——这正是设计意图:当配额用尽、你最需要“紧急叫停一个跑偏的子代理”的时候,stop依然可用。 - 子代理不能递归派生子代理:默认的
role='leaf'子代理拿不到delegate_task工具;只有显式指定role='orchestrator'的子代理才保留派发能力(受delegation.max_spawn_depth深度限制)。所以“控制”永远发生在顶层对话这一侧。 - 转向送达时机:
steer是“排队注入”而非“即时打断”。如果子代理卡在一个超长工具调用里,纠正指令要等它到下一个工具边界才会生效——对大多数场景这完全够用,但对“必须立刻停手”的场景,stop才是正确的工具。
什么时候值得用
实时编排最有价值的场景,是把“人工巡检”从任务结束后提前到任务进行中:
- 长任务早期纠偏:重构成千上万行代码时,跑 10 分钟才发现方向错了,代价极高。中途
list+steer一次,可能省下几个小时。 - 多子代理并行时的定点处理:三个子代理里只有一个跑偏,
steer/stop它一个,另外两个继续跑,而不是整批重来。 - 和审批/看板流程配合:如果你用看板管理子代理任务(可以参考我们之前写的 kanban 评审生命周期 一文),实时控制面正好补齐了“任务进行中如何干预”这一环。
之前介绍过用 delegate_task 做代码评审仲裁(见 merge-reconciler:中立的代码合并仲裁者),那篇文章展示的是“派出后等结果”的用法;今天这个控制面让 delegate_task 从“发射后不管”进化成了“边跑边指挥”。子代理体系是 v0.20.0 以来 Hermes 多智能体工作流的核心(发版说明见 v0.20.0 Herald 发布笔记),现在它终于有了实时方向盘。
一句话总结:list 让你看得见,steer 让你说得上话,stop 让你刹得住车——三个动作都发生在不打断其他子代理的前提下。下次再遇到“子代理跑偏”,不用掀桌子重来了。