NousResearch/hermes-agent + stevengonsalvez/hermes-fleet-backup · architecture note

What we layered on top of vanilla Hermes

Vanilla Hermes — the upstream NousResearch/hermes-agent harness — gives us a Python gateway, a plugin loader with pre_llm_call / post_llm_call events, profiles, sessions, and a CLI. That's it. The Fleet Lambda overlay is everything we wrap around that core to turn it into a self-improving, drift-resistant, observable agent fleet: a 12-file fleet-hooks plugin, a canonical fleet-hooks-spec contract validated on every write, lifecycle hooks that POST to Convex, per-agent identity files (SOUL.md, IDENTITY.md, STANDING_ORDERS.md, HEARTBEAT.md), the cross-fleet BANK at ~/.clan/learnings/, a holographic memory store, and an encrypted backup mirror at github.com/stevengonsalvez/hermes-fleet-backup. Every overlay layer can be ripped out and Hermes still runs — the seed is untouched.

The overlay, ringed around the seed

Hermes Fleet Lambda — overlay on vanilla Hermes nested rings · each ring is something we added on top of NousResearch/hermes-agent 06 · persistence + egress encrypted backup → github.com/stevengonsalvez/hermes-fleet-backup (transcrypt aes-256-cbc · hourly cron · restore.sh) live egress → Convex /api/events (wololo session events + acp-metrics POST per turn → live dashboard) 05 · skills + tool configs fleet-skills/ (mirrored from hermes-fleet-backup/fleet-skills/) · tool-configs/gh-hosts.yml (encrypted) 04 · knowledge cross-fleet BANK: ~/.clan/learnings/ · patterns · corrections-raw · strikes · missed-learnings · acp-metrics · bank-injection bank.db (FTS5 index · gitignored · rebuildable from .jsonl) holographic memory: ~/.hermes/profiles/<name>/memory_store.db (sqlite embeddings · hermes-memory-store plugin) 03 · identity (per agent profile) SOUL.md · IDENTITY.md · STANDING_ORDERS.md · HEARTBEAT.md · MEMORY.md (rolled-up index) config.yaml · agent-config.yaml (encrypted) · .env (encrypted) · cron/jobs.json · memories/ · self-improving/ 02 · lifecycle hooks (gateway) wololo-events → Convex POST on session/agent start (fire-and-forget · 3s timeout) message-test → debug log appender 01 · plugin layer · fleet-hooks + spec fleet-hooks/ · 12 py · 5 spec-first ports + week-2 + spec_validator + dispatcher fleet-hooks-spec/ · 10 schemas · 8 behaviors · 59 test-vectors · golden runners (py+node) vanilla Hermes Python harness · gateway · plugin loader · pre_llm_call/post_llm_call · profiles · sessions · CLI github.com/NousResearch/hermes-agent read inside-out: vanilla harness is the seed; each ring adds capability without modifying the core.

// diagram generated via /fireworks-tech-graph

The six overlay layers

1
~/.hermes/plugins/fleet-hooks/ + hermes-fleet-backup/plugins/fleet-hooks-spec/

The plugin layer — the one ring that touches every LLM turn. Vanilla Hermes loads it via the standard plugin contract, but the dispatcher fans out to five spec-first hook ports (session_rules, learning_sync, learning_verifier, acp_metrics, manifest_context) plus three Week-2 fleet behaviours (correction_detector, inbox_enforcer, circuit_breaker) plus bank_lookup, injection_history, and spec_validator. Every write is validated against fleet-hooks-spec — 10 JSON schemas, 8 behavior docs, 10 test-vector directories, Makefile + golden runners (py + node), 59 cases green on both languages.

what's inside
# ~/.hermes/plugins/fleet-hooks/
__init__.py           # dispatcher: pre_llm_call + post_llm_call
spec_validator.py     # graceful jsonschema · warn unless FLEET_HOOKS_SPEC_STRICT=1
session_rules.py      # pre: inject STANDING_ORDERS (full T1, condensed T2+)
manifest_context.py   # pre: 1st turn — inject .clan/manifest.yaml repo context
learning_sync.py      # post: corrections → patterns.jsonl + strikes
learning_verifier.py  # post: sig-collision → missed-learnings.jsonl
acp_metrics.py        # post: outcome enum · flock append · Convex POST
correction_detector.py# pre+post: scan + verify mtime delta
inbox_enforcer.py     # post: @mention without [inbox:ID] → violation
circuit_breaker.py    # pre: 3-strike injection guard
bank_lookup.py        # pre: FTS5 query over patterns.jsonl (1st turn)
injection_history.py  # in-memory + per-agent injection ledger

# hermes-fleet-backup/plugins/fleet-hooks-spec/
schemas/              # 10 .schema.json · schemaVersion 1
behaviors/            # 8 canonical behavior docs
test-vectors/         # 10 dirs · 59 cases (valid + invalid)
Makefile              # make test-spec → runs py + node golden runners
runners/{py,node}/    # cross-language validators
2
~/.hermes/profiles/<name>/hooks/ · sourced from hermes-fleet-backup/hooks/

Gateway hooks — these fire on session lifecycle events (not per-turn). Vanilla Hermes has the hook contract; we use it. wololo-events POSTs to the Convex backend on session_start and agent_start (fire-and-forget, 3-second timeout, never blocks). message-test is a debug log appender. Without these the dashboard at getwololo.com is blind to fleet activity.

config shape
# ~/.hermes/profiles/freeman/hooks/wololo-events.yaml
events:
  - session_start
  - agent_start
action: http_post
url: ${CONVEX_URL}/api/events
timeout_ms: 3000
on_failure: drop  # never block the agent
3
~/.hermes/profiles/{freeman,motoko}/ · mirrored encrypted to hermes-fleet-backup

Persistent agent identity. Vanilla Hermes has config.yaml per profile, nothing else. The overlay adds a small constellation of markdown files that are the agent: SOUL.md (personality + voice), IDENTITY.md (who am I), STANDING_ORDERS.md (rules — fed back via session_rules hook every turn), HEARTBEAT.md (long-running ops directives), MEMORY.md (rolled-up memory index over memories/*.md). Plus the encrypted half: agent-config.yaml (Discord token, model, Convex URL) and .env, both transcrypted before they touch git.

profile layout
# ~/.hermes/profiles/freeman/
config.yaml              # model, plugins, gateway settings · public
agent-config.yaml        # Discord token, Convex URL · ENCRYPTED
.env                     # API keys · ENCRYPTED
SOUL.md                  # personality + voice
IDENTITY.md              # who am I, name, role
STANDING_ORDERS.md       # rules, behaviours, hard constraints
HEARTBEAT.md             # long-running ops directives
MEMORY.md                # rolled-up index over memories/
memories/                # private .md files per topic
self-improving/          # corrections.md, violations.jsonl, …
cron/jobs.json           # scheduled tasks
4
~/.clan/learnings/ + ~/.hermes/profiles/<name>/memory_store.db

The memory layer. Vanilla Hermes has no shared learning store, no embedding retrieval. The overlay gives us two complementary stores. The cross-fleet BANK at ~/.clan/learnings/ is a forest of append-only jsonl files (patterns, strikes, corrections-raw, missed-learnings, acp-metrics, bank-injection) plus an FTS5 sqlite index that rebuilds itself from the .jsonl source on boot — so bank.db is gitignored and fully recoverable. Then holographic memory: memory_store.db per agent, sqlite-backed semantic embeddings via the hermes-memory-store plugin (ported from clawdbot). Every correction the user lands becomes a pattern the next first-turn bank_lookup can find — "correct once, never again".

structure
# ~/.clan/learnings/  — cross-fleet, shared with NanoClaw
patterns.jsonl           # canonical learnings (sig-stamped)
patterns.md              # human-readable render
corrections-raw.jsonl    # every flagged correction event
strikes.jsonl            # 3-strike ledger for HOT promotion
missed-learnings.jsonl   # sig-collision detections
acp-metrics.jsonl        # per-turn outcome counters
bank-injection.jsonl     # log of BANK retrievals → context
discoveries.jsonl        # ad-hoc agent discoveries
bank.db (+ wal/shm)      # FTS5 index · gitignored · rebuildable
scripts/                 # acp-inactivity-closer.py, daily-bank-report.py

# ~/.hermes/profiles/<name>/  — per agent, private
memory_store.db          # holographic embedding sqlite
memory_store.db-shm/wal  # sqlite write-ahead
5
~/.hermes/fleet-skills/ + hermes-fleet-backup/tool-configs/

Composable capabilities. The fleet-skills/ directory holds reusable agent skill bundles, mirrored from hermes-fleet-backup/fleet-skills/ on restore. Tool configs (gh-hosts.yml for the GitHub CLI, future sentryclirc, etc) live encrypted in the backup repo under tool-configs/. Vanilla Hermes has no skill-registry pattern at all — agents are bound to whatever tools come at process start. The overlay gives Stevie a place to drop new agent capabilities (a new skill folder + restart) without touching harness code.

layout
# ~/.hermes/fleet-skills/  — runtime
<skill-name>/
  SKILL.md               # what the skill does, when to trigger
  scripts/               # executable steps
  references/            # supporting docs

# hermes-fleet-backup/tool-configs/  — encrypted
gh-hosts.yml             # gh CLI auth
sentryclirc              # (future) sentry CLI
6
github.com/stevengonsalvez/hermes-fleet-backup + Convex /api/events

The outermost ring — survival + observability. Vanilla Hermes persists everything to live disk, full stop; a laptop dies, the fleet dies. The overlay wraps that with two egress channels. The encrypted backup repo (github.com/stevengonsalvez/hermes-fleet-backup) uses transcrypt aes-256-cbc — .env + agent-config.yaml + tool-configs/ never touch git in plaintext. A cron runs backup.sh hourly: rsyncs profile state, mirrors the BANK, commits, pushes. Restore is git clone + transcrypt --decrypt + ./restore.sh = back in business on a fresh machine. Convex egress (POST /api/events) sinks two streams in real-time: wololo lifecycle events from Layer 2, and acp-metrics records from every turn — both feed the getwololo.com dashboard.

backup contents
# github.com/stevengonsalvez/hermes-fleet-backup/
profiles/freeman/        # config + identity .md files + memories + self-improving
profiles/motoko/         # (same shape, per agent)
plugins/fleet-hooks/     # Python source
plugins/fleet-hooks-spec/# 10 schemas + 8 behaviors + test-vectors
shared/clan/learnings/   # mirror of ~/.clan/learnings/ (minus bank.db)
hooks/                   # gateway hook scripts
fleet-skills/            # composable agent skills
tool-configs/            # ENCRYPTED — gh-hosts.yml etc
docs/                    # architecture, migration, storage-map
backup.sh / restore.sh   # cron'd mirror + restore script
.gitattributes           # transcrypt filter rules

How a single LLM turn moves through the overlay

Per-LLM-turn flow — Hermes Fleet Lambda how one conversation turn moves through the overlay · 5 pre · LLM · 5 post · persisted USER MESSAGE conversation turn arrives at gateway ▸ pre_llm_call · UserPromptSubmit pre · 01 correction-detect scans user msg no/wrong/actually signals pre · 02 manifest-context first turn only inject .clan/manifest.yaml pre · 03 session-rules every turn inject STANDING_ORDERS pre · 04 bank-lookup first turn only FTS5 over patterns.jsonl pre · 05 circuit-breaker every turn stop repeated failures LLM CALL prompt assembled · model reasons · response streams fleet-hooks-spec validates every write ▸ post_llm_call · Stop post · 01 correction-verify did corrections.md mtime change? else flag post · 02 inbox-enforcer @mention without [inbox:ID] then violation post · 03 learning-sync sig dedup + strike patterns.jsonl append post · 04 learning-verify sig-collision vs strikes ledger then miss post · 05 acp-metrics outcome enum + flock + Convex POST ▸ persistence · validated writes per-agent self-improving/ ~/.hermes/profiles/[name]/ violations · pending-corr injection-history · MEMORY.md cross-fleet BANK ~/.clan/learnings/ patterns · strikes · acp-metrics missed-learnings · bank-injection bank.db (FTS5 idx) ~/.clan/learnings/bank.db gitignored · rebuildable feeds next turn pre·04 ↑ Convex egress POST /api/events acp-metric records wololo session events next turn BANK feedback

// diagram generated via /fireworks-tech-graph · dashed feedback arrow is why every correction makes the next turn smarter

What you get vs. vanilla — the value table

Overlay layer What it gives you vs. vanilla Hermes
fleet-hooks plugindeterministic per-turn behaviour: correction capture, inbox governance, learning sync, drift detection, ACP metrics, BANK retrievalvanilla = LLM-driven freeform only; no governance layer; no learning loop
fleet-hooks-speccanonical cross-fleet contract — 10 JSON schemas + 8 behavior docs + 59 test-vectors. Every write validated, hard-fail under FLEET_HOOKS_SPEC_STRICT=1vanilla has no spec layer; plugin writes are unverified by definition
gateway hooks (wololo)real-time observability — Convex dashboard sees session start, agent start, every ACP metric per turnvanilla has the hook contract but nothing implementing it → blind
identity files (SOUL/IDENTITY/STANDING_ORDERS/HEARTBEAT)persistent agent personality + rules + ops directives across sessions — fed back via the session_rules hook every turnvanilla has config.yaml only; no agent-identity .md files; no compaction-proof rule injection
shared BANK (~/.clan/learnings/)cross-agent + cross-fleet memory — "correct once, never again". FTS5 over patterns.jsonl, rebuilds from .jsonl on bootvanilla has no shared learning store; each agent re-discovers the wheel
memory_store.db (holographic)per-agent semantic retrieval over private memories/*.md via embeddings — ported from clawdbot's hermes-memory-store pluginvanilla has no embedding store; only literal-string memory access
backup repo + transcryptlaptop-loss survivable. Encrypted secrets in git. backup.sh hourly cron, restore.sh one-command recovery on a fresh machinevanilla persists state to live disk only — laptop dies, agents die
fleet-skills/composable agent capabilities pulled from hermes-fleet-backup/fleet-skills/ on restore — drop a folder, get a skillvanilla has no skill-registry pattern; tools are bound at process start
Convex integrationlive getwololo.com dashboard, ACP-metric records, cron heartbeat — real-time fleet visibilityvanilla has no external sink; no dashboard, no telemetry

Where everything lives

Layer Runtime path (live) Source-of-truth (git)
vanilla harnessinstalled Python pkg + ~/.hermes/github.com/NousResearch/hermes-agent
fleet-hooks (impl)~/.hermes/plugins/fleet-hooks/hermes-fleet-backup/plugins/fleet-hooks/
fleet-hooks-spec— (consumed via spec_validator)hermes-fleet-backup/plugins/fleet-hooks-spec/
gateway hooks~/.hermes/profiles/<name>/hooks/hermes-fleet-backup/hooks/
agent profile identity~/.hermes/profiles/<name>/hermes-fleet-backup/profiles/<name>/ (.env + agent-config encrypted)
cross-fleet BANK~/.clan/learnings/hermes-fleet-backup/shared/clan/learnings/ (bank.db gitignored)
holographic memory~/.hermes/profiles/<name>/memory_store.db(gitignored · rebuilds from memories/*.md)
fleet-skills~/.hermes/fleet-skills/hermes-fleet-backup/fleet-skills/
tool configs~/.config/gh/, ~/.sentryclirc, …hermes-fleet-backup/tool-configs/ (encrypted)
Convex egresslive HTTP POST · no local persistencegithub.com/stevengonsalvez/getwololo (backend)