This looks at the default memory in two agent platforms, OpenClaw and Hermes, and at a custom system built on OpenClaw.
How to read this: if you are deciding between the two, the comparison at the end is the short version, and the plain-language summary at the top of each section carries the gist. If you run an OpenClaw gateway and want the memory system itself, the custom-system section is the detail.
Out of the box, OpenClaw persists sessions, not structured memory. If you configure nothing, direct messages share the agent's main session and each group chat gets its own. Conversation history survives within a session; there is no separate tier for durable facts, preferences, or project state, and no semantic recall across sessions.
Structured memory in OpenClaw is a plugin you install, not a default you get out of the box. Two plugins cover most of it: memory-core and memory-wiki. They supply the MEMORY.md convention, the memory_search and memory_get tools, and embedding-backed search gated by the memorySearch config key. For a new OpenClaw gateway, both are worth installing right away. So the tiered system described later is not something OpenClaw hands you. It is something you assemble on top of these building blocks.
Source: docs.openclaw.ai (session model under Getting Started; memory features absent from the default overview).
Hermes ships a more opinionated default. It keeps two files in ~/.hermes/memories/:
MEMORY.md (roughly 800 tokens) for environment facts, conventions, and learned lessons the agent writes about itself.USER.md (roughly 500 tokens) for the user profile: preferences, communication style, expectations.Both are injected into the system prompt as a frozen snapshot at session start. The agent edits them through a memory tool with add, replace, and remove actions, where replace and remove match on a unique substring instead of the full entry. Each file has a fixed character cap (2,200 for MEMORY.md, 1,375 for USER.md). Once it is full, a new entry is refused until the agent consolidates overlapping notes or removes ones it judges stale or less important; the files are never truncated automatically. Writes hit disk immediately, and the agent sees its own write in the tool's reply, but the copy of the files quoted at the top of the prompt is not re-rendered mid-session, so a new entry appears in that memory block only at the next session start. That delay is deliberate: it keeps the prompt prefix stable so the model's prefix cache is not invalidated mid-session. The agent does not lose what it just learned, since the write and the live conversation are both in its context; only the curated block waits.
Alongside the two files, session_search queries every past CLI and messaging session, stored in SQLite at ~/.hermes/state.db with FTS5 full-text search. These queries return the actual stored messages, with no summarization and no truncation. A background review loop turns repeated corrections and durable workflow lessons into compact memory entries or procedural skills, and a write-approval gate can hold those automatic saves for human review before they persist.
Source: hermes-agent.nousresearch.com/docs/user-guide/features/memory.
Hermes offers eight external memory backends, one active at a time, alongside its built-in files, configured through hermes memory setup. The deployment column decides where your data physically lives.
| Provider | What it does | Where it runs |
|---|---|---|
| Honcho | Cross-session user modeling with dialectic reasoning, semantic search, persistent conclusions | Cloud, or self-hosted |
| Mem0 | Server-side LLM fact extraction with semantic search, reranking, and deduplication | Cloud, self-hosted server, or in-process (OSS) |
| Hindsight | Long-term memory with a knowledge graph, entity resolution, and multi-strategy retrieval | Cloud, or local embedded Postgres |
| OpenViking | Filesystem-style context database (Volcengine / ByteDance) with tiered retrieval and automatic extraction | Self-hosted only (infra you control) |
| Holographic | Local SQLite fact store with FTS5, trust scoring, and Holographic Reduced Representations (no LLM, no embeddings) | Local only, no external calls |
| RetainDB | Memory API with hybrid search (vector + BM25 + rerank), seven memory types, delta compression | Cloud only |
| ByteRover | Persistent memory via the brv CLI, a hierarchical knowledge tree with tiered retrieval | Local-first, optional cloud sync |
| Supermemory | Semantic long-term memory with profile recall, explicit memory tools, and session-end conversation ingest | Cloud, or self-hosted server |
The upside of a provider is retrieval a flat file cannot do: vector similarity, a knowledge graph, automatic extraction so the agent writes less by hand. On the benchmarks the vendors cite, several of these (RetainDB, Supermemory) claim state-of-the-art recall. The cost is a dependency, and the deployment column is where that cost is paid.
A cloud provider necessarily has access to your session data. A memory backend works by receiving what the agent says and stores, so when that backend is a hosted service, your memories, and in most cases the raw conversation they are extracted from, are sent to and held on the vendor's servers. That is not a misconfiguration to avoid; it is how the service functions. It also reaches past conversation. To have the agent work from a body of documents such as contracts, business records, or a reference wiki, a cloud provider must ingest their contents before it can recall them, so those documents come to rest on the vendor's servers too. No cloud-provider setup gives the agent recall over a document while keeping the document off the provider. Of the eight, RetainDB is cloud-only, and Honcho, Mem0, and Supermemory default to a hosted service. The ones that can keep data on your own machine are Holographic (fully in-process, no external calls), OpenViking (self-hosted on infrastructure you control), and the local modes of Mem0, Hindsight, and ByteRover. For an operator whose sessions carry personal or business detail, that column is not a footnote. Picking a hosted provider means a third party holds a standing copy of what the agent knows about you.
Source: hermes-agent.nousresearch.com/docs/user-guide/features/memory-providers (descriptions and deployment). Vendor identities and benchmark claims confirmed via each provider's own project page.
This system is built on OpenClaw's memory plugins, and its shape started the same way most agent memory does: markdown files the agent reads at session start and writes to as it learns. What follows is what got added on top, and the reason each piece exists. Every component named here is actively running today in our gateway.
Memory is split across four levels by how often it needs to be in context:
memory/MEMORY-L0.md): a one-line index per topic plus a "right now" header. Loaded first, every main session.MEMORY.md): operational facts, two to three lines per topic, with a pointer to the detail.memory/topics/<name>.md, 20 files at present): full context, loaded only for the topic in play.memory/YYYY-MM-DD.md): raw session logs.The point of tiering is to keep L0 and L1 short enough to load every session without cost, while the detail sits in L2 and loads on demand. Two dedicated logs sit beside the tiers: DECISIONS.md for choices and their trade-offs, and ERRORS.md for mistakes and how each was prevented from recurring.
Search over memory is weighted by a trust tier tied to where a result came from, so a curated topic file outranks a raw daily note when they disagree. The weights in scripts/provenance_search.py: owner-curated topic files and the wiki vault at 1.0; agent-curated, session-reviewed files (MEMORY.md, USER.md, SOUL.md) at 0.9; daily notes and lower-provenance sources below that. This was added after a retrieval returned a stale value because an early raw note happened to match first.
Tiering and weighted search are useful, but they do not hold on their own. MEMORY.md was deliberately distilled down to 11.7 KB, then grew back to 22.3 KB over the next nine days, a 90 percent regain. Facts flowed into the always-loaded tier from every writer and nothing pushed them back out, so the file that is supposed to stay small did the opposite. In the same period a trip was flagged in memory as "99 days out" when it was 17 days out, a backup routine claimed to run nightly had run once and failed silently for a month, and a standing "bind to this address" rule was violated three separate times after being written down. None of these were storage failures. The facts were stored. The system had no way to notice when they went stale, drifted from the live config, or were simply ignored.
The conclusion that shaped the rest of the design: memory that depends on the model remembering to keep it clean will decay, because the model is exactly the component that gets distracted. So the maintenance work moved into code that runs on a schedule whether or not any model is paying attention.
Seven checks run as ordinary scripts, wrapped into a daily and a weekly job:
| Check | What it enforces |
|---|---|
memory_budget.py | L1 stays ≤ 14 KB, L0 ≤ 8 KB. Back-pressure against the regrowth above. Currently 8.3 KB and 4.5 KB. |
memory_staleness.py | Flags overdue review-by dates and past-dated action lines in L0/L1. Writes a report; the nightly consolidation acts on it. |
errors_lint.py | Every ERRORS.md entry carries an Enforcement field (a named guard, or advisory-only) and a Repeat-of field. |
enforcement_audit.py | Finds advisory-only rules that recurred and flags them for a real guard. |
error_metrics.py | Computes the repeat-error rate from the Repeat-of fields. The number the whole error log is meant to drive down. |
config-drift-guard.py | Asserts named invariants in the live gateway config match what memory says they are. |
cron_delivery_lint.py | Every scheduled job addresses an explicit handle, never a display-name lookup or an empty route. |
Two of these came directly from incidents. config-drift-guard.py exists because a config value silently disagreed with a written rule for over a week; it now fails the daily job if the two diverge. cron_delivery_lint.py exists because a scheduled job with a broken delivery route improvised a recipient and sent internal notes to a fabricated phone number. The lint makes that configuration impossible to leave in place.
The design rule underneath all of them: a check detects, a report records, and the nightly model turn fixes. The scripts never edit memory themselves. That separation is deliberate. A deterministic monitor that also rewrites its own target is how one of these scripts was silently truncated to a single word in an earlier incident.
New durable facts go to the L2 topic file; L1 gets a pointer. That rule is written into the agent instructions and backed by the budget guard, so the regrowth problem cannot return quietly. On top of the guards, three slower loops run: a weekly pass reconciles learned "instincts" against the correction log and demotes any that were contradicted; a nightly pass drafts decision-log entries from commits and daily notes so choices stop escaping into commit messages; and the repeat-error rate is tracked over time as the honest measure of whether the error log is doing its job.
Neither default is good enough for serious use, and it helps to see why side by side. OpenClaw out of the box keeps the raw conversation and recalls things by carrying that history in context, cruft and all, but sorts none of it into organized memory; you add that with a plugin. Hermes out of the box builds organized memory right away, but into files hard-capped at a couple thousand characters, so it holds a curated page or two and evicts the rest. One keeps everything and organizes nothing. The other organizes from the start, into a room that does not get bigger.
The fix is where they diverge. In Hermes you switch on a memory provider, close to a single command, and the growing record, decisions, meeting notes, months of history, and all documents your agent needs to understand, own, or provide information to you on, moves into that provider and is retrieved on demand. The built-in cap does not lift; the provider simply becomes the place real memory lives. That is genuinely easy, and it carries two concerns. The provider is now a dependency your agent needs in order to work at scale, and the most capable providers are hosted services, so for something like a business chief-of-staff the whole history would sit on a third party's servers. Local providers exist and close that gap, the most self-contained of them giving up some retrieval power.
In OpenClaw the same capability is more assembly. You install the memory plugins and a system like the one above: tiered local files, on-demand retrieval, and the guards that keep it honest. Nothing forces older facts out to make room, nothing leaves the machine, and every part is a plain file you can read and change. It is more work than flipping a provider on, and in exchange the growth is unbounded, private, and yours.
So the real question is not which default is better; both need work. It is which kind of work you want, and what you are willing to trade. Hermes trades some control over your data, and a dependency on an outside provider, for a fast and low-effort path to memory that grows. OpenClaw asks for more effort and returns a memory you own outright and can grow without limit. For a weekend assistant, the fast path is the sensible one. For an agent meant to hold a business's history for years, the balance tips toward the one you control.