website/docs/user-guide/features/memory.md
Hermes Agent has bounded, curated memory that persists across sessions. This lets it remember your preferences, your projects, your environment, and things it has learned.
Two files make up the agent's memory:
| File | Purpose | Char Limit |
|---|---|---|
| MEMORY.md | Agent's personal notes — environment facts, conventions, things learned | 2,200 chars (~800 tokens) |
| USER.md | User profile — your preferences, communication style, expectations | 1,375 chars (~500 tokens) |
Both are stored in ~/.hermes/memories/ and are injected into the system prompt as a frozen snapshot at session start. The agent manages its own memory via the memory tool — it can add, replace, or remove entries.
:::info Character limits keep memory focused. When memory is full, the agent consolidates or replaces entries to make room for new information. :::
At the start of every session, memory entries are loaded from disk and rendered into the system prompt as a frozen block:
══════════════════════════════════════════════
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
§
User prefers concise responses, dislikes verbose explanations
The format includes:
§ (section sign) delimitersFrozen snapshot pattern: The system prompt injection is captured once at session start and never changes mid-session. This is intentional — it preserves the LLM's prefix cache for performance. When the agent adds/removes memory entries during a session, the changes are persisted to disk immediately but won't appear in the system prompt until the next session starts. Tool responses always show the live state.
The agent uses the memory tool with these actions:
old_text)old_text)There is no read action — memory content is automatically injected into the system prompt at session start. The agent sees its memories as part of its conversation context.
The replace and remove actions use short unique substring matching — you don't need the full entry text. The old_text parameter just needs to be a unique substring that identifies exactly one entry:
# If memory contains "User prefers dark mode in all editors"
memory(action="replace", target="memory",
old_text="dark mode",
content="User prefers light mode in VS Code, dark mode in terminal")
If the substring matches multiple entries, an error is returned asking for a more specific match.
memory — Agent's Personal NotesFor information the agent needs to remember about the environment, workflows, and lessons learned:
user — User ProfileFor information about the user's identity, preferences, and communication style:
The agent saves automatically — you don't need to ask. It saves when it learns:
usermemorysudo for Docker commands, user is in docker group" → save to memorymemorymemorymemoryMemory has strict character limits to keep system prompts bounded:
| Store | Limit | Typical entries |
|---|---|---|
| memory | 2,200 chars | 8-15 entries |
| user | 1,375 chars | 5-10 entries |
When you try to add an entry that would exceed the limit, the tool returns an error:
{
"success": false,
"error": "Memory at 2,100/2,200 chars. Adding this entry (250 chars) would exceed the limit. Consolidate now: use 'replace' to merge overlapping entries into shorter ones or 'remove' stale or less important entries (see current_entries below), then retry this add — all in this turn.",
"current_entries": ["..."],
"usage": "2,100/2,200"
}
The agent should then:
replace to merge related entries into shorter versionsadd the new entryBest practice: When memory is above 80% capacity (visible in the system prompt header), consolidate entries before adding new ones. For example, merge three separate "project uses X" entries into one comprehensive project description entry.
Compact, information-dense entries work best:
# Good: Packs multiple related facts
User runs macOS 14 Sonoma, uses Homebrew, has Docker Desktop and Podman. Shell: zsh with oh-my-zsh. Editor: VS Code with Vim keybindings.
# Good: Specific, actionable convention
Project ~/code/api uses Go 1.22, sqlc for DB queries, chi router. Run tests with 'make test'. CI via GitHub Actions.
# Good: Lesson learned with context
The staging server (10.0.1.50) needs SSH port 2222, not 22. Key is at ~/.ssh/staging_ed25519.
# Bad: Too vague
User has a project.
# Bad: Too verbose
On January 5th, 2026, the user asked me to look at their project which is
located at ~/code/api. I discovered it uses Go version 1.22 and...
The memory system automatically rejects exact duplicate entries. If you try to add content that already exists, it returns success with a "no duplicate added" message.
Memory entries are scanned for injection and exfiltration patterns before being accepted, since they're injected into the system prompt. Content matching threat patterns (prompt injection, credential exfiltration, SSH backdoors) or containing invisible Unicode characters is blocked.
Beyond MEMORY.md and USER.md, the agent can search its past conversations using the session_search tool:
~/.hermes/state.db) with FTS5 full-text searchhermes sessions list # Browse past sessions
See Session Search Tool for the three calling shapes (discovery / scroll / browse) and the response format.
| Feature | Persistent Memory | Session Search |
|---|---|---|
| Capacity | ~1,300 tokens total | Unlimited (all sessions) |
| Speed | Instant (in system prompt) | ~20ms FTS5 query, ~1ms scroll |
| Cost | Token cost in every prompt | Free — no LLM calls |
| Use case | Key facts always available | Finding specific past conversations |
| Management | Manually curated by agent | Automatic — all sessions stored |
| Token cost | Fixed per session (~1,300 tokens) | On-demand (searched when needed) |
Memory is for critical facts that should always be in context. Session search is for "did we discuss X last week?" queries where the agent needs to recall specifics from past conversations.
# In ~/.hermes/config.yaml
memory:
memory_enabled: true
user_profile_enabled: true
memory_char_limit: 2200 # ~800 tokens
user_char_limit: 1375 # ~500 tokens
For deeper, persistent memory that goes beyond MEMORY.md and USER.md, Hermes ships with 8 external memory provider plugins — including Honcho, OpenViking, Mem0, Hindsight, Holographic, RetainDB, ByteRover, and Supermemory.
External providers run alongside built-in memory (never replacing it) and add capabilities like knowledge graphs, semantic search, automatic fact extraction, and cross-session user modeling.
hermes memory setup # pick a provider and configure it
hermes memory status # check what's active
See the Memory Providers guide for full details on each provider, setup instructions, and comparison.