MMNTM logo
Technical Deep Dive

How Hermes Agent Implements Memory

A walkthrough of the 3,575-character bet: two capped files, a frozen snapshot pattern that preserves the prefix cache, and a memory tool that forces curation.

Greg Salwitz
11 min read
#Hermes Agent#Agent Memory#Architecture#Nous Research#Open Source

The Bet

Hermes Agent's entire persistent memory is 3,575 characters. Not 3,575 files, not 3,575 entries — 3,575 characters, total, across two Markdown files. Under 1,300 tokens.

This is not a limitation the team plans to lift. It's the thesis. OpenClaw — the accumulation-theory framework — gives its agents an uncapped filesystem and a vector index, and inherits the context cliff as its failure mode. Hermes inverts the bet: if memory is scarce, the agent (and its human) must decide what actually matters. Curation is the feature.

"Get rid of irrelevant details so that the essential things and the relationships between them stand out." — Ray Dalio, Principles (p. 767)

At 215,000 GitHub stars as of July 2026, this is the most widely deployed curated-memory system in existence. It's organized as three tiers: a bounded core that's always in the prompt, unlimited session history behind a search tool, and an optional external provider layered on top. Here's how each works.


Two Files, Hard Caps

Persistent memory lives in ~/.hermes/memories/ as two files with independent character budgets:

Memory Files

FeatureCap~TokensStores
MEMORY.md2,200 chars~800Environment facts, conventions, learned lessons
USER.md1,375 chars~500Preferences, communication style, identity

Entries are separated by section-sign (§) delimiters, and the system prompt shows the agent its own budget — the agent always knows how full its memory is, the same way you know your fuel gauge:

══════════════════════════════════════════════
MEMORY (your personal notes) [67% — 1,474/2,200 chars]
══════════════════════════════════════════════
User's project is a Rust web service at ~/code/myapi using Axum + SQLx
§
This machine runs Ubuntu 22.04, has Docker and Podman installed

The caps are configurable but the defaults are the design:

memory:
  memory_enabled: true
  user_profile_enabled: true
  memory_char_limit: 2200
  user_char_limit: 1375
  write_approval: false

Set write_approval: true and every memory write requires explicit human confirmation — a control OpenClaw's continuous-append model has no equivalent for.


The Frozen Snapshot Preserves the Prefix Cache

The most consequential design decision isn't the size cap — it's the freeze. Both files are captured once at session start, injected into the system prompt, and never changed mid-session. Writes persist to disk immediately, but the agent doesn't see them until the next session.

The reason is economic. LLM providers cache the static prefix of a prompt; every token that never changes is a token you don't pay full price to reprocess on each turn. A memory block that mutates mid-session invalidates the cache for everything after it — every turn, for the rest of the session.

This is the same constraint Claude Code engineers around: static content first, dynamic content last, and alerts on cache hit rate. Hermes bakes the discipline into the architecture — memory physically cannot invalidate the prefix because it cannot change mid-session.

The trade-off is real: an agent that learns something at turn 3 can't consult that memory at turn 40. It has to hold it in context — knowledge in the mind, not knowledge in the world — until the session ends. For short sessions this is invisible. For marathon sessions it's the architecture telling you to start a new session.


The Memory Tool Forces Curation

The agent manages its memory through a single tool with three actions:

memory(action: "add", text: "...")
memory(action: "replace", old_text: "...", text: "...")
memory(action: "remove", old_text: "...")

Three details reveal the philosophy:

There is no read action. Memory is always in context via the system prompt, so a read would be redundant. The tool surface is write-only.

Edits use substring matching. replace and remove take an old_text fragment rather than requiring exact full-entry text — surgical edits without brittle string equality. Exact duplicate entries are rejected automatically.

Writes are scanned before acceptance. Every entry passes screening for prompt-injection patterns, credential exfiltration, and invisible Unicode before it lands. A poisoned webpage that convinces the agent to "remember" a malicious instruction still has to get that instruction past the scanner — a defense layer that matters given that persistent memory is a prompt-injection persistence vector.

And the system does not auto-compact. When a write would exceed the cap, the tool errors and the agent must consolidate — merge entries, drop stale ones — in the same turn before retrying. The cap is selection pressure: entries compete for space, and low-signal ones get pruned to make room. Recommended practice is consolidating at 80% capacity, before the wall arrives.

This is the consolidation wall from The Memory Model Is Your Failure Mode: when memory fills, the agent stops absorbing until curation happens. The failure is visible and bounded — the opposite trade from OpenClaw's silent context cliff.


session_search Is the Escape Valve

Bounded persistent memory raises the obvious objection: what about everything else? Hermes' answer is that history doesn't belong in memory — it belongs in a database you can search.

Every conversation is stored in SQLite at ~/.hermes/state.db, indexed with FTS5 full-text search. The session_search tool queries it in roughly 20 milliseconds and returns actual stored messages — not summaries, not embeddings-adjacent paraphrases. Scrolling context around a hit takes about a millisecond.

Contrast with OpenClaw's retrieval stack — 70/30 vector/BM25 hybrid search with 4× over-fetch across an uncapped memory corpus, covered in How OpenClaw Implements Agent Memory. OpenClaw needs semantic retrieval because accumulation guarantees the corpus outgrows keyword search. Hermes gets away with plain FTS5 because the searchable corpus is raw session history, and the distilled knowledge already lives in the frozen 3,575 characters.

The division of labor: persistent memory answers "what do I know," session search answers "what happened."


A Background Review Curates After Every Turn

Curation would be a chore if the agent had to interrupt its work to do it. Hermes moves the work to a background review that fires after each turn, re-reading the conversation — which is warm in the prefix cache, so the re-read is cheap — and deciding whether anything qualifies as a durable fact, a correction, or a workflow lesson worth persisting.

The review follows a save/skip policy: most turns produce nothing, and that's the design. It can run on a cheaper auxiliary model (auxiliary.background_review config), and a periodic nudge (~every 300 seconds) prompts the agent to evaluate whether anything worth persisting has accumulated. Two human controls gate the loop: write_approval: true requires explicit confirmation before any background-triggered write lands, and /memory pending surfaces staged writes for review.

This resolves the obvious objection to curated memory — "who has time to be the librarian?" The answer: the agent does, between turns, on a cheap model, with the human holding a veto. Curation is automated; the decisions stay auditable.


Skills Hold the Procedures Memory Can't

A 3,575-character budget cannot hold a deployment runbook. Hermes doesn't ask it to: procedural knowledge lives in a separate skills layer (~/.hermes/skills/) — Markdown files encoding reusable procedures, loaded on demand when relevant rather than injected every turn.

The split keeps each store honest. Core memory holds compact declarative facts ("user prefers pnpm, never npm"); skills hold arbitrarily detailed procedures ("how to deploy this service, step by step"), created and improved autonomously as the agent completes tasks — the closed learning loop behind Nous Research's "the agent that grows with you" tagline. Skills are compatible with the agentskills.io open standard.


Eight External Providers When Bounded Isn't Enough

For deployments where curation genuinely can't hold everything — support agents with thousands of users, research agents with deep document context — Hermes supports one external memory provider active at a time, layered on top of the built-in tiers: Honcho (dialectic user modeling), OpenViking (self-hosted tiered knowledge hierarchy), Mem0 (server-side fact extraction), Hindsight (knowledge graph with cross-memory synthesis), Holographic (local SQLite, zero external dependencies), RetainDB (delta compression, hybrid retrieval), ByteRover (pre-compression extraction), and Supermemory (context fencing, session-end graph ingest). Setup is a single command (hermes memory setup).

With a provider active, each turn runs an auto-sync cycle: provider context is prefetched into the system prompt (non-blocking), the agent responds using all three tiers, disk writes stay invisible until next session (the prefix cache stays warm), and at session close the transcript lands in session search while the provider extracts semantics.

The architectural point: providers are additive, never substitutive. Activating Honcho means built-in memory plus session search plus Honcho — the curated core stays authoritative. OpenClaw's plugin model is the opposite: its plugins.slots.memory slot holds exactly one backend, and installing LanceDB replaces the default engine, dreaming pipeline and all. Composition versus substitution — see Hermes Agent vs OpenClaw for what that costs in practice.


Patterns Worth Stealing

Show the agent its own budget. The 67% — 1,474/2,200 chars gauge in the system prompt turns capacity into something the agent can reason about, instead of a wall it hits blind.

Freeze what you cache. If your harness relies on prefix caching, structural immutability beats behavioral discipline. Make mid-session memory mutation impossible, not discouraged.

Error, don't auto-compact. Automatic summarization silently decides what to forget. A hard error at the cap forces the deciding intelligence — agent or human — to make the call explicitly.

Scan writes to persistent stores. Memory is a persistence vector for prompt injection. Screening entries before acceptance is cheap; un-poisoning a memory file after the fact is not.

Separate "what I know" from "what happened" from "what I can do." Distilled facts in a bounded, always-loaded store; raw history in a searchable database; procedures in on-demand skill files. Most agent memory designs conflate all three and inherit the worst of each.

Make extensions additive, not substitutive. Hermes providers stack on top of built-in memory instead of replacing it. An extension that can't break the core is an extension you can adopt without an architecture review.


See also: Hermes Agent vs OpenClaw: The 2026 Head-to-Head for the full framework comparison, The Memory Model Is Your Failure Mode for the theory across Hermes, OpenClaw, and Claude Code, and Agent Memory: From Stateless to Stateful AI for the conceptual foundations.

Greg SalwitzJul 15, 2026