🤖HermesBlog
Hermes Feature Guides · Part 48/9/2026

Why Hermes Remembers (and You Don't Have To)

Persistent Memory — AI's Long-Term Memory — easy-to-understand guide based on official docs

Persistent memory: two cheat sheets

Why Hermes Remembers (and You Don’t Have To)

Ever told an assistant something once, then had to repeat it every single time? Frustrating, right? Hermes Agent fixes that with persistent memory. It’s like giving your agent a tiny notebook it actually reads before every conversation.

Here’s the kicker: Hermes doesn’t try to remember everything. It keeps a bounded, curated set of notes. Think of it as a sticky note, not a filing cabinet. This keeps things fast, focused, and—most importantly—accurate.

The Two Files Behind the Magic

Hermes uses two simple text files to store what it knows. They live in ~/.hermes/memories/:

File What It Holds Size Limit
MEMORY.md Agent’s personal notes: environment facts, project conventions, lessons learned 2,200 characters (~800 tokens)
USER.md Your profile: preferences, communication style, expectations 1,375 characters (~500 tokens)

At the start of every session, Hermes reads these files and injects them into its system prompt as a frozen snapshot. It’s like reading its notebook before starting work. The snapshot doesn’t change mid-session—that’s intentional, because it keeps things fast and predictable.

Memory Needs Session Boundaries

The whole memory system is built around the moment a session ends: MEMORY.md and USER.md carry the essentials into the next session, and session_search fills the gaps once the old context is gone. Inside a single session none of that machinery has a reason to run—everything important is still in the live context, so the agent rarely consults session_search and mostly compacts memory entries instead of curating them.

This matters on messaging platforms (Telegram, Discord, etc.), where a chat is deliberately one continuous session that survives restarts, gateway crashes, and machine reboots. Shutting the machine down overnight does not end the session—the next message picks it up exactly where it left off. If you never reset, a chat can run for weeks as a single session: convenient, but it grows expensive (compaction runs repeatedly over an ever-longer history) and the learning loop of forget → recall from memory → search past sessions almost never gets to fire. Fresh memory entries also stay invisible to the running session because of the frozen snapshot above.

Practice: run /new at natural boundaries—a finished task, a change of topic, the start of a day. Each boundary is when memory pays off: the agent re-reads the updated MEMORY.md/USER.md snapshot, starts from a cheap short context, and reaches for session_search when it actually needs history. On the CLI this mostly takes care of itself (every invocation is a new session); on gateways the boundary is yours to create.

Troubleshooting: “I Told It to Remember, and the Next Session It Forgot”

The most common report looks like this: you tell the agent where something lives (an Obsidian vault, a project directory, a server), it answers “Done, I’ll remember that”, and a fresh session has no idea what you mean. Work through these in order—the first one explains the large majority of cases.

  1. Check whether the write actually happened. Memory only persists when the model calls the memory tool; a sentence like “I’ve added that to my memory” is just text. Open the file and look for the entry:

    cat ~/.hermes/memories/MEMORY.md
    cat ~/.hermes/memories/USER.md

    If the fact isn’t there, the model claimed a save it never made. Small local models (roughly under 30B parameters) and models with weak tool-calling do this often—they produce the confirmation without the tool call. Ask explicitly (“use the memory tool to save the vault path /srv/vault”) and confirm the entry landed in the file. If it keeps happening, the fix is a stronger model for setup, not more instructions; once the entries exist, a smaller model reads them fine because they arrive in the system prompt.

  2. Check the write wasn’t staged. With write_approval: true, writes outside the interactive CLI are held for review and never reach the file until approved—run /memory pending and /memory approve all.

  3. Check you are reading the same memory you wrote. Memory is per profile: hermes -p work (or work chat / work gateway start) reads ~/.hermes/profiles/work/memories/, not ~/.hermes/memories/. A CLI session in the default profile and a Telegram bot on another profile do not share notes. hermes profile list shows what exists.

  4. Check memory is enabled. memory.memory_enabled: false (or memory under agent.disabled_toolsets) removes the tool entirely—the model cannot save anything, whatever it says.

  5. Remember the snapshot is frozen at session start. A fact saved in the current session is visible to the next session, not to another session that was already running. Start a new session (/new, or a fresh CLI invocation) after the write.

Two things that do not make the agent remember: variables in .env (those are credentials and settings, not memory) and facts mentioned in passing without asking for them to be saved. For a location the agent needs on every run of a recurring task, a skill is often the better home than a memory entry—it loads only when relevant and does not compete for the 2,200-character budget.

How the Agent Manages Its Memory

Hermes doesn’t just store notes; it actively curates them using the memory tool. There are three actions:

  • add — Write a new memory entry
  • patch — Replace one span inside an existing entry and keep the rest (old_text is the span, content its replacement)
  • remove — Delete an entry that’s no longer relevant (uses substring matching via old_text)

There’s no read action—memory is injected into the system prompt automatically at session start, so the agent already sees it as part of the conversation.

Here’s the clever part: patch and remove use short, unique substrings. You don’t need to quote the whole entry. Just give a snippet that uniquely identifies it.

Every tool call requires a top-level target: "memory" for agent notes or "user" for the user profile. A batch uses that one target for every operation:

{"target": "user", "operations": [{"action": "add", "content": "User prefers metric units"}]}

Missing or null targets, and a target inside an operation that differs from the top-level one, return an error before writing or staging approval. Correct the payload and retry; use separate calls to update both stores.

# If memory contains "User prefers dark mode in all editors"
memory(action="patch", target="memory",
       old_text="dark mode",
       content="light mode in VS Code, dark mode in terminal")

If your substring matches multiple entries, Hermes will ask you to be more specific. No accidental deletions.

What Goes in Each Notebook

memory — The Agent’s Personal Notes

This is for facts about the environment and workflows:

  • OS, tools, and project structure
  • Project conventions and config details
  • Tool quirks and workarounds discovered
  • Completed task diary entries
  • Skills and techniques that worked

user — Your Profile

This is all about you:

  • Name, role, timezone
  • Communication preferences (concise vs. detailed)
  • Pet peeves and things to avoid
  • Workflow habits
  • Technical skill level

What Hermes Saves (and What It Skips)

Hermes saves proactively—you don’t have to ask. It remembers:

  • Your preferences: “I prefer TypeScript over JavaScript” → saved to user
  • Environment facts: “This server runs Debian 12 with PostgreSQL 16” → saved to memory
  • Corrections: “Don’t use sudo for Docker commands” → saved to memory
  • Conventions: “Project uses tabs, 120-char line width” → saved to memory
  • Completed work: “Migrated database from MySQL to PostgreSQL on 2026-01-15” → saved to memory
  • Explicit requests: “Remember that my API key rotation happens monthly” → saved to memory

But it’s smart about what not to save:

  • Trivial or vague info (“User asked about Python”)
  • Facts it can easily look up (like Python version docs)
  • Huge data dumps (code blocks, log files)
  • Session-specific ephemera (temporary file paths)
  • Anything already in context files like SOUL.md or AGENTS.md

When Memory Gets Full

Memory limits are strict, and there’s no silent auto-compaction. If a write would exceed the limit, the memory tool returns an error that tells the agent exactly how many characters it needs to free:

{
  "success": false,
  "error": "Memory at 2,100/2,200 chars; adding this entry (250 chars) would exceed the limit by 153 chars. Retry as ONE 'operations' batch that removes or shortens (replace) stale entries from current_entries below to free at least 153 chars AND adds this entry — the limit is checked only on the batch result.",
  "current_entries": ["..."],
  "usage": "2,100/2,200"
}

The agent then reissues one operations batch that frees at least the stated number of characters (removes, or replaces with shorter versions) and adds the new entry; the limit is checked only on the batch’s final result. A replace/remove whose old_text matches no entry fails the same way, with the entries it most resembles under closest_entries.

One important note: patch is also bound by the limit. A patch that lengthens an entry can still overflow, so the new text must be shortened (or another entry removed) to fit.

A good habit: once memory passes about 80% full (the system prompt header shows the percentage), consolidate before adding. Merging a few small “project uses X” entries into one richer entry usually frees plenty of room.

A Word of Caution

Don’t point two agent processes at the same Hermes home directory. Memory writes are automatic and load back at session start. Two writers sharing one home will compound each other’s entries into a mess neither of you authored. Memory is scoped per profile by design—give a second agent its own profile. If they need shared memory, use an external memory provider instead.

Going Beyond the Two Files

For deeper, persistent memory that goes beyond MEMORY.md and USER.md, Hermes ships with 2 external memory provider plugins—RetainDB and ByteRover—and more, such as Honcho, Hindsight, Supermemory, Mem0, OpenViking and Holographic, are available from the plugin catalog via hermes plugins install <name>.

External providers return their full prefetched context by default, up to a safety ceiling of 10× hooks.output_spill.max_chars (at least 100,000 characters); recall above that still spills so a runaway provider can’t overflow the context window. Setting memory.prefetch_spill_enabled: true opts the active profile into replacing oversized recall with a head/tail preview and a file path. This can reduce replayed context, but the relevance-ranked middle is no longer immediately visible to the model—prefer your provider’s own recall budget when available. The opt-in uses the shared hooks.output_spill threshold, preview lengths, and directory; hooks.output_spill.enabled: false still disables it. Normal plugin hooks continue to spill by default, independently of the memory opt-in. Settings are captured at provider registration, so restart Hermes after changing them.

The Takeaway

Hermes’s memory system is designed to be focused, curated, and reliable. It remembers what matters, forgets what doesn’t, and keeps you in control. No more repeating yourself—just tell Hermes once, and it’ll remember.

📖 Official Docs

This article is based on the official Hermes Agent documentation:Official docs › user-guide/features/memory