OpenClaw's Memory Stack: A Local-First Map of What Lives Where
Mar 31, 2026
A practical walkthrough of OpenClaw's five memory mechanisms, how they work together, and why I still prefer a local-first approach to agent memory.
After rewriting my notes into one coherent document, I realized OpenClaw’s “memory” is not one mechanism.
It is a stack.
Different parts store different kinds of information, run at different times, and solve different problems. If you blur them together, it becomes very easy to misunderstand what the system is actually remembering, what is just compressed history, and what is really the long-term source of truth.
This post is my current map of that stack, based on the memory tools and approaches I have chosen or experimented with so far.
The Five Mechanisms at a Glance
| Mechanism | Primary Role | How It Runs | Storage |
|---|---|---|---|
| Workspace files | Source of truth for durable memory | Written explicitly | ~/.openclaw/workspace/memory/ |
memory_flush | Saves same-day memory before compaction | Triggered automatically | ~/.openclaw/workspace/memory/YYYY-MM-DD.md |
| QMD backend | Semantic search over memory files | Queried explicitly via tools | ~/.openclaw/agents/<agentId>/qmd/ |
lossless-claw | DAG-based conversation history compression | Runs passively each turn and at thresholds | ~/.openclaw/lcm.db |
self-improving-agent | Error capture and continuous improvement logs | Captures passively, promotes on schedule | ~/.openclaw/workspace/.learnings/ |
The important thing is that these mechanisms are complementary, not interchangeable.
1. Workspace Files Are the Real Source of Truth
For me, the Markdown files in the workspace are the most important layer because they are the final source of truth for durable memory.
Everything else is derived from them, indexed from them, or compressed around them.
~/.openclaw/workspace/
├── MEMORY.md
└── memory/
├── YYYY-MM-DD.md
└── *.md
MEMORY.md is the curated long-term layer. The memory/ directory holds daily logs and topic-based notes such as project memory.
How this layer works
- Agents can write to these files whenever something feels worth preserving.
- On session startup, OpenClaw loads today’s and yesterday’s daily logs.
- The main session also loads
MEMORY.md. - During runtime, agents can query this layer through
memory_searchandmemory_get.
When it runs
| Situation | Behavior |
|---|---|
| Session startup | Loads today + yesterday daily logs; main session also loads MEMORY.md |
| Agent decides something matters | Writes to workspace memory files |
/new session | Reloads from disk without previous chat history |
This is the layer I trust most because it is local, legible, and directly editable.
2. memory_flush Is Silent Pre-Compaction Saving
memory_flush is a small mechanism, but it matters a lot.
Before OpenClaw starts automatic compaction, it inserts a silent agentic turn that tells the agent to persist anything worth keeping into that day’s memory file. The user never sees this turn.
The flow
Context window approaches soft threshold
↓
System injects a silent turn
↓
Agent receives: "Session nearing compaction. Store durable memories now."
↓
Agent writes to memory/YYYY-MM-DD.md
↓
Agent replies NO_REPLY
↓
Normal compaction continues
What it does well
- It gives the system one last chance to preserve useful information before compression.
- It writes into the most natural short-term durable layer: the daily log.
Its limits
- It only writes to the current day’s log, not to
MEMORY.md. - It is reminder-based, not guaranteed.
- The quality still depends on the agent’s judgment in that moment.
So I see memory_flush as a helpful safeguard, not as a complete memory strategy.
3. QMD Is the Search Engine, Not the Memory
QMD is the local retrieval engine behind memory search.
It is what turns raw Markdown files into something an agent can query effectively. In my setup, this matters more than having a fancy external memory product, because local notes become much more useful once retrieval is good enough.
QMD supports hybrid retrieval, including:
- BM25
- vector search
- MMR reranking
- temporal decay
That makes it a semantic search layer over the memory files, not the memory itself.
Agent-facing tools
memory_search(query: string, maxResults?: number): MemoryResult[]
memory_get(path: string, from?: number, lines?: number): string
The trigger model here is explicit: QMD does nothing unless the agent decides to search memory.
Index update flow
Memory file changes
↓
debounce (1.5s)
↓
index marked dirty
↓
background update every 5 minutes
↓
qmd update + qmd embed
↓
SQLite index refreshed
My current config
"memory": {
"backend": "qmd",
"qmd": {
"update": { "interval": "5m" },
"limits": { "maxResults": 6 }
}
}
This is one reason I am not in a hurry to outsource memory. Once local Markdown plus local semantic search works well enough, a large part of the memory problem is already solved.
4. lossless-claw Manages History, Not Workspace Memory
lossless-claw is not a file-based memory system.
It is a context engine for conversation history. Its job is to stop chat history from being naively truncated. Instead of dropping older messages, it stores them in a DAG and compresses them hierarchically.
The structure
Raw Messages
↓ summarize
Leaf Summary (L1)
↓ summarize
Condensed Node (L2+)
↓ ...
Higher-level condensed summaries
Runtime behavior
On every turn, lossless-claw assembles context from two things:
- a summary chain from the DAG
- a fresh tail of recent raw messages
Then it ingests the latest turn back into lcm.db.
When the context threshold is reached, it compacts older material into higher-level summaries.
Turn-by-turn flow
Each conversation turn:
User message
↓
assemble()
↓
Read DAG summary chain + fresh tail
↓
Construct model context
↓
Model inference
↓
ingest()
↓
Persist to lcm.db
Compaction flow
When context reaches threshold:
compact()
↓
Leaf compression
↓
Cascading higher-level compression if needed
↓
Write updated DAG to lcm.db
My current config
"lossless-claw": {
"enabled": true,
"config": {
"freshTailCount": 32,
"contextThreshold": 0.75,
"incrementalMaxDepth": -1
}
}
This means:
- the most recent 32 messages stay uncompressed
- compaction starts at 75% context usage
- cascading compression depth is effectively unlimited
The important clarification
This distinction is easy to blur, so it is worth saying directly:
lossless-clawstores conversation messagesMEMORY.mdandmemory/*.mdare workspace files- they solve different problems
I think that separation is healthy. History and memory should not be treated as the same thing.
5. self-improving-agent Turns Friction Into Better Defaults
The fifth mechanism is less about recall and more about adaptation.
self-improving-agent is an event-driven logging layer that captures mistakes, corrections, knowledge gaps, and requests for missing capabilities. Later, a scheduled process can promote the useful parts into longer-lived files.
What it captures automatically
| Event | File | Category |
|---|---|---|
| Command failure | .learnings/ERRORS.md | error |
| User correction | .learnings/LEARNINGS.md | correction |
| Knowledge gap | .learnings/LEARNINGS.md | knowledge_gap |
| Better practice discovered | .learnings/LEARNINGS.md | best_practice |
| Missing feature request | .learnings/FEATURE_REQUESTS.md | feature_request |
Scheduled promotion
A daily job runs at 6 AM and does the following:
- Reads the files under
.learnings/ - Organizes and filters what is actually useful
- Promotes valuable material into
SOUL.md,AGENTS.md,TOOLS.md, orMEMORY.md - Clears or archives processed learnings
File layout
~/.openclaw/workspace/
├── .learnings/
│ ├── LEARNINGS.md
│ ├── ERRORS.md
│ └── FEATURE_REQUESTS.md
└── SOUL.md / AGENTS.md / TOOLS.md / MEMORY.md
This layer matters because it converts repeated operational friction into system improvement.
How the Pieces Work Together
Once these mechanisms are separated, the full stack becomes much easier to reason about.
User input
│
├── lossless-claw
│ assemble() every turn
│ compact() at threshold
│ stores conversation history in lcm.db
│
├── model inference
│
├── memory_flush
│ silent pre-compaction reminder
│ writes to today's memory log
│
├── ingest()
│ persists latest messages into lcm.db
│
└── self-improving-agent
captures errors, corrections, and better practices
promotes useful learnings on a schedule
Workspace files
│
├── memory/YYYY-MM-DD.md
├── MEMORY.md
│
└── QMD backend
indexes files every 5 minutes
serves memory_search / memory_get
And if you want the timing view:
| Moment | What Happens |
|---|---|
| Session startup | Load MEMORY.md plus today/yesterday daily logs; restore DAG state |
| Every turn | lossless-claw assembles context; messages are ingested into lcm.db |
| Agent needs memory | Agent calls memory_search; QMD retrieves from memory files |
| Context nearing soft limit | memory_flush silently writes durable notes to today’s log |
| Context reaches threshold | lossless-claw compacts the DAG |
| Command failure or correction | self-improving-agent writes to .learnings/ |
| Every 5 minutes | QMD refreshes its index |
| Daily at 6 AM | self-improving-agent promotes useful learnings |
What This Means for SaaS Memory
This architecture also changed how I think about SaaS memory products.
There is a real tension here.
View A: memory is identity
Memory plus skills define what an agent is. If I hand that to a third-party SaaS, I am effectively outsourcing a trained employee’s working memory. If the service disappears, changes direction, breaks access, or loses data, that identity layer becomes fragile.
That is why I prefer to understand the local stack first: what is stored, where it lives, and how the layers interact.
View B: memory should not be too important
At the same time, a healthier pattern is emerging. Project truth should live in project files. Skills should improve themselves. If that is true, then “memory” should carry much less weight than people often assume.
What remains is mostly preference:
- how I like to work
- what I tend to correct
- which habits the agent should remember
- what defaults fit me better
If memory is mostly a preference cache, then it should be lightweight, partially disposable, and allowed to grow and fade automatically.
My current resolution: split memory by layer
Once I separate the layers, the contradiction mostly disappears.
| Layer | Content | Storage Strategy | Importance |
|---|---|---|---|
| Preference layer | Habits, preferences, personal rules | Memory files + self-improving-agent | Worth keeping locally |
| History layer | Conversation traces and work history | lossless-claw DAG in local SQLite | Best kept local |
| Knowledge layer | Project context and domain knowledge | Workspace files under version control | Must live in the project |
From that perspective, the main value of SaaS memory is not “remembering for me.” It is sharing preference memory across multiple agents or systems.
That is a valid use case. It is just not my current one.
The Tools I Have Evaluated So Far
There are many memory products and memory-shaped infrastructure layers in the market. These are simply the ones I have looked at or experimented with so far.
Mem0
Mem0 positions itself as a general-purpose memory layer for AI applications. Its pitch is “self-improving memory,” not just storage. It has both SaaS and self-hosted options.
That positioning makes sense: lower token costs, stronger personalization, and a layer that can accumulate user-specific signals over time.
Supermemory
Supermemory presents itself more as context infrastructure than as a narrow memory layer. Its stack includes user profile, retrieval, extractors, a memory graph, and connectors. It also offers self-hosted deployment.
What stands out to me is that it is trying to be broader than “vector database plus notes.” It is aiming to be an operational memory substrate.
My Current Conclusion
For now, my practical conclusion is simple:
- conversation history belongs in a local DAG
- personal preferences belong in local memory files
- project knowledge belongs in the project itself
- local semantic search already covers a large part of the retrieval problem
So I am not against SaaS memory. I just do not think it should be the first abstraction people reach for.
Right now, the clearest differentiated use case for SaaS memory seems to be shared preference memory across multiple agents working for the same user or team. That may matter later. It does not matter enough for me yet.
The local stack is already surprisingly capable.
The ideas in this post are mine; Codex helped me write it.
If you'd like to follow what I'm learning about AI tools and workflows, you can subscribe here → Subscribe to my notes