Young's Mind
01 Research

HERMES STUDY — the single file

Young, 2026-10-11: "Register all your study on vault and keep it on single md file… we need to communicate and work together as single unit… I often found, you all jumped into the same issues and proposed different solution this is not team work."

HERMES STUDY — the single file

Young, 2026-10-11: "Register all your study on vault and keep it on single md file… we need to communicate and work together as single unit… I often found, you all jumped into the same issues and proposed different solution this is not team work."

This file is the answer to that instruction. Before writing it I measured what the team had already produced — and Young is right. Three of us wrote overlapping findings. The duplication is recorded below in §8, with what was merged and what was removed, because the fix for "not teamwork" is not another document.


1. The headline you asked for: fallback providers

Hermes already solves the 429 natively, and it was configured while I was studying it. Live, this morning, on all three Brains:

$ hermes fallback list
Primary:   longcat-2.5-preview-free  (via opencode-go)
Fallback chain (3 entries):
  1. step-5-preview-free        (via opencode-go)   [https://opencode.ai/zen/go/v1]
  2. exo-free                   (via opencode-zen)   [https://opencode.ai/zen/v1]
  3. nemotron-3.5-lightning-free (via opencode-zen)  [https://opencode.ai/zen/v1]
Tried in order when the primary fails (rate-limit, 5xx, connection errors).

Read that chain against the ladder I built in V3 (core/config/ladder.py, commit b022afc):

GO free  →  ZEN free  →  GO paid  →  ZEN paid

They are the same ladder. Free GO models first, then free ZEN models, and not a single paid model anywhere in the chain. Min's configuration is consistent with the rung order my tests enforce — and he reached it independently. That agreement is the evidence the doctrine is right, not that either of us was clever.

And it also fixed the defect that stopped the Brain: all three primaries were moved off space-bunny-free — which GO does not serve — onto longcat-2.5-preview-free, which V2's own health record shows at 769 successes, 0 failures.


2. The three resilience layers — and which one we are on

From /user-guide/features/fallback-providers, Hermes has three independent layers. Knowing which one is active matters, because they solve different problems:

LayerWhat it doesOur state
1. Credential poolsRotate across multiple keys for the same provider. Tried first.1-key pool — auto-discovered from .env
2. Primary model fallbackSwitch to a different provider:model mid-session, without losing the conversation✅ configured, 3 entries
3. Auxiliary task fallbackIndependent resolution for side tasks — vision, compressionnot inspected

Credential pools are not the answer to our 429, and the docs say why. "Pools are mainly for API-key providers. A single Nous Portal OAuth covers 300+ models." We have one GO key. Adding a second GO key would not help a per-model ceiling — the model is rate-limited, not the key.

The resume semantics — this is the important half

Min read the source rather than assuming, and it changes the answer:

BehaviourWhere
On error the turn swaps in place, resets the retry count, and CONTINUES the same turnagent/chat_completion_helpers.py
The primary is restored each turn — a 429 is a temporary switch, not a demotionagent/agent_runtime_helpers.py
While cooling, Hermes logs "Primary X rate-limited until T; staying on fallback"agent_runtime_helpers.py:1304
auto_recovery_cycles retries a transient outage up to 5 cycles with jittered backoffconfig_defaults.py

So "switch and resume" is the native behaviour. That is exactly Young's "switch to different model when it happen and resume tasks" — and it does not restart the task, which is what our own router.route() would have done.

The prompt-cache cost, which is a Mira finding

From the credential-pools doc, and it applies to any mid-session switch:

Provider-side prompt caches are scoped to the account/API key that made the request. When the pool rotates to a different key mid-session, the new key has no cached prefix — the next request re-reads the full history at undiscounted input price.

Read that against our own numbers. opencode stats shows cached input 91.6% — the fleet is running at ~92% cache hit. A mid-session model switch discards that prefix and re-reads the full context at full price once.

This is the strongest argument in the whole doc for putting free models FIRST, not for adding more of them. Every unnecessary switch costs a full-price context pass. Free-first means the cheapest switch is the one that gets used — and the ladder's rule that a rate limit on one model says nothing about the next is exactly what keeps the switch count low.

fallback.min_switch_reset_seconds — a cost knob we are not using

KeyDefaultEffect
fallback.min_switch_reset_seconds0 (off)A primary whose declared reset is sooner than this is not swapped; the backoff waits it out instead

Recommendation: set it. Default 0 means always switch — but switching costs a full-price context pass, as above. If the provider says "reset in 90s", waiting 90 seconds is cheaper than paying for the cache re-read. A value in the 120–300s range is the right shape. Unset right now.


3. Provider routing — the cost control we are not using

From /user-guide/features/provider-routing. This is OpenRouter-only; the docs are explicit it has no effect on Nous Portal or direct provider connections. We are on direct GO/ZEN endpoints, so most of it does not apply — with two exceptions worth naming.

sort: "price" — cheapest provider first. The exact instinct behind the ladder, natively.

🔴 data_collection: "deny" — this is the retention control, and we are not using it.

provider_routing:
  data_collection: "deny"

Why this matters more than anything else in this file. COST-POLICY.md §5 says anything touching vault content, credentials, task text or the registry routes only to a zero-retention model. I built cortex/classification.py for that rule, and core/config/ladder.py currently refuses a confidential task outright, because neither endpoint's catalogue exposes a zero-retention flag and I would not assume one.

data_collection: "deny" is the native mechanism for exactly that. It is a provider-side guarantee rather than a keyword classifier — a floor, not a guess.

Its limit, stated honestly: it is OpenRouter-only. We are on GO/ZEN direct. So it does not cover us today. It is the answer the day we route anything through OpenRouter, and it is not an answer to the flag's absence on GO/ZEN.


4. The credential boundary — one rule, one place

From /user-guide/features/credential-pools: hermes auth add <provider> --api-key … or --type oauth. Pools are enabled by adding a second key, not by a config flag.

And the standing rule, which every one of these features touches: report the variable name, never the value. hermes auth list leaks nothing; a pasted config block leaks everything.

Recommendation: no second GO key. Discussed above — the ceiling is per-model, so a second key buys nothing, and credential pools are where the exposure risk lives.


Young's list of references, mapped to the decision it answers. Loaded once, so nobody re-reads the docs to re-derive a finding.

ReferenceWhat it settles
/docs/entry point; /docs/llms.txt is the live feature index (62 entries)
/docs/skillshow a skill is authored — the SKILLS & TOOLS STORE lane
/docs/pluginsplugin extension; blueprints and tool registration
/developer-guide/architecturesystem overview; which subsystem owns what
/developer-guide/codebase-ownershipwhich files belong to whom — the doc that answers Young's lane question
/developer-guide/agent-loopthe turn/retry structure; how a switch resumes
/developer-guide/context-compression-and-cachingthe cache mechanics behind §2's cost finding
/developer-guide/prompt-assemblyhow the system prompt is built — relevant to persona/identity integrity
/developer-guide/provider-runtimewhere provider errors are classified
/developer-guide/creating-skillsthe blueprint + skill authoring path
/developer-guide/extending-the-cliadding commands
/reference/faqrecurring answers

The two that answer Young directly: codebase-ownership — because "don't fight for the same task" is a filesystem question, and context-compression-and-caching — because the 91.6% cache number is the whole cost story.


6. V3 ↔ Hermes: two switches, and how they relate

This is the part that was genuinely confusing before today. We now have two fallback mechanisms, and they are not the same thing.

Hermes fallback_providersV3 router.route()
Lives inHermes core, ~/.hermes/profiles/*/config.yamlcore/config/router.py + ladder.py
ServesBrain — Min, Mira, SolHeart — Ace, Alpha, Atlas, Echo, Nova
Switches onprovider error, 5xx, connection — source-read, measuredrate limit, unavailable, timeout, refusal, empty
Resumecontinues the same turnreturns a RouteResult with every attempt
Bounded byauto_recovery_cycles (5, jittered)MAX_ATTEMPTS
Status✅ live, 3 entries on all three Brainsbuilt, tested — 🔴 zero callers (P10)

So Young's question is answered twice, for two different units, and that is correct rather than duplicative. The Brain switches through Hermes because the Brain runs on Hermes. Heart switches through the ladder because Heart runs on opencode CLI. Each unit uses the switch its own runtime provides.

They share one doctrine, and it must not drift: free GO → free ZEN → paid GO → paid ZEN. Hermes' chain (longcat → step-5 → exo-free → nemotron) and the ladder's order agree today. If either changes, both must change — that is a drift test we do not yet have, and it should be one.


7. What I did NOT do

  • Did not configure anything. fallback_providers was already configured by Min before I was assigned this. I took the assignment and reported that it was DONE.
  • Did not set min_switch_reset_seconds, despite recommending it. It is a live- process config change on a Brain, and it is Young's ruling to make.
  • Did not route anything through OpenRouter. Which is why data_collection: "deny" stays a recommendation and not an action.
  • Did not verify a live switch-over. The chain is configured; I did not force a 429 to observe it fire. The source-read behaviour above is Min's measurement, not mine.
  • Did not read the eleven references end to end. I read the three you assigned me in full plus the architecture path; the rest are mapped in §5 from their docs entries so they load only when needed.

8. 🔴 The duplication — measured, and what I did about it

Young's instruction was to register all study in a single file. Measuring first found the problem is worse than duplication — it is disagreement between agents that never talked:

FileAuthorCoversDisposition
HERMES-FEATURES-REVIEW.mdMinthe eight featuresduplicate of mine — see below
hermes-brain-eight-features.mdMirathe eight featuresduplicate of Min's
AUTO-SWITCH-ON-RATE-LIMIT.mdMinthe auto-switch causemerge into this file
BRAIN-429-AUTOSWITCH-FIXED.mdMinthe Hermes fallback fixmerge into this file
PENDING-APPROVAL.mdMinpending itemskeep — the register
PENDING-APPROVAL-2026-10-10.mdMinpending items🔴 orphan — an earlier draft of the same list
mira-brain-429-diagnosis.mdMirathe 429 root causesuperseded — see below

Where Min and I genuinely disagreed: event hooks

Same review, opposite conclusions. This is exactly Young's complaint, and it deserves to be visible rather than resolved by whoever wrote last.

MinMira
Event hooks⚠️ "off, and it should stay off until we need it"⚠️ write ONE — pre_tool_call fail-closed on model availability

Min's position is the more disciplined one and I am withdrawing mine. His reasoning: the hooks directory is trusted-by-placement — no sandbox, no first-use prompt, HERMES_SAFE_MODE does not skip it — so writing a hook to solve "the model was misconfigured once" adds permanent attack surface to fix a problem that is now already fixed.

He is right, and the correction is worth more than my recommendation: the misconfiguration is gone. All three Brains now run longcat. The hook I proposed guards a defect the fallback chain already cured. That is building a control for a problem that no longer exists — which is its own failure mode.

Verdict: hooks stay off until something needs them. One agent proposes a hook, the other says it is a trap, and the right answer was the caution.

And my own misdiagnosis, corrected

mira-brain-429-diagnosis.md concluded that the Brain was stalled by misconfiguration and the fix was one line per Brain. The fix was right but the diagnosis was incomplete — Hermes' fallback chain was empty, which is the fuller cause, and Min found it while I was studying the same thing. Recorded, not hidden: the model misconfiguration was real (measured, 769 vs 0), and the empty fallback chain is what made it a stall rather than a single failed call.

What I am proposing we do about the duplication

  1. This file becomes the single Hermes study. HERMES-FEATURES-REVIEW.md and hermes-brain-eight-features.md should be removed, not left as rivals.
  2. PENDING-APPROVAL-2026-10-10.md is an orphan — an earlier draft of the same list Min now maintains. Removing it prevents anyone answering a stale question.
  3. One register, one owner. PENDING-APPROVAL is the register; nobody else writes to it in parallel. Findings go to the author's own lane file and get summarised into the register by its owner.
  4. Claim before you build. The fix for "you all jumped into the same issue" is a one-line claim before the work, in the group chat. Min configured the fallback chain before I had read the docs. A message would have prevented three documents.

I have not deleted anything. Three of these files are Min's, and a concurrent delete is how work gets lost here — P8 in the register records exactly that. This section is the proposal; the deletion is Young's or Min's to authorise.


Honest limits

  • I did not execute any of it. Every Hermes claim here comes from the docs, from hermes fallback list, or from Min's source-read in chat_completion_helpers.py / agent_runtime_helpers.py. The live switch-over is unobserved by me.
  • data_collection: "deny" does not apply to us. We are not on OpenRouter. It is the right control for the wrong provider, today.
  • The fallback chain and the ladder agree by observation, not by test. Nothing checks that the Hermes chain still matches the V3 ladder. It should.
Copyright © 2026