Your Subagent Is Going the Wrong Way? Now You Can Steer It Mid-Run

Monday afternoon, you have Hermes spawn three subagents to parallelize a refactor: one for the frontend, one for the backend, one for the tests. Half an hour in, you glance at the progress and realize the backend one is charging in the wrong direction — it’s still writing against the old API while the new one changed every signature. Before, your only option was to kill the entire batch, re-explain the requirements, and start over; if you were unlucky, the two subagents that were doing fine got caught in the blast too. Not anymore. Since August 13, delegate_task ships a real-time control plane — you can list the running subagents, steer the one that drifted, or stop one that’s beyond saving, all without interrupting the rest of the team.
The conductor’s console: three control actions
First, a quick premise: a subagent is a separate “clone” Hermes dispatches to work independently, with its own isolated conversation context and terminal session. Previously delegate_task had exactly one verb — spawn: fire a task, wait for the summary. PR #85232 adds three control actions directly to the same tool, without introducing any new tool. The model still calls delegate_task; it just gets three new parameters: action, subagent_id, and message.
| Action | Parameters | Effect |
|---|---|---|
action='list' |
none | List the still-running subagents spawned by this conversation |
action='steer' |
subagent_id + message |
Queue a course-correction into a running subagent without stopping it |
action='stop' |
subagent_id |
Interrupt a subagent early; its partial result still comes back normally |
omitted or action='spawn' |
goal/tasks etc. |
The original spawn mode — behavior unchanged |
The three control actions run synchronously — they never enter the background dispatch queue and return immediately, so you get an instant “here’s what’s running” answer right in the conversation.
How to use it: a full discover → steer → stop drill
Say you just dispatched three subagents and want to check on them:
{
"tool": "delegate_task",
"action": "list"
}
Each entry in the returned list carries subagent_id, parent_id, depth, goal, model, started_at, and accepting_steer — the goal field lets you spot at a glance which one is “still writing against the old API.”
Once you’ve found the stray one, inject a correction:
{
"tool": "delegate_task",
"action": "steer",
"subagent_id": "sa-7f3k9",
"message": "Heads up: the backend API signature changed. Use the new /v2/users endpoint — the field is userId, not id."
}
steer works by queuing the text into the target subagent’s pending input, which gets delivered at the child’s next tool boundary — it doesn’t yank the subagent out of whatever it’s doing; the correction lands at a safe point. And if the subagent finishes before it ever consumes the steer, the instruction doesn’t vanish into thin air: it surfaces as a missed_steer field in that subagent’s completion entry, so you know the course-correction never landed.
If that subagent is truly beyond saving, terminate it:
{
"tool": "delegate_task",
"action": "stop",
"subagent_id": "sa-7f3k9"
}
stop rides the interrupt machinery: the subagent halts at its next iteration boundary, and whatever partial result it produced re-enters as a normal completion message — no wasted work, no dangling state. You can take the partial output and dispatch a fresh subagent to finish the rest.
Boundaries and safety: you can only control your own tree
The control plane comes with a few deliberately designed boundaries — know them and you won’t get surprised:
- Ownership chain: a conversation can only control subagents it spawned itself. Hermes enforces this via a
_delegate_parent_refweakref chain with identity checks — you can’tsteeranother conversation’s children from yours. That’s the same guarantee that keeps multiple Hermes sessions from trampling each other. - Control actions don’t consume the spawn budget: there’s a per-turn cap on how many subagents you can spawn, but
list/steer/stopare exempt — by design. When the cap is hit is exactly when “urgently stop the runaway one” matters most, sostopstays usable. - Subagents can’t spawn subagents by default: a
role='leaf'child never gets thedelegate_tasktool; only an explicitrole='orchestrator'keeps the dispatch toolset (bounded bydelegation.max_spawn_depth). Control always lives on the top-level conversation side. - Steer delivery timing:
steeris “queued injection,” not “instant interruption.” If the subagent is stuck inside one very long tool call, the correction only lands at the next tool boundary — fine for most cases, but for “must stop right now” situationsstopis the right tool.
When live orchestration pays off
The real value is moving your “human inspection” from after-the-fact to mid-flight:
- Early course-correction on long tasks: when rewriting tens of thousands of lines, discovering a wrong direction after 10 minutes is expensive. One
list+steerin the middle can save hours. - Surgical handling in parallel batches: of three subagents, only one drifted —
steerorstopjust that one while the other two keep running, instead of restarting the whole batch. - Pairing with kanban/review flows: if you manage subagent tasks on a board (see our kanban review lifecycle guide), the control plane fills the “how do I intervene mid-task” gap that the board alone couldn’t.
We’ve covered delegate_task before — the merge-reconciler, a neutral code-merge arbiter showed the “dispatch and wait for results” shape. This control surface evolves delegate_task from fire-and-forget to conduct-while-running. Subagents are the core of Hermes’ multi-agent workflows since v0.20.0 (see the v0.20.0 Herald release notes), and now they finally have a live steering wheel.
One line to remember: list lets you see, steer lets you speak, stop lets you brake — all three without interrupting the subagents that are doing fine. Next time a subagent drifts, you don’t have to flip the table and start over.