One batch, many brains: delegate_task now picks a model or a profile per task


You hand Hermes a batch: eight subtasks. Six are lookups — read a doc, grep a log, reformat a table. Two are the hard ones — untangle a concurrency bug, redesign a module boundary. You get one model for all of them. Pick an expensive one and the six trivial tasks burn money; pick a cheap one and the two hard tasks come back with plausible nonsense. That forced choice stops being mandatory with PR #142563, merged on October 22, 2026.

The old rule: one delegation.model for every child

The child model was pinned globally in config.yaml — delegation.model, delegation.provider, delegation.base_url. Under the default strategy delegate_task has no per-task model parameter, so every subagent in a batch runs on the same route. The docs said it plainly: for a quality-sensitive subtask you either leave delegation.model unset for that session, or hand the work to the kanban board, which does support a per-task model override.

So everyone made the same compromise: pin a mid-tier model and live with it.

The new rule: delegation.backend decides how work is routed

The change in one sentence: delegation became a pluggable provider category, the same shape as TTS, image generation and terminal backends. delegation.backend selects the strategy. default means exactly what you had — unset or default leaves the delegate_task schema and every hermes-cli tool definition byte-identical to before.

The two other strategies come from the official advanced-delegation plugin:

  • model_map — you list titled options (fast, deep, …), each with a one-line description plus a provider and model, and the model picks one per task;
  • profile_routes — each task runs as one of your Hermes profiles, with that profile’s model, credentials, skills and persona.
delegation:
  backend: model_map
  backends:
    model_map:
      options:
        - name: fast
          description: Cheap and quick; lookups, summaries, simple edits.
          provider: openrouter
          model: google/gemini-3-flash-preview
        - name: deep
          description: Slow and careful; hard debugging and design work.
          provider: anthropic
          model: claude-opus-5
          reasoning_effort: high
          service_tier: fast      # optional; refused at spawn if this route has no fast tier
      default: fast                # optional: option for tasks that set none
    profile_routes:                # read when backend: profile_routes
      profiles:
        - name: coder
          description: Writes and refactors code; runs tests.

The descriptions are not decoration. The model only ever sees the names and descriptions you configured — never the raw provider, model or key fields. Write “Cheap and quick; lookups, summaries” and you are teaching it when to save money; write “Slow and careful; hard debugging and design work” and you are teaching it when to spend.

Core keeps the whole lifecycle either way: spawn, isolation, leaf/orchestrator roles, depth, concurrency, background units, stop fan-out, results, output_schema, progress. Only the routing decision moved.

Every routed result now carries a route receipt

A task that went through a backend reports where it actually ran: the backend, the option or profile name, and the provider, model, reasoning effort and speed tier the child used. If a fallback provider took over, fallback_activated is true.

That matters more than it sounds. Before, you inferred the child’s model from “I set delegation.model”. Now it reports back — so when a batch suddenly gets expensive, you read the receipt instead of guessing.

Failures are loud, never a silent switch

This is where the PR spends most of its effort:

  • If the selected backend is missing (plugin not installed or disabled) or reports it cannot run, delegate_task returns a tool error naming the backend and the fix (install/enable the plugin, /delegation default, or hermes config set delegation.backend default). No subagent starts, and the children never quietly run on the default route.
  • Inside a batch, a task its backend cannot route — an unknown option, a parameter the selected backend does not take, a profile that does not exist, a service_tier the route does not offer, an unknown reasoning_effort, missing credentials — is refused alone. Its result entry has status: "error", the reason, and route.refused: true; the siblings still run.
  • The call only becomes a tool error when every task was refused.
  • A model route without its own fallback_providers inherits delegation.fallback_providers; fallback_providers: [] on the route disables fallback for it. A profile route uses that profile’s own fallback chain.

One boundary worth knowing: while model_map or profile_routes is active, delegation.model and delegation.provider are inactive — the routes decide. Do not configure options and then wonder why the old pin stopped mattering.

Switching, and switching back

Both strategies, the /delegation slash command and hermes delegation config (create, edit and delete model routes, pick profiles) ship in the official plugin:

hermes plugins search advanced-delegation
hermes plugins install advanced-delegation
hermes plugins enable advanced-delegation

Then switching does not require editing files:

/delegation model_map               # this session only
/delegation profile_routes --global # writes delegation.backend to config.yaml
/delegation default                 # back to the default strategy

There is a subtlety the docs call out explicitly: a session switch changes routing, not the tool schema. The per-task parameters (option, profile) are part of the cached prompt and follow config.yaml, so they change at the next session. Until then the model may still send the previous backend’s parameter — an option: fast after switching to profile_routes. Such a task is refused on its own, with the fix in the message: /delegation <backend> --global then /new (because /new starts on the saved backend), or /delegation <saved backend> to go back. It never runs on the new backend’s default route just to keep going.

Without the plugin, hermes config set delegation.backend default restores the old behaviour.

Which strategy fits

  • model_map — one credential set, money split by difficulty. Light tasks go to a cheap model, hard ones to a strong model. It fits batches whose subtasks differ wildly in difficulty: fix ten issues in one run, run twenty research threads.
  • profile_routes — the child changes identity. Each profile carries its own model, credential pool, SOUL.md and terminal policy, which fits “these subagents should run under different permissions”, for example keeping code work inside a restricted terminal policy.

One warning comes straight from the docs and deserves quoting: listing a profile in delegation.backends.profile_routes lets this profile’s subagents use that profile’s credentials, credential pool, SOUL.md and terminal policy. Only list profiles whose keys and terminal access you are happy for this agent to use.

Release status

PR #142563 merged to main on October 22, 2026. The follow-up #142564 moves the default strategy itself into a bundled plugin, and #143126 adds the desktop delegation settings (mode picker, model-route editor, profile routes). The most recent release is v0.22.4 from October 21, so all of this is on main only today and reaches the stable channel with the next release. If you switch to it now, note the channel: patch releases do not carry it yet.

If you have not used live subagent control (list/steer/stop) yet, start with the subagent orchestration guide. For the full delegation section, the hermes config reference is faster than reading source. The other half of per-model routing lives in the model_overrides guide, and plugin installation is covered in the plugin catalog guide.