Yue Song

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

MechanismPrimary RoleHow It RunsStorage
Workspace filesSource of truth for durable memoryWritten explicitly~/.openclaw/workspace/memory/
memory_flushSaves same-day memory before compactionTriggered automatically~/.openclaw/workspace/memory/YYYY-MM-DD.md
QMD backendSemantic search over memory filesQueried explicitly via tools~/.openclaw/agents/<agentId>/qmd/
lossless-clawDAG-based conversation history compressionRuns passively each turn and at thresholds~/.openclaw/lcm.db
self-improving-agentError capture and continuous improvement logsCaptures 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_search and memory_get.

When it runs

SituationBehavior
Session startupLoads today + yesterday daily logs; main session also loads MEMORY.md
Agent decides something mattersWrites to workspace memory files
/new sessionReloads 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-claw stores conversation messages
  • MEMORY.md and memory/*.md are 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

EventFileCategory
Command failure.learnings/ERRORS.mderror
User correction.learnings/LEARNINGS.mdcorrection
Knowledge gap.learnings/LEARNINGS.mdknowledge_gap
Better practice discovered.learnings/LEARNINGS.mdbest_practice
Missing feature request.learnings/FEATURE_REQUESTS.mdfeature_request

Scheduled promotion

A daily job runs at 6 AM and does the following:

  1. Reads the files under .learnings/
  2. Organizes and filters what is actually useful
  3. Promotes valuable material into SOUL.md, AGENTS.md, TOOLS.md, or MEMORY.md
  4. 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:

MomentWhat Happens
Session startupLoad MEMORY.md plus today/yesterday daily logs; restore DAG state
Every turnlossless-claw assembles context; messages are ingested into lcm.db
Agent needs memoryAgent calls memory_search; QMD retrieves from memory files
Context nearing soft limitmemory_flush silently writes durable notes to today’s log
Context reaches thresholdlossless-claw compacts the DAG
Command failure or correctionself-improving-agent writes to .learnings/
Every 5 minutesQMD refreshes its index
Daily at 6 AMself-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.

LayerContentStorage StrategyImportance
Preference layerHabits, preferences, personal rulesMemory files + self-improving-agentWorth keeping locally
History layerConversation traces and work historylossless-claw DAG in local SQLiteBest kept local
Knowledge layerProject context and domain knowledgeWorkspace files under version controlMust 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