The Brain stopped on 429. It is not rate limited. It is misconfigured.
The Brain stopped on 429. It is not rate limited. It is misconfigured.
Young, 2026-10-11: "I saw Brain Unit stopped due to 429 on Hermes, now how do we fix this issue and switch to different model when it happen and resume tasks."
Measured, not argued. The 429 is real, and it is the wrong endpoint's 429.
1. What the Brain is actually configured to use
$ grep -m1 '^ default: "' /home/lab/.hermes/profiles/*/config.yaml
min default: "longcat-2.5-preview-free"
mira default: "space-bunny-free" ← provider opencode-go
sol default: "space-bunny-free" ← provider opencode-go
All three point at base_url: https://opencode.ai/zen/go/v1 — the GO
endpoint.
space-bunny-free does not exist on GO. Live probe, this morning:
go/space-bunny-free → HTTP 401 {"ModelError",
"message":"Model space-bunny-free is not supported"}
MISS lab-go/space-bunny-free | NOT served by go (45 models listed)
That is the Stage 1.8 defect, live in V3's own registry of models, and it is running in production. Two of three Brains are pointed at a model their endpoint does not serve. Min flagged it two days ago as a known-bad fixture; nobody knew it was the Brain's live default.
2. Why it reads as "429" and not "wrong model"
Because the fleet's own health record already answers it. V2's
state/model_health.json, decoded:
| Model | ok | fail | reason |
|---|---|---|---|
opencode-go/longcat-2.5-preview-free | 769 | 0 | — |
opencode-go/space-bunny | 1 | 0 | — |
opencode-zen/longcat-2.5-preview-free | 0 | 2 | provider.quota "Rate limit exceeded." 429 |
opencode/mimo-v2.6-flash-free | 2 | 23 | provider.quota: Rate limit exceeded |
opencode/big-pickle | 0 | 11 | provider.quota: Rate limit exceeded |
opencode/space-bunny-free | 30 | 0 | — |
Read the third row and the last row together. The same model id on the
ZEN endpoint rate-limited with 0 successes. On the opencode endpoint it did
30 successful calls. And longcat on GO did 769 with zero failures.
So the 429s the fleet is hitting are on opencode-zen and opencode — not on
GO. Two of three Brains are asking GO for a model it will not serve, the call
fails, and the failure is being read as the generic "429 rate limit" everybody
knows about.
The free tier is not exhausted. 769 successes proves it. Brain is asking the wrong door.
3. The fix — one line, per Brain
mira and sol → longcat-2.5-preview-free, which is:
- served by GO (probed:
OK opencode-go/longcat-2.5-preview-free) - 769 successes, 0 failures in V2's own record — the most-proven free model in the fleet's history
- free, so it draws on the $10 package, not the $40 ZEN float
min is already on it and needs nothing.
# mira/config.yaml and sol/config.yaml, line 63
- default: "space-bunny-free"
+ default: "longcat-2.5-preview-free"
I have NOT applied this. ~/.hermes/profiles/ is the Brain's own config and
this is a live-process change — it is Sol's /home/lab/.hermes territory, and
it needs a restart to take effect. It is recorded here with the evidence so
the change is a yes/no, not an investigation.
4. And the switch, so this cannot recur
The 429 switch you asked for is built and proven — core/config/router.py
with core/config/ladder.py, committed b022afc. With the real catalogue (2
free on GO, 12 free on ZEN):
every free model rate-limited except the last one on ZEN
→ 12 attempts · 0 paid calls · success on space-bunny-free
It classifies by OUTPUT, not exit code, because V2's defect was a model
declining politely, exiting 0, and the run recording as success. rc == 0 is
not success.
Two defects I found in my own module this week, both the V2 pattern:escalate() reached only 1 of 14 free models; and the rung order put paid GO
ahead of free ZEN, calling qwen3.8-flash on attempt 3 while a free model sat
untried until 13. Cost rung beats instrument rung.
5. 🔴 But the switch has no caller, so it does not run
$ grep -rn "route(" --include=*.py . | grep -v tests/
(no results — defined, tested, called from nowhere in production)
This is registered as P10. The switch is correct and inert until the fleet's
invocation layer calls router.route(rungs=..., invoke=...) instead of invoking
a model directly. Owner: Sol, operation/runtime/.
6. What stops a stall from becoming a stop
Today's answer to "resume tasks" is the task model's own rule — Stage 3.3,
already committed and tested: a task that stops progressing escalates instead of
waiting, and does so without a human deciding. core/tasks/stuck.py.
So the sequence Young asked for is: rate limit → switch model (built, needs wiring) → if the task still cannot progress → escalate (built and tested) → the queue does not stall.
7. Honest limits
- I could not authenticate a live GO chat call from this shell. The
OPENROUTER_API_KEYinsolos2/.envreturns401 Invalid API keyagainst GO. The diagnosis above stands on the catalogue probe (45 models listed, GO does not listspace-bunny-free) and V2's own 769/0 record — not on a successful GO completion. - "Model not supported" was returned before any auth check, so it is a stronger signal than the 401: the endpoint rejected the model, not the key.
- I have not restarted anything. The fix is one line per Brain and needs Sol or Young to apply and restart.
One line changes Brain from stalled to serving, and the evidence for it is 769 successes in our own health record.
Finding — the A2A dependency gap
Found while acting on Young's "only report if error" request: I read the cron list to make the backup quiet, and the restore-proof job had been failing for a day. Chasing that failure surfaced a second, more important one.
V3 — cost and provider policy
Read first: young-corrections-2026-10-10.md §1 (Min) and sol-corrections-and-lane-division.md §1 (Sol) both record the one-workspace correction. I am not restating it. This file holds the part of my lane that neither of them covered, because neither of us is the finance owner:

