Hermes internals — memory, context, prompt assembly, self-evaluation and improvement
Hermes internals — memory, context, prompt assembly, self-evaluation and improvement
Summary
- Memory is a fixed, frozen budget; context is everything else. Two profile-scoped files (MEMORY.md 2,200 chars, USER.md 1,375 chars) are injected as a frozen system-prompt snapshot, always in context, agent-managed by the
memorytool; session recall of everything else issession_searchover SQLite FTS5, not memory pressure.1 - The system prompt is a 3-tier cached object — stable (identity/SOUL + tool guidance), context (project files, git snapshot), volatile (skills index, memory snapshots, runtime facts last) — deliberately separated from per-call additions (ephemeral prompts, prefill, gateway overlays) so provider prompt caches survive whole sessions.4
- Hermes self-evaluates and improves through two independent loops: a per-turn judge (
goal_judge) that drives goal-loop continuation/parking, and a background self-improvement review (~every 10 turns) that persists lessons as agent-created skills for the Curator to lifecycle-manage — plus curation-side linters that flag, never silently rewrite, skills that drift into log-shaped prose.[9]8 - This note is doc-verified, not a live-trace. Where the docs are silent (memory-file on-disk format, FTS internals, consolidation prompt internals, turn-counter logic), the gaps are listed rather than guessed; unchanged claims were cross-checked against
hermes-agent.nousresearch.com/docs/llms.txtand only retained when a cited doc page carried them.[1][9]12
Memory — the frozen-budget model
- Two files live in
~/.hermes/memories/per profile: MEMORY.md (2,200 chars) and USER.md (1,375 chars), and are reshaped ONLY by thememorytool'sadd/replace/removeactions — there is noreadaction, because the whole snapshot already sits in the system prompt header with usage percentages and§-delimited entries.1 - The agent writes here proactively (post-turn background review included); writes carry a
write_approvalstaging gate, duplicate-content rejection, and a blocked pattern list (injection/exfiltration/invisible Unicode). Over-limit writes fail with current usage, forcing an in-tool consolidation before retry. No auto-compaction of memory exists — a full memory must be consolidated by the agent, not pruned by the runtime.1 - External memory providers (8 plugins: Honcho, OpenViking, Mem0, Hindsight, Holographic, RetainDB, ByteRover, Supermemory) run alongside the built-in files, not instead of them.1
session_searchis deliberately not memory: it stores and queries real session data from~/.hermes/state.db(SQLite FTS5, sub-second, no LLM in the loop) so recall is on-demand rather than in-context; this split (fixed budget vs. instant recall) is the core memory design in Hermes.2
Context — what fills the window, and what never costs
- Context files use a first-match-wins priority chain (
.hermes.md→AGENTS.md→CLAUDE.md→.cursorrules, one only), and are loaded per project from the current working directory rather than a central store;SOUL.mdis independent and always resolved from$HERMES_HOME/SOUL.mdonly, never from a project directory.[3]6 - In git repos, AGENTS.md files from the git root down to the CWD merge into one block (specific-wins, provenance headers, dedupe); in non-git directories only the CWD file is loaded. Progressive discovery via
SubdirectoryHintTrackerinjects subdirectory AGENTS.md blocks into later tool results — at most 5 ancestors, 8 files, 8,000 chars, once per directory per session.3 ~/.hermes/state.dbis the canonical session store (WAL, schema v23):sessions,messages,messages_fts(FTS5 + trigram/cjk tables), compression locks, async delegations;api_contentis a byte-fidelity sidecar used for prompt-cache-stable replay after compression splits, withparent_session_idpreserving lineage.2- Write contention is handled with a 1-second SQLite busy timeout, 15 jittered retries,
BEGIN IMMEDIATEand a PASSIVE checkpoint every 50 writes — the design accommodates multiplexed gateway processes sharing the same DB.2 @context references are a CLI-side expansion (@file:,@folder:,@diff,@git:,@url:) that injects fetched material into the next user turn, bounded by a soft 25% warning and a hard 50% refusal. Sensitive paths (.ssh/,.aws/,$HERMES_HOME/.env, service configs) are always blocked, traversal outside the workspace root is rejected, and binaries are rejected by MIME/null-byte check. On gateways/Telegram the equivalent is agent tools, not@syntax.11
Prompt assembly — three tiers, one cache
- The three tiers are ordered stable → context → volatile so that shared blocks match at the front and volatile blocks (memory snapshot, skills index, timestamp/session/model line, runtime env hints) sit at the very end. This is what preserves longest-prefix prompt caching across sessions, worktrees and models of the same project.4
- Everything that varies per turn lives on the "API-call-time-only" path —
ephemeral_system_prompt, prefill, gateway overlays,pre_llm_callplugin blocks — and is appended to that turn's user message rather than mutating the cached prompt. Mid-session changes like skill-index diffs or platform switches ride a one-shot note on the same per-turn channel, then converge into the cache at the next rebuild.4 - The project context files are ordered so the shared part (project files) precedes the worktree-specific part (git snapshot), which is what lets the whole context-tier prefix be reused across sibling worktrees of one repo rather than invalidated per check-out.4
load_soul_md()reads and sanitizes SOUL.md, then its content replaces the built-in default identity block;build_context_files_prompt(skip_soul=True)exists to prevent a double load, so SOUL lives in slot #1 of the prompt and personality overlays come later as temporary session overrides rather than a separate channel.[4]6- Skills use progressive disclosure: the index (~3K tokens) sits in the system prompt,
skills_list()is the on-demand level 0 view, andskill_view(name[, file])pulls the body or a reference only when the task needs it — the docs' "skill is the better home for procedures" is the cache-stable trade-off against memory's fixed char budget.8
Context compression, caching, and cost of the loop
- Hermes has two compressors, by design: a gateway-level hygiene net at 85% of context (fires only when history exceeds 4 messages, so the agent compressor missed it) and an in-loop
ContextCompressorat 50% (defaultcompression.threshold, floored to 0.75 for windows under 512K). The 85% exists specifically because a gateway firing at 50% compressed before every turn — the threshold drift is a lesson, not a typo.5 - Trigger decisions lean on provider evidence, not estimates: the usage anchor combines real reported tokens with an estimate of appends since, and only unanchored over-threshold runs wait one request for a reported token count; provider-proven overflow compresses immediately. Pluggable
context.engineswaps the whole internals, and plugin engines never auto-activate.[5]12 - Prompt-cache invalidation is documented exactly: any mid-sequence insert/remove of messages after a hit prefix, and any post-compression region, invalidate that segment's cache; the system-prompt cache survives compression, and rolling
system_and_3re-establishes prompts within 1–2 turns. Model/credential identity is part of the cache key — a/modelswitch or key-pool rotation legitimately produces zero cache hits until the new identity establishes a prefix, which is the documented cost warning rather than a bug.5 - Micro-compaction (opt-in) folds one assistant exchange per turn into a running summary, keeping user messages always verbatim; the price is a synchronous prompt-cache prefix break every turn, so it is a cadence dial —
micro_compact_every_n_turns— rather than a free win. Failure ladders (cooldowns 60s→300s→900s) and provider-proven overflow bypasses are documented fail-safe paths.12
Delegation — prompt extension by context, not by prompt
- A delegated child sees only the text the parent passed:
delegate_task(tasks=[{goal, context}])spawns an isolated conversation whose ONLY prompt extension is thecontextfield, so paths, project shape and constraints must ride inside it rather than being inherited implicitly.7 - Children inherit the parent's toolsets minus the blocked ones, cannot re-delegate by default (orchestrators with
delegation.max_spawn_depth> 1 can), and only the final summary returns — intermediate tool calls never enter the parent's context, which is why summaries must be verified before being trusted as fact.7 - Delegation durability is bounded by the parent process: background children are process-local, so cross-restart work needs cron or detached terminal processes instead of a stranded background child.
Skills pipeline — how a lesson becomes a future-session capability
- A skill is a directory with a required
SKILL.mdplus optionalreferences/andscripts/, carrying structured frontmatter (name, description with trigger-first wording, version, author, license, platforms and Hermes metadata tags); this is the agentskills.io-compatible shape and it is what makes a lesson loadable rather than a prose memory dump.10 - The chain back into future sessions: the system prompt carries the index,
skills_list()is the level-0 view (~3K tokens),skill_view(name[, path])loads the body or a reference file on demand, and mid-conversation changes ride a one-shot note on the user-message channel so the cached index converges at the next compaction rather than breaking cache mid-session.[10]8
Self-evaluation and improvement — three independent mechanisms
- In-loop judge (
goal_judge): every turn's last output is judgeddone | continue | blockedagainst the standing goal. This is what drives both chat-session/goals and Kanban--goalcards; fail-open on judge errors, so a broken judge cannot wedge the loop, and the turn budget is the backstop.4 - Background self-improvement review fork: runs ~ every 10 agent turns in its own prompt cache (so it does not cost a paid call in the live conversation) and, via
skill_managewithcreated_by: background_review, persists a lesson as an agent-created skill. This is the mechanism that gives Hermes "self-improvement" without human triage of every change.8 - Curator: a two-phase skill lifecycle manager. Phase 1 is deterministic inactivity sweeps (
active → stale @14 days → archived @30 days) into~/.hermes/skills/.archive/, never auto-delete; phase 2 (opt-in viacurator.consolidate) is an LLM pass that can merge, umbrella, or archive agent-created skills — the ~50–100 API calls are a deliberate opt-in cost, not silent background work. Telemetry lives in.usage.json; hand-written/external skills stay unmanaged unless explicitly adopted. Vault-style fused-rule: curator never deletes; the worst it does is archive.9 - The three mechanisms never cross each other: the judge does not save skills, the self-improvement fork does not edit config, and curation's consent gate keeps hand-written skills out of the LLM's reach. This separation is the design that makes the loop simple to reason about.[9]8
What is deliberately NOT documented (do not treat as verified)
- The exact on-disk format of MEMORY.md/USER.md entry boundaries (beyond the
§delimiter convention visible in the prompt header). - How automatically-generated memory entries are captured (the hook, the interval, or the prompt that drives auto-capture).
- The FTS5 index internals and how it is kept in sync with
messagesunder high write contention. - Exact programmatic trigger of
parent_session_idsplits during compression, beyond the doc's own stated behavior. - The consolidated curator LLM prompt internals and exact turn-counter for the ~every-10-turns fork.
kanban_workerand spawned-Hermes-process prompt extensions are not in this note — they live in the Kanban worker-lane docs and are out of scope here.
Relation
2026-10-11-hermes-kanban-multi-agent-collab
Sources
1 https://hermes-agent.nousresearch.com/docs/user-guide/features/memory2 https://hermes-agent.nousresearch.com/docs/developer-guide/session-storage3 https://hermes-agent.nousresearch.com/docs/user-guide/features/context-files4 https://hermes-agent.nousresearch.com/docs/developer-guide/prompt-assembly5 https://hermes-agent.nousresearch.com/docs/developer-guide/context-compression-and-caching6 https://hermes-agent.nousresearch.com/docs/guides/use-soul-with-hermes7 https://hermes-agent.nousresearch.com/docs/guides/delegation-patterns8 https://hermes-agent.nousresearch.com/docs/user-guide/features/skills9 https://hermes-agent.nousresearch.com/docs/user-guide/features/curator10 https://hermes-agent.nousresearch.com/docs/developer-guide/creating-skills11 https://hermes-agent.nousresearch.com/docs/user-guide/features/context-references12 https://hermes-agent.nousresearch.com/docs/developer-guide/agent-loop
Hermes multi-tenant hosting: profiles, routing, and isolation
Hermes Kanban as a multi-agent collaboration plane — and Tam's vault registration pipeline
Summary. A verified live system study of the two coordination halves Young asked about: (1) Hermes Kanban — a durable SQLite-backed task board acting as the fleet's multi-agent dispatch lane; (2) Tam's vault registration pipeline — the laptop-mirror → LAB-main sync that turns research work into durable file artifacts. How each works, what Hermes docs advise, what today's live telemetry shows, where our two lanes currently sit (one healthy, one deliberately blocked), and what to do about it. Every number below came from live tool reads at 2026-10-11 ~18:58 AEDT; every Hermes claim is cited against the official docs, fetched fresh.

