Hermes: Mnemosyne long-term memory
1. What? — Definition and context
Section titled “1. What? — Definition and context”An agent that forgets everything between two conversations is just a chatbot with tools. What distinguishes Hermes from a one-off LLM call is that it accumulates: what is said on Monday is still available on Thursday.
Mnemosyne is the external memory provider that delivers this persistence — a local SQLite database with hybrid vector + FTS5 search and background capture on every turn.
What Mnemosyne replaces
Section titled “What Mnemosyne replaces”Hermes’ native memory is a MEMORY.md file re-injected into the system prompt. Simple and readable, but it plateaus quickly.
Native MEMORY.md | Mnemosyne | |
|---|---|---|
| Storage | A Markdown file | SQLite database |
| Search | None — everything is re-injected | Hybrid: vector + FTS5 |
| Budget | Character cap in the prompt | Selective recall driven by the query |
| Capture | Explicit write | Background task on every turn |
| Structure | Free text | Episodes, temporal triples, graph |
The native file is not removed for all that: it stays in place and becomes the active memory again if the external provider is disabled.
Active configuration
Section titled “Active configuration”memory: memory_enabled: true user_profile_enabled: true memory_char_limit: 2200 user_char_limit: 1375 provider: mnemosyne nudge_interval: 10 flush_min_turns: 6Two distinct budgets: memory_char_limit for what the agent has retained, user_char_limit for the user profile it builds up across exchanges.
2. Why? — Stakes and motivations
Section titled “2. Why? — Stakes and motivations”Why wrapper mode rather than a custom image?
Section titled “Why wrapper mode rather than a custom image?”This is the structuring decision of the installation. Three routes were possible:
| Route | Cost | Problem |
|---|---|---|
| Custom image | A Dockerfile extending the upstream image | Breaks the DIUN flow: no more automatic detection of upstream updates, manual rebuild on every version |
Patching /opt/hermes | Modifying the application tree inside the container | Overwritten on every image update |
| Wrapper mode | Side venv + plugin, entirely under /opt/data | Survives recreates and image updates |
Wrapper mode wins because /opt/data is a bind mount: everything living there is outside the image lifecycle. The container stays strictly the upstream image, DIUN keeps detecting new versions, and there is nothing to rebuild.
Why local-first?
Section titled “Why local-first?”Capture runs on every turn, over everything passing through the conversation: meeting notes, technical decisions, information about contacts. Sending that stream to an external vectorisation service would amount to continuously exporting the content of the exchanges.
Mnemosyne computes its embeddings locally and stores everything in a SQLite file on the data volume. No conversation data leaves the VPS to be indexed.
3. How? — Technical implementation
Section titled “3. How? — Technical implementation”Where everything lives
Section titled “Where everything lives”| Item | Path |
|---|---|
Side venv (mnemosyne-hermes → mnemosyne-memory[embeddings]) | /opt/data/.mnemosyne/venv |
| Plugin shim + manifest (discovery by Hermes) | /opt/data/plugins/mnemosyne/ |
| Bundled skill | /opt/data/skills/memory/mnemosyne-memory-override/ |
| SQLite database | /opt/data/mnemosyne/data/mnemosyne.db |
Activation is a single line: memory.provider: mnemosyne in the config file.
The exposed tools
Section titled “The exposed tools”The plugin declares 20 tools and 3 hooks (pre_llm_call, on_session_start, post_tool_call):
| Family | Tools |
|---|---|
| Memory | mnemosyne_remember, mnemosyne_recall, mnemosyne_update, mnemosyne_forget, mnemosyne_invalidate |
| Graph and triples | mnemosyne_triple_add, mnemosyne_triple_query, mnemosyne_graph_query, mnemosyne_graph_link |
| Scratchpad | mnemosyne_scratchpad_write, mnemosyne_scratchpad_read, mnemosyne_scratchpad_clear |
| Consolidation | mnemosyne_sleep |
| Transfer | mnemosyne_export, mnemosyne_import, mnemosyne_sync_push, mnemosyne_sync_pull, mnemosyne_sync_status |
| Diagnostics | mnemosyne_stats, mnemosyne_diagnose |
The hooks do the invisible work: on_session_start loads the relevant context, pre_llm_call injects the recall into the prompt, post_tool_call captures what deserves keeping.
Operations
Section titled “Operations”# Is the provider actually active?docker exec hermes hermes memory status # → Provider: mnemosyne, available
# Database statisticsdocker exec --user hermes -e HOME=/opt/data -e HERMES_HOME=/opt/data hermes \ /opt/data/.mnemosyne/venv/bin/mnemosyne stats
# Updatedocker exec --user hermes -e HOME=/opt/data hermes \ /opt/data/.mnemosyne/venv/bin/pip install --no-cache-dir -U mnemosyne-hermesdocker compose -f ai-stack/docker-compose.yaml restart hermesBackup
Section titled “Backup”The database goes into the daily backup. The venv and the fastembed model cache are excluded: they are heavy and reinstall in one command.
A consequence worth knowing for a restore: the database comes back as-is, but the venv has to be recreated before the provider becomes available again.
4. What if? — Outlook and limits
Section titled “4. What if? — Outlook and limits”Current limits
Section titled “Current limits”| Limit | Impact | Mitigation |
|---|---|---|
| Memory tied to the container | A second user would share the same memory and the same profile | One container per user rather than a widened allowlist |
| Consolidation without an LLM | Episode grouping stays mechanical | MNEMOSYNE_HOST_LLM_ENABLED=true, at the cost of quota |
| Opaque content | The SQLite database is not readable in Obsidian | Export as markdown notes, planned |
| Wrapper fragile to a Python bump | Silent failure after an image update | Check hermes memory status after every update |
| No memory shared with the workstation | What Hermes knows, the local assistant does not | Bidirectional sync, planned |
Evolution scenarios
Section titled “Evolution scenarios”If memory has to become readable:
- Export memories as markdown notes into
vps-vault, with provenance frontmatter. - The point goes beyond reading: memory versioned in Git becomes auditable and correctable by hand.
- The
mnemosyne-operationsskill already covers the governance of that export.
If memory has to be shared between the agent and the workstation:
- The
mnemosyne_sync_push/mnemosyne_sync_pulltools already exist on the plugin side. - What remains is choosing the source of truth on conflict, and deciding whether client-side encryption is needed.
If volume becomes a problem:
mnemosyne_invalidateandmnemosyne_forgetalready allow targeted pruning.- A regular consolidation pass compresses better than brutal deletion.
Related pages
Section titled “Related pages”Hermes
Section titled “Hermes”- Hermes Agent — The deployment and its security model
- Plugins — Mnemosyne is one of the four active plugins
- Skills —
mnemosyne-operations, the memory governance procedure
Infrastructure
Section titled “Infrastructure”- Database backup — The database is backed up, the venv is not
- AI Stack — Qdrant, the infrastructure’s other vector database
Reference
Section titled “Reference”- Glossary — Long-term memory, Embeddings, Vector Database