Hermes as a better Brain — eight features, measured, not assumed
Hermes as a better Brain — eight features, measured, not assumed
Young, 2026-10-11: "Utilise and optimise Hermes for a better Brain. Review, study and enable it these feature on Hermes."
Method. Each feature below was read from its docs page and then checked
against the live config (/home/lab/.hermes/profiles/{min,mira,sol}/config.yaml,
~/.hermes/cron/jobs.json, ~/.hermes/kanban.db, CLI --help). A feature
listed as "enabled" without a live measurement is not a finding.
The headline
Six of the eight are already live and need no work. Two are the gap, and they are the two that make a fleet autonomous rather than merely busy.
| Feature | Live state | Verdict |
|---|---|---|
| Code execution | ✅ enabled — code_execution toolset active on CLI + Telegram | leave it |
| Event hooks | ⚠️ infra present, no hooks written | enable |
| Batch processing | ✅ batch_runner.py ships | not for the Brain — see below |
| Automation blueprints | ✅ /blueprint works from every surface | enable |
| Goals | /goal runtime command, per-session | enable as doctrine |
| Kanban | ✅ kanban.db exists (118 KB), review_dispatch: true, kanban toolset | already the shared board |
| Heartbeats | /heartbeat runtime command, min 60s | enable — this is the 24/7 answer |
| Recurring loops | /loop + loop_watchdog: true already on | enable as doctrine |
| Curator | ✅ enabled, hash-chained skill audit ledger | don't build a second |
1. Heartbeats — 🔴 the one that answers "work autonomously 24/7"
From the docs: /heartbeat every 10m <prompt> fires as a normal user turn
whenever the session is idle. Idle-only — it never interrupts a running turn.
Missed ticks coalesce — a day of downtime produces one heartbeat, not a
backlog. Cache-safe — plain user message, no system-prompt mutation. Survives
restart via SessionDB, and the gateway resumes it.
Why this is the right primitive for the Brain, and not cron. Cron spins a fresh isolated session per tick — no memory of the conversation. A heartbeat runs in the same conversation with full context. For a Brain that must notice "the free model is 429ing again", that context is the whole point: it remembers what it tried last time.
Measured gap: no heartbeat is set on any of min / mira / sol.
Enable, per Brain:
/heartbeat every 10m Check GO free model health and report meaningful changes
And the pair that makes it cost nothing: /loop is self-paced — it backs
off exponentially (1m → 2m → 4m → … → 15m) while replies stop changing, and snaps
back to the floor the moment one differs. So the heartbeat/loop pair is cheap
when nothing is wrong and fast when something is. That difference is exactly
what we want from a 24/7 watchdog.
Recommendation: /loop (self-paced), not /heartbeat (fixed interval) — the
work drives the rhythm. Use a fixed /heartbeat 10m only for the model-health
watch, which is on its own clock.
2. Goals — the doctrine that stops "issue to the next"
From the docs: after every turn, a lightweight judge model checks whether the goal is satisfied. If not, a continuation prompt is fed back into the same session, until the goal is achieved, you pause it, or the turn budget runs out.
The sharp boundary the docs are explicit about, and it matters to us:
/goalis single-session. It never creates a kanban card, never fans out, never hands off.- Kanban is the board — many tasks, own worker process each, dependencies and handoffs on the board.
So the correct split for SolOS is already defined by the tool, not invented by us:
| Want | Use |
|---|---|
| Brain keeps iterating on one objective until done | /goal |
| Many tasks, dependencies, handoffs across Min/Mira/Sol | Kanban |
| One card that iterates until acceptance criteria met | kanban card with --goal |
🔴 The finding for us. This is the actual answer to Young's "I feel we're
going from issue to the next." A judge-driven goal means the Brain does not stop
at a plausible-looking stopping point — it stops at the achieved objective. V2's
pattern was a plausible-looking zero; /goal's judge is the mechanism that refuses
that.
Enable as doctrine: every Brain gets /goal for any task with a definition of
done. Not for one-turn work.
3. Automation blueprints — the cheap path to standing jobs
From the docs: a blueprint is "a skill with a metadata.hermes.blueprint
block in its SKILL.md frontmatter." /blueprint morning-brief time=08:00
schedules it as a cron job — no cron syntax. Works from every surface, always
confirms before creating.
Live state: works. /blueprint resolves from dashboard, CLI, TUI and
messengers, with forgiving name matching.
Measured gap: ~/.hermes/cron/jobs.json holds exactly one job —
sol-persona-sync, every 30m. For a fleet that is supposed to run 24/7, that is
the whole standing schedule.
Enable — four blueprints for the Brain, in cost order:
model-health— free-tier 429 watch. The one Young just hit. Runs/probeagainst GO+ZEN, records the result, reports only changes.fleet-drift— V3's registry against the live endpoints. This is the Stage 1.8 defect (space-bunny-freeunder GO) as a standing check rather than a one-off discovery.costledger-digest— readscore/config/cost_ledger.py's output and reports spend by instrument. The number that would have caught V2's $10.34 day on day one.backup-cadence— Stage 9, still an open ruling (P5). Cheap to schedule the moment the cadence is decided.
Cost note: each is a cron job = a fresh isolated session per tick, so each burns a model call. Four standing jobs is not free. Recommend they all run on the GO free tier, and that only the two that report changes (1 and 2) fire often — the other two daily.
4. Event hooks — ⚠️ infra present, zero hooks written
From the docs, four systems:
| System | Registered via | Runs in |
|---|---|---|
| Gateway hooks | HOOK.yaml + handler.py in ~/.hermes/hooks/ | Gateway only |
| Plugin hooks | ctx.register_hook() | CLI + Gateway |
| Shell hooks | hooks: block in profile config.yaml | CLI + Gateway + Desktop/TUI |
| Outbound webhooks | hooks.outbound: in config.yaml | CLI + Gateway |
Trust model, and it matters before we write one: "The hooks directory is a
trusted-by-placement extension point… There is no sandbox, no first-use prompt, and
HERMES_SAFE_MODE does not skip this loader." handler.py runs in-process
with the gateway's own access — loaded credentials included.
Measured: ~/.hermes/hooks/ — empty. No hooks written anywhere.
The one hook worth writing, and it is a Brain-liveness guard, not a feature:
a shell pre_tool_call hook that fails closed if the configured model is not
in the live catalogue. That is precisely the defect that stopped the Brain this
week — two of three profiles on space-bunny-free, which GO does not serve.
The hook would have caught it on the first turn instead of on the 429.
And the credential boundary it must respect: the hook reports the variable name of a model/key, never its value. Mira's standing rule.
Recommendation: write exactly one hook — the model-availability fail-closed guard. Everything else is feature creep on a trusted-by-placement surface.
5. Code execution — already on, and it is the Brain's biggest cost lever
From the docs: execute_code lets the agent write Python that calls Hermes
tools over a Unix-domain socket, and only the script's print() output enters
the context window — intermediate tool results never do.
Live state: ✅ code_execution in the enabled toolset on both CLI and
Telegram lines. Already working.
Why this is the single highest-leverage item on Young's list. I use it
constantly — and its rule is literally "3+ tool calls with logic between them".
V2's cost problem was not the model price; it was 30,721 attempts where
intermediate results flooded context. execute_code is the mechanism that
prevents that on V3.
No action needed. Record it so nobody disables it as "expensive".
6. Recurring loops — already on, guardrail included
Live state: loop_watchdog: true, loop_watchdog_probe_interval_s: 30.0,
max_strikes: 3 — already configured. Plus startup_watchdog and
restart_loop_guard.
This is important: Hermes already ships a watchdog against the exact failure mode of an autonomous fleet — a loop that spins without progressing. V2's retry storm is what that guard exists to stop.
No action needed. Use /loop self-paced for anything driven by the work.
7. Kanban — already the shared board, and it is our task model
Live state: ~/.hermes/kanban.db (118 KB), review_dispatch: true, and the
kanban toolset is in the enabled list. Workers drive it through kanban_*
tools; humans and cron drive hermes kanban.
This is the answer to "orchestrator assigns tasks to agents" — already live. Each card gets its own full OS process with its own identity, which is the isolation our Heart Unit needs.
One measured caution: the docs describe dispatcher-owned workers with finite
iteration budgets and a consecutive-failure circuit breaker. That is the same
doctrine as V3's router.route() — bounded attempts, and every attempt recorded.
Aligned, not duplicated. Do not let the two retry policies diverge.
8. Batch processing — 🔴 honest recommendation: do NOT enable it
From the docs: batch_runner.py runs the agent across thousands of prompts to
generate ShareGPT-format trajectories for fine-tuning.
Live state: ships with Hermes; nothing configured.
Recommendation: not for the Brain. We are not producing training data — we are running a fleet that ships. And the docs' own warning is the cost warning: "Batch runs spin up many concurrent agent sessions, each making model calls."
Enable it only if we adopt a fine-tuning step. Registering that as a decision rather than silently ignoring it, because it was on Young's list.
What I recommend we do, in order
| # | Action | Owner | Cost |
|---|---|---|---|
| 1 | Set /loop self-paced on all 3 Brains — the 24/7 watchdog | Sol applies | free-tier |
| 2 | Write ONE shell hook: model-availability fail-closed | Mira | ~0 |
| 3 | Create model-health + fleet-drift blueprints | Mira | 2 cron jobs |
| 4 | Adopt /goal as doctrine for any task with a definition of done | all | judge model |
| 5 | Enable curator (curator.enabled) — currently unconfigured | Young's call | aux model |
| 6 | Batch processing: NO — registered as a decision, not enabled | — | — |
Live config measured: /home/lab/.hermes/profiles/{min,mira,sol}/config.yaml
· ~/.hermes/cron/jobs.json (1 job) · ~/.hermes/kanban.db · ~/.hermes/hooks/
(empty) · hermes --help.
Honest limits
curator.enabled— CORRECTED by a live probe. My first pass recorded it as absent and therefore a gap. That was wrong.hermes config get curatorreturnsenabled: true, weekly (168h), stale after 14 days, with a skill audit ledger at~/.hermes/skills/.curator_ledger.jsonlrecording before/after hashes and poweringhermes curator rollback <entry-id>.
Why the correction matters more than the original finding. The curator is not memory housekeeping — it audits skill mutations, with before/after hashes and a rollback path. For a fleet where Young assigned "a skill curator — Min", a live, hash-chained, rollback-able audit ledger already exists. We do not need to build one, and we must not build a second.
The general lesson, recorded because it cost me a wrong finding: an absent key inconfig.yamlis not an absent setting.config_migrations.pyseeds missing sections fromDEFAULT_CONFIGat load. I read the file and inferred; the probe would have told me. A config read is not a probe.- I have enabled nothing. Every item above is a measurement plus a
recommendation. Items 1–4 need Sol or Young to apply —
/loopand/heartbeatare session-scoped runtime commands and cannot be set from a config file, and~/.hermes/is Sol's lane. - Docs-only, not executed. Every feature above is confirmed two ways: its
docs page, and the docs index (
/docs/llms.txt, 62 entries, fetched live) listing it. What I did not do is execute any of them — no/goalset, no/heartbeatrunning, no blueprint scheduled, no hook written. A feature that exists is not a feature that is enabled, and none of these are.
The reason is a lane boundary, not caution:/loop,/heartbeatand/goalare session-scoped runtime commands — they cannot be set from a config file and they do not survive into another profile's session — and~/.hermes/is Sol's lane. Min applies the commands; I supply the measurement.

