Escalation Governor
A weak model does not know when it is out of its depth. Left alone, an
agent on a cheap model retries the same failing approach until the session
dies — Hermes' own advanced-delegation write-up recorded 0 delegations in
2,900 calls over ~89 hours, because the decision to escalate was left to
the model that was already failing.
Escalation Governor takes that decision away from the model. It watches
deterministic signals only — no LLM judging, no prompt tricks — and when
a session is measurably stuck, it injects a structured escalation packet
into the model's context and directs it to hand the remaining work to a
stronger model.
Signals
| Signal | Default threshold | Source hook |
| --- | --- | --- |
| Consecutive tool errors | 3 | post_tool_call (status != ok) |
| Same tool call repeated (same tool + same args) | 3 | post_tool_call |
| Provider API errors since last successful tool result | 3 | api_request_error |
| Model calls since last successful tool result | 12 | post_api_request |
Any successful tool result resets the error counters — the governor only
fires on sustained failure, never on a single unlucky call.
What happens on a trip
The governor builds a packet — the session goal, the approaches already
tried and how each one failed, and the trip reason — and injects it once per
turn (via transform_tool_result mid-turn, and pre_llm_call at the next
turn's start). The packet directs the agent to:
- call
delegate_taskwith the packet as the brief, so a stronger model
takes over the remaining work without repeating the failed approaches, or - if delegation is unavailable, stop and present the packet to the user as
the blocker report.
A successful tool call after injection clears the trip (the session
recovered on its own); a subagent_start also clears it (the escalation
was acted on).
At on_session_end, a one-line JSON report is appended to
~/.hermes/escalation-governor-reports.jsonl with turn/API/tool counts,
token usage, escalation count, and whether delegation followed — so you can
measure what the governor saved. /governor shows live session status;
/governor report prints the last session report.
How this differs from what exists
- The bundled delegation plugin decides which model a subagent uses.
The Governor decides when escalation must happen at all. They compose:
the Governor trips, the delegation plugin routes. - A community blog hook ("escalade") popularised failure-count escalation.
The Governor generalises it to four independent signal families, adds
no-progress detection (calls without a successful tool result), packet
injection at two points in the turn lifecycle, recovery semantics, and a
persistent per-session savings report.
Configuration
Defaults work out of the box. Override with a JSON file at
~/.hermes/escalation-governor.json (keys: consecutive_error_threshold,
repeat_call_threshold, api_error_threshold, no_progress_api_calls,
max_packet_actions) or environment variables GOVERNOR_CONSECUTIVE_ERRORS,
GOVERNOR_REPEAT_CALLS, GOVERNOR_API_ERRORS, GOVERNOR_NO_PROGRESS_CALLS.
GOVERNOR_DISABLE=1 is a kill switch.
Safety
- Fail-open: every callback swallows its own exceptions; a Governor bug
can never break the agent loop. - Non-blocking: the Governor never blocks or modifies a tool call. It
only adds context and writes its own report file. - No credentials, no network: it reads no secrets and calls nothing.
- The packet contains only the session's own goal text (truncated) and
metadata-style summaries of its own tool calls (tool name + target hint +
outcome) — the same visibility the agent already has.
Install
Drop this directory into ~/.hermes/plugins/escalation-governor/, enable
it (hermes plugins enable escalation-governor), and restart Hermes.
Tests
python3 tests/test_governor.py — plain-python tests of the signal engine
(trip conditions, once-per-turn injection, progress reset, recovery,
delegation consumption, usage accounting).
README from the reviewed commit 50fcf38; it updates when the author re-pins.

jusst