Last updated: 2026-09-27

How Hermes Memory Works — MEMORY.md, USER.md & Session Search

Hermes memory is deliberately small. Two files hold what the agent should always know: MEMORY.md, its own notes, and USER.md, what it knows about you. Both are injected into every new session. Everything else it has discussed with you stays searchable in a local session database. This guide explains how the pieces fit together, why an agent sometimes "forgets", and how to control what it saves.

This guide was rewritten on 2026-09-27

The previous version described "episodic, semantic and procedural" memory stores, a PostgreSQL backend, vector-embedding settings and commands such as hermes memory facts list and hermes memory export. None of that exists in Hermes. What follows is taken from the official memory documentation.

The two memory files

FileWhat it holdsLimit
MEMORY.mdThe agent's own notes: your environment, project conventions, lessons learned2,200 characters (~800 tokens)
USER.mdYour profile: preferences, communication style, expectations1,375 characters (~500 tokens)

Both live in ~/.hermes/memories/. On another profile they live in ~/.hermes/profiles/<name>/memories/, because memory is per profile. The agent edits them with its memory tool using three actions: add, replace and remove. There's no "read" action; the contents are already in its prompt.

Memory never compacts itself. When a write would go over the limit, the tool returns an error listing the current entries, and the agent has to merge or remove entries in the same turn before retrying. Good entries are dense and specific, such as "Project at ~/code/api: Rust, Axum + SQLx, deploys via GitHub Actions". Vague ones like "user likes code" waste the budget.

Entries are scanned before they're accepted. Anything that looks like prompt injection, credential exfiltration or an SSH backdoor, or that contains invisible Unicode, is blocked, because memory is injected straight into the system prompt.

Why a fact saved today appears tomorrow: the frozen snapshot

Memory is loaded into the system prompt once, at session start, and doesn't change mid-session, which keeps the prompt cache warm. A new entry is written to disk straight away, but the running session won't see it. The next session will.

This is why session boundaries matter. On Telegram or Discord, a chat is one continuous session that survives restarts and reboots, so if you never reset it, new memories never load and the conversation keeps getting longer and more expensive. Run /new at natural breaks: when a task is finished, the topic changes or a new day starts. On the CLI, every invocation is already a new session.

Session search: everything else

Every CLI and messaging session is stored in ~/.hermes/state.db, a SQLite database with full-text search. The agent can find something from weeks ago with its session_search tool and scroll through the surrounding messages, and it returns the actual messages, not an AI summary. Searching costs no model calls.

Memory filesSession search
Size~1,300 tokens totalEvery session you've had
CostPaid in every promptFree; queried only when needed
Use forFacts that should always be in context"Did we discuss X last week?"

Browse sessions yourself with hermes sessions list.

"I told it to remember, and the next session it forgot"

Check these in order. The first one explains most cases.

  1. Did the write actually happen? "I've added that to my memory" is just text unless the model called the tool. Look:
    cat ~/.hermes/memories/MEMORY.md
    cat ~/.hermes/memories/USER.md
    Small local models (roughly under 30B) and models with weak tool calling often claim saves they never made. Ask explicitly: "use the memory tool to save …". Or use a stronger model for setup. Once the entries exist, a smaller model reads them fine.
  2. Is it waiting for approval? With write_approval: true, writes from outside the interactive CLI are held back. Run /memory pending.
  3. Are you on the same profile? A CLI session on the default profile and a Telegram bot on a work profile don't share memory. Check with hermes profile list.
  4. Is memory switched on? memory.memory_enabled: false, or memory listed under agent.disabled_toolsets, removes the tool entirely.
  5. Did you start a new session? See the frozen snapshot above.

For a path or setting that a recurring job needs every time, a skill is often a better home than memory. A skill loads only when it's relevant and doesn't use up the 2,200-character budget.

Controlling what gets saved

By default the agent saves freely, both during a turn and in a background review that runs after turns to capture memories and skills. To approve saves first:

# ~/.hermes/config.yaml
memory:
  memory_enabled: true
  user_profile_enabled: true
  memory_char_limit: 2200
  user_char_limit: 1375
  write_approval: true     # default false

With approval on, the interactive CLI asks you inline. Everywhere else, including the background review, writes are staged:

/memory pending          # list staged writes (automatic ones are tagged [auto])
/memory approve <id>     # or: all
/memory reject <id>      # or: all
/memory approval on      # turn the gate on or off and save it

This is the fix for "the agent saved a wrong assumption about me". Since v0.21.0, the agent's own instruction files (AGENTS.md, skills and the memory stores) also always need write approval, so a prompt-injected agent can't quietly rewrite its standing orders.

Cheaper background review. The review runs on your main model by default. On an expensive model you can point it elsewhere. The docs report roughly 3–5× lower cost with the same memory capture in testing:

auxiliary:
  background_review:
    provider: openrouter
    model: google/gemini-3-flash-preview   # "auto" (default) = your main model

To turn built-in memory off completely, set both memory_enabled and user_profile_enabled to false.

Reviewing and pruning what it learned: /journey

hermes journey (or /journey in a session) shows a timeline of every skill and memory entry Hermes has picked up. The desktop app shows the same data as a star map. You can correct it from there:

hermes journey list              # node ids
hermes journey edit <node>       # open a skill or memory entry in $EDITOR
hermes journey delete <node>     # skills are archived (restorable); memory entries are removed

External memory providers

For more than two small files, such as knowledge graphs, semantic search or automatic fact extraction, Hermes ships seven memory provider plugins: Honcho, OpenViking, Mem0, Holographic, RetainDB, ByteRover and Supermemory. Hindsight is available from the plugin catalog. Only one can be active at a time, and it runs alongside the built-in files rather than replacing them.

hermes memory setup    # pick and configure a provider
hermes memory status   # what's active
hermes memory off      # back to built-in only

An external provider is also the documented way to give two agents shared memory. Never point two Hermes processes at the same home directory: both write automatically, and each would load the other's entries as its own.

Backing up memory

hermes backup                      # zip of ~/.hermes: config, memories, skills, sessions (state.db)
hermes import <backup.zip>         # restore it

The zip includes .env, so it holds your API keys; store it like a password. Don't delete state.db to "fix" a slow or broken install. If Hermes 0.21.0 or 0.21.1 reported it corrupt, see Troubleshooting; those versions could misreport a healthy database.

Official sources

Checked against the Hermes Agent documentation (v0.21.5) on 2026-09-27. If anything here disagrees with these pages, trust the vendor docs.

← Back to Hermes hub · See also: Long-Running Tasks & Scheduling · Quick Start

📬 Weekly Digest — In Your Inbox

One email a week: top news, releases, and our deepest new guide. No spam. Same content via RSS if you prefer.