Hermes Agent
Hermes separates provider exhaustion from Kanban protocol failure
A Hermes report says Kanban workers can exit zero after provider rate limits or timeouts, causing the dispatcher to label an upstream failure as protocol violation. Two task-state records also show initially blocked work being promoted and spawned.
NousResearch/hermes-agent issue #91177 is the inspected primary source: “Kanban worker exits rc=0 after provider rate-limit/timeout — dispatcher misclassifies as protocol violation and auto-blocks.” The related records below were inspected as supporting context rather than independent confirmation.
The facts
- NousResearch/hermes-agent issue #91177 was created 2026-08-21T00:04:43Z and was open at inspection; its title is “Kanban worker exits rc=0 after provider rate-limit/timeout — dispatcher misclassifies as protocol violation and auto-blocks.” - NousResearch/hermes-agent PR #91180 was created 2026-08-21T00:14:12Z and was open at inspection; its title is “fix(kanban): make --initial-status blocked sticky from birth.” - NousResearch/hermes-agent issue #91178 was created 2026-08-21T00:05:14Z and was closed at inspection; its title is “kanban task created with --initial-status blocked is promoted and spawned.” - The repository reported 233547 stars, 33991 open issues, default branch main, and last push 2026-08-21T00:23:14Z. - The latest tagged-release baseline checked was v2026.8.18 published 2026-08-18T07:26:46Z.
What changed
NousResearch/hermes-agent issue #91177 reports: Summary When a kanban worker's model provider fails mid-run (rate-limit 429 / timeout 400) and retry attempts exhaust, the hermes chat -q worker process **exits with code 0**. The dispatcher (_classify_worker_exit in hermes_cli/kanban_db.py) reads *clean exit + task still running* as a **protocol violation** ("worker exited cleanly without calling kanban_complete/kanban_block") and auto-blocks the task after failure_limit consecutive occurrences. Infrastructure failures are thereby misclassified as worker misbehavior, and healthy work queues seize up during provider outages. Expected behavior A worker whose agent loop terminates due to an unrecoverable provider error should exit **non-zero** — ideally with the existing KANBAN_RATE_LIMIT_EXIT_CODE — so the dispatcher classifies the run as rate_limited (task released back to ready, no failure counted, per the comment at kanban_db.py ~L6900: "a long quota window can't trip the breaker"). Actual behavior The chat runner ends the turn normally after provider retries are exhausted (the API error is absorbed into the session as a final assistant message / session end) and the process exits 0. The dispatcher records: Two consecutive occurrences auto-block the task, even though the worker did nothing wrong and the task may be partially or fully completed in the workspace. Reproduction 1. Configure a worker profile on a rate-limited provider (e.g. OpenRouter free tier, 1,000 req/day account-wide). 2. Dispatch a long-running kanban task that exceeds the provider's quota
NousResearch/hermes-agent PR #91180 reports: What does this PR do? Makes hermes kanban create --initial-status blocked actually stick. The sticky-block gate (_has_sticky_block, from #28712) keys on the latest "blocked"/"unblocked" event row, but a task born blocked only ever wrote the status column — no event row. On the next dispatch tick, recompute_ready therefore treated it as event-less and auto-promoted it through promoted → claimed → spawned, starting the assignee ~21s after creation and bypassing exactly the setup/credential/deployment activation gate the caller had expressed (#91178). An explicit post-create hermes kanban block did persist, confirming the initial-block path was the only one missing the event. The fix emits the block transition atomically inside the create transaction, with the same payload shape block_task writes (reason/kind/recurrences/source_status, plus initial: True to mark the origin), so an initial-blocked task follows the same lifecycle as a post-create block: sticky until an explicit unblock, invisible to the dispatcher's auto-recovery. Related Issue Fixes #91178 Type of Change [x] Bug fix (non-breaking change that fixes an issue) Changes Made hermes_cli/kanban_db.py — create_task's post-create hook now appends a "blocked" event row when initial_status == "blocked", inside the same write transaction as the create, with the #91178 rationale documented inline tests/hermes_cli/test_kanban_blocked_sticky.py — three regressions beside the existing #28712 sticky tests: an initial-blocked task has a durable sticky event and survives five recompute_ready ticks un-promoted; an explicit
NousResearch/hermes-agent issue #91178 reports: Bug description A task created with hermes kanban create --initial-status blocked can be promoted and dispatched by the gateway on the next tick instead of remaining blocked. This defeats the documented activation-gate use case and can start an assignee before prerequisites are installed. Reproduction 1. Run a gateway with embedded Kanban dispatch enabled. 2. Create a named-board task with a real assignee and --initial-status blocked. 3. Do not unblock or promote it. 4. Wait for the next dispatcher tick. Observed result The create receipt reported status: blocked, but the event stream then recorded: created with status: blocked promoted claimed spawned The worker process started approximately 21 seconds after creation. An explicit later hermes kanban block did persist and close the run. The initial blocked creation had no durable block transition/reason in the event stream before promotion. Expected result --initial-status blocked must remain blocked until an explicit unblock; the dispatcher must never auto-promote or spawn it. If an initial block requires a reason or block kind, the CLI should require and persist it atomically. Safety impact This can bypass setup, human, credential, or deployment gates expressed through the documented initial blocked state. Workaround Create parked work in triage with auto-decomposition disabled, or immediately issue an explicit kanban block with a reason before any dispatcher tick.
Why it matters
Schedulers need to preserve why work did not run. Conflating provider exhaustion, worker protocol failure and operator-blocked state makes automated recovery both noisy and unsafe. The operator test is whether the system remains bounded and its receipts still describe the action after failure, retry or restart.
Current
The primary record was open when captured on 2026-08-21. The tagged-release baseline was v2026.8.18 published 2026-08-18T07:26:46Z. Repository metadata, full source bodies, current pull requests and issues, releases, Google News, Hacker News, Lobsters, Metamesh and the rendered ClawCharts row were inspected. ClawCharts selected the subject; it did not prove the claim.
Evidence
The primary URL is https://github.com/NousResearch/hermes-agent/issues/91177. Supporting records are https://github.com/NousResearch/hermes-agent/pull/91180 and https://github.com/NousResearch/hermes-agent/issues/91178. Source bodies, timestamps and states are preserved in the daily evidence bundle. Test counts and reproductions remain attributed to their authors unless identified as independently rerun.
Source boundary
Open work is described as open, closed work as closed, and operator reports as reports. A pull request is evidence of proposed or reviewed direction, not proof of a shipped release. Search residue, package mirrors and historically published source spines were excluded.
Operator take
Carry provider failure class and initial blocked state through the worker receipt, and forbid promotion until the same durable state transition explicitly clears the gate. Preserve a before-state receipt, make the smallest reversible change, and verify the original failure independently.
Caveat
Public project records are mutable. Status, scope and evidence can change after publication. This brief records the inspected state and does not authorize changes to a reader’s deployment.
Source inspected; source state, environment and release boundary remain explicit.