Memory Manager
What it is
The component that prefetches, synchronizes, and registers tools for optional external memory providers; the built-in memory files remain separate.
In plain terms
Picture a research lab that keeps its own logbook, written into directly by whoever’s on shift, but the lab has, at most, one partner lab it shares results with — a runner photocopies each new logbook page and carries it over there, never splitting the same delivery between two competing partners at once. MemoryManager plays that runner’s role inside Hermes: the built-in notebook is written to directly by the memory tool, and MemoryManager plugs in, at most, one outside memory service — asking it for anything relevant before each turn and forwarding it a copy of whatever the notebook just saved.
Why it matters
MemoryManager coordinates optional external provider behavior: prefetch before a turn, background sync after it, mirroring committed memory-tool writes, and registering provider tools without letting them shadow reserved core names. It does not own the built-in MEMORY.md/USER.md store and does not promise to deduplicate that store. The built-in memory tool remains responsible for those files even when an external provider is enabled.
How it works
MemoryManager stitches together whatever it’s given (agent/memory_manager.py) — but it holds at most one provider, an external plugin; the built-in MEMORY.md/USER.md store lives outside it, read and written directly by the memory tool. Before each turn, prefetch_all() asks the registered provider for relevant context; once a turn finishes, sync_all() hands the completed exchange to a single background worker thread, so a slow or stuck provider — one was observed hanging nearly five minutes — can never freeze the conversation. Whenever the built-in memory tool commits a write, the agent loop separately notifies MemoryManager, which mirrors that entry out to whichever external provider is active. Tool schemas from every provider get merged into one list, with built-in tool names such as clarify always winning over anything a provider tries to register under the same name, and a second external provider is rejected outright with a logged warning rather than silently stacking.
A concrete example
A user runs Hermes with mem0 configured as the external memory provider. Behind the scenes, MemoryManager does three things:
- Before each turn, it asks mem0 — the one provider it manages — for anything relevant to the incoming message; the built-in notebook’s own contribution is separate, already baked into the system prompt at session start.
- Once the assistant replies, it queues the finished exchange to a background thread, so mem0’s own write never delays the next message.
- If the user later tries to also enable Honcho as a second external provider, MemoryManager logs a rejection and keeps mem0 as the only external backend.
How it connects
This note belongs to the Memory family. Its closest neighboring concepts are: Memory, Memory Provider, Agent Runtime, Personal OS.
Source evidence
vendor/hermes-agent/agent/memory_manager.py:505-515#MemoryManager.prefetch_all— Verified Source Map evidence for MemoryManager. MemoryManager callsprefetchon each registered provider in order, skips empty results, isolates individual provider failures, and merges the remaining text.
Workflows
- No first-pass workflow mapping yet; this concept still appears in the vault graph through articles and source evidence.
Related articles
- No article currently mentions this concept by name/alias often enough to qualify (see mention-mining policy).
