04 · OpenClaw 的记忆系统:短期、长期、可检索记忆
解释 OpenClaw 如何用 Markdown 文件、记忆搜索、压缩前保存和 Dreaming 组成可审查的记忆系统。
上一章讲 Agent 的大脑循环:模型每一步都要依赖上下文和工具观察。这里自然会遇到一个问题:如果模型本身没有隐藏状态,OpenClaw 怎么让 Agent 记住长期偏好、历史决策和跨会话经验?
结论先说:
OpenClaw 的记忆不是神秘数据库,而是写在 Agent workspace 里的 plain Markdown files;模型只会“记住”被保存到磁盘、并在后续上下文中被加载或检索回来的东西。
这篇不要把它想复杂。先把文件、搜索、压缩、后台提炼四件事分清楚。
1. 模型没有隐藏记忆
官方 Memory overview 说得很直白:OpenClaw remembers things by writing plain Markdown files in your agent's workspace。模型只“记得”保存到磁盘的内容,没有 hidden state。
这意味着三件事:
- 用户在聊天里说过,不等于长期记住。
- 写进文件,才有跨会话复用的机会。
- 后续仍然需要加载或搜索到上下文里,模型才能使用。
flowchart LR
A[Conversation] --> B{Worth saving?}
B -- No --> C[Session context only]
B -- Yes --> D[Write Markdown memory]
D --> E[Index or load]
E --> F[Future context]
所以 OpenClaw 的记忆系统不是“模型变成了有意识的长期记忆体”,而是一套围绕文件、索引、召回和提炼的工程系统。
2. 三类核心记忆文件
OpenClaw 当前官方记忆布局可以先记这三类:
| 文件 | 作用 | 加载/使用方式 |
|---|---|---|
MEMORY.md | 长期记忆,保存 durable facts、preferences、decisions | 每个 DM session 开始时加载 |
memory/YYYY-MM-DD.md | 每日笔记,保存 running context 和 observations | 今天和昨天的 notes 自动加载 |
DREAMS.md | 可选,Dream Diary 和 dreaming sweep summary | 供人类审查,不是普通聊天历史 |
这些文件位于 Agent workspace,默认路径是 ~/.openclaw/workspace。
~/.openclaw/workspace/
MEMORY.md
DREAMS.md
memory/
2026-05-05.md
2026-05-04.md理解这三类文件,比背很多参数重要:稳定偏好,例如“用户偏好 TypeScript”,更适合放 MEMORY.md;今天任务中的临时观察,例如“这个项目测试暂时卡在依赖版本”,更适合放 memory/YYYY-MM-DD.md;后台提炼的主题、候选长期记忆、梦境摘要,更适合进入 DREAMS.md。
DREAMS.md 是可选层,不要把它理解成 Agent 自动加载的普通长期记忆。长期提升最终仍然写入 MEMORY.md。
3. Context 和 Memory 不是一回事
Context 是本轮模型能看见的内容。Memory 是存放在磁盘上的材料。
这两个概念经常被混用,但排障时必须分开:
| 问题 | 属于 Context | 属于 Memory |
|---|---|---|
| 本轮 prompt 里有没有这条信息 | 是 | 否 |
| 信息有没有落盘 | 否 | 是 |
| 下次会话还能不能找回 | 不一定 | 有机会 |
| 会不会受模型上下文窗口限制 | 是 | 文件本身不受本轮窗口限制 |
| 模型能否直接使用 | 能,前提是已经在上下文里 | 不能,必须先加载或搜索回来 |
一个简单例子:
flowchart TD
A[用户说: 我喜欢简洁回答] --> B[本轮 context]
B --> C{需要长期保存?}
C -- Yes --> D[写入 MEMORY.md 或 daily note]
D --> E[memory_search 索引]
E --> F[未来按需召回到 context]
C -- No --> G[会话结束后只留在 transcript 或摘要里]
所以“Agent 失忆”通常有三种不同根因:
- 当时没有写入记忆文件。
- 写入了,但没有被加载或检索回来。
- 检索回来了,但被后续上下文或系统指令稀释。
不要只说“记忆坏了”,要先判断是哪一层的问题。
写进 Memory 只是第一步;后续被加载、搜索或主动召回进本轮 Context,模型才真正能用。
4. MEMORY.md 是长期事实,不是垃圾桶
MEMORY.md 保存 durable facts、preferences、decisions。它会在每个 DM session 开始时加载,因此越应该保持高信号。
适合写入 MEMORY.md 的内容:
- 长期偏好:用户偏好中文、简洁、先结论。
- 稳定身份:某个 Agent 的职责、边界、长期协作方式。
- 反复出现的决策:某个项目固定部署到 Cloudflare Pages。
- 已验证的工作约定:某个仓库必须通过特定脚本发布。
不适合写入 MEMORY.md 的内容:
- 一次性任务进度。
- 未核验的猜测。
- 短期约会、明天提醒、临时待办。
- 会过期的状态,例如“今天测试失败”。
官方还单独提到 commitments:有些未来 follow-up 不是 durable facts。例如“明天面试后问我结果”,更像短期承诺,不该粗暴写成永久长期记忆。明确提醒仍应使用 scheduled tasks。
长期记忆的质量,决定 Agent 越用越稳,还是越用越乱。
5. Daily notes 是短期工作轨迹
memory/YYYY-MM-DD.md 是 daily notes。它保存 running context 和 observations。官方说明今天和昨天的 notes 会自动加载。
它适合记录:
- 今天做过哪些排障。
- 某个临时错误的现象。
- 本周正在推进的项目状态。
- 还没验证到足以进入
MEMORY.md的线索。
它不适合承载所有长期规则。原因很简单:daily notes 会越来越多,不能指望每一条旧日记都自动进入每一轮上下文。
flowchart LR
D1[memory/2026-05-04.md] --> L[Auto load recent notes]
D2[memory/2026-05-05.md] --> L
D3[memory/older.md] --> S[memory_search]
L --> C[Current context]
S --> C
旧 daily note 主要靠 memory_search 找回,而不是靠全部加载。
6. memory_search 和 memory_get
OpenClaw 给 Agent 提供两个记忆工具:memory_search 用来语义搜索相关 notes,即使用词不同也能找;memory_get 用来读取某个具体 memory file 或行范围。
这两个工具由 active memory plugin 提供,默认是 memory-core。
memory_search 的关键是 hybrid search:
flowchart LR
Q[Query] --> E[Embedding]
Q --> K[Keyword tokens]
E --> V[Vector search]
K --> B[BM25 search]
V --> M[Merge]
B --> M
M --> R[Relevant memory snippets]
它会把两条路径合并:
- Vector search:按语义相似度找,例如“gateway host”能匹配“the machine running OpenClaw”。
- BM25 keyword search:按精确词匹配,例如配置键、错误码、路径、ID。
这解释了为什么记忆搜索比普通 grep 更适合“用户偏好”“项目背景”这类软信息,也解释了为什么它仍然需要关键词路径:错误日志、配置 key、文件名必须精确命中。
7. Embedding provider 决定搜索质量
官方列出的 memory_search provider 包括 Bedrock、Gemini、GitHub Copilot、Local、Mistral、Ollama、OpenAI、Voyage。
如果你已经配置了 GitHub Copilot subscription、OpenAI、Gemini、Voyage 或 Mistral key,memory search 通常可以自动工作。也可以显式配置:
{
"agents": {
"defaults": {
"memorySearch": {
"provider": "openai"
}
}
}
}没有 API key 时,也可以用 provider: "local",但本地 embedding 会带来模型下载、构建和速度问题。
排障时先跑:
openclaw memory status
openclaw memory status --deep
openclaw memory index --force几个典型症状:
| 症状 | 可能原因 | 处理 |
|---|---|---|
| 没有结果 | 索引为空 | openclaw memory index --force |
| 只有关键词命中 | embedding provider 没配置或不可用 | openclaw memory status --deep |
| 中文找不到 | FTS 索引需要重建 | openclaw memory index --force |
| 结果重复 | 大量 daily notes 相近 | 开启 MMR |
| 旧内容总排前面 | 历史 note 太多 | 开启 temporal decay |
MMR 用来减少重复结果。Temporal decay 会让旧 notes 逐渐降权,但 evergreen files 如 MEMORY.md 不衰减。
8. Compaction 前的 memory flush
上一章讲过,Agent loop 有上下文窗口限制。官方 Compaction 文档说明:当会话接近上下文限制时,OpenClaw 会把旧消息压缩成 summary;完整历史仍在磁盘上,compaction 改变的是下一轮模型看见什么。
记忆系统和 compaction 的关系在这里:
Before compaction, OpenClaw can run a silent memory flush turn to store durable notes to disk。
也就是压缩前,OpenClaw 可以静默提醒 Agent 把重要内容写进 memory files,避免旧上下文被摘要后丢失细节。
Memory flush 不是万能自动记忆,而是 compaction 前的一次保护动作:先把值得保留的事实落盘,再压缩上下文。
flowchart TD
A[Conversation grows] --> B[Near context limit]
B --> C[Silent memory flush]
C --> D[Save important notes to memory files]
D --> E[Compaction summary]
E --> F[Next turn uses compacted context]
这不是“每隔固定多少字就写记忆”的万能机制。它是 compaction 前的保护动作。你也可以给 memory-flush turn 配一个独立模型:
{
"agents": {
"defaults": {
"compaction": {
"memoryFlush": {
"model": "ollama/qwen3:8b"
}
}
}
}
}注意这个 override 是 exact model override,不继承 active session fallback chain。
9. Dreaming 是后台提炼,不是默认开关
Dreaming 是 memory-core 里的 background memory consolidation system。它帮助 OpenClaw 把强短期信号移动到 durable memory,同时保持过程可解释、可审查。
两个硬事实:
- Dreaming 是 opt-in,默认 disabled。
- Long-term promotion 仍然只写入
MEMORY.md。
Dreaming 有三类输出或状态:memory/.dreams/ 放机器状态,包括 recall store、phase signals、checkpoints、locks;DREAMS.md 放人类可读的 Dream Diary 和 phase summaries;memory/dreaming/<phase>/YYYY-MM-DD.md 放可选阶段报告。
它的三阶段模型:
| Phase | 做什么 | 是否写长期记忆 |
|---|---|---|
| Light | 整理和暂存近期短期材料 | 否 |
| REM | 反思主题和重复想法 | 否 |
| Deep | 评分并提升 durable candidates | 是,写入 MEMORY.md |
Deep phase 的候选提升不是随便写。官方列出评分信号包括 frequency、relevance、query diversity、recency、consolidation、conceptual richness。候选还要通过 score、recall frequency、query diversity 等门槛。
这说明 Dreaming 的定位不是“每天自动把所有日记塞进长期记忆”,而是带阈值、可审查的后台提炼。
10. Active Memory 是回复前召回
多数记忆系统是 reactive:主 Agent 想起来才查,或者用户明确说“记住这个”“搜索记忆”才查。Active Memory 解决的是另一类问题:在生成主回复之前,给系统一次有边界的机会先找相关记忆。
官方定义:Active memory 是 optional plugin-owned blocking memory sub-agent,运行在 eligible conversational sessions 的主回复之前。
它适合:
- 持久用户偏好。
- 反复出现的个人习惯。
- 需要自然延续感的长期上下文。
它不适合:
- 自动化任务。
- 内部 worker。
- one-shot API 调用。
- 不应该隐藏个性化的场景。
默认建议从 direct-message sessions、queryMode: "recent"、较短 timeout 开始,因为它在主回复路径上,会直接影响延迟。
11. Memory Wiki 是知识层,不替代记忆层
memory-wiki 是 bundled plugin,用来把 durable memory 编译成更像知识库的 vault。
它不替代 active memory plugin。官方分工是:Active memory plugin,例如 memory-core、QMD、Honcho,拥有 recall、semantic search、promotion、dreaming、memory runtime;memory-wiki 拥有 compiled wiki pages、provenance-rich syntheses、dashboards、wiki-specific search/get/apply。
Memory Wiki 适合你希望记忆更像“维护过的知识层”,而不是一堆 Markdown 日记。它可以提供:
- deterministic page structure。
- structured claims and evidence。
- contradiction and freshness tracking。
- generated dashboards。
- compiled digests。
wiki_search、wiki_get、wiki_apply、wiki_lint。
实践规则:泛化召回一段记忆先用 memory_search;跨 memory 和 wiki 做广义召回用 memory_search corpus=all;需要来源、可信度、页面结构时用 wiki_search + wiki_get;要维护 claims、contradictions、freshness 时用 memory-wiki。
12. 写记忆的判断标准
不是所有信息都应该写入记忆。
建议按这个顺序判断:
flowchart TD
A[New information] --> B{Will it matter after this session?}
B -- No --> X[Do not write]
B -- Yes --> C{Stable and durable?}
C -- Yes --> D[MEMORY.md]
C -- No --> E{Useful for current workstream?}
E -- Yes --> F[memory/YYYY-MM-DD.md]
E -- No --> G[Maybe commitment or scheduled task]
高质量记忆通常满足:
- 可复用:未来任务会再次用到。
- 可验证:不是猜测或情绪化印象。
- 可压缩:一句话能说明用途。
- 有边界:知道适用范围和过期条件。
低质量记忆通常是:
- “用户今天说了很多话”这种流水账。
- “某个任务做到一半”但没有后续价值。
- 没有来源的推断。
- 已经过期的临时状态。
长期记忆写得越乱,Agent 后续越容易自信地引用错误背景。
记忆不是越多越好。低质量长期记忆会污染未来判断,比没有记忆更难排查。
13. 给 Agent 的实践任务
把下面任务交给你的 OpenClaw Agent:
请检查你的记忆系统状态:
1. 说明你的 workspace 记忆文件布局:MEMORY.md、memory/、DREAMS.md 是否存在。
2. 用 memory_search 查询“用户偏好”和“当前项目约定”,说明返回了哪些结果。
3. 用 memory_get 读取最相关的一条记忆来源。
4. 判断这些内容应该保留在 daily note,提升到 MEMORY.md,还是不应该长期保存。
5. 如果搜索为空,给出 memory status、status --deep、index --force 的排障顺序。你要观察它有没有分清楚:
- 文件存在不等于已索引。
- 已索引不等于会自动进上下文。
- daily note 不等于长期记忆。
- Dreaming 不等于默认自动提炼。
- Memory Wiki 不等于替代
memory-core。
14. 本章自检
读完这一篇,你应该能回答:
- OpenClaw 为什么说没有 hidden state?
MEMORY.md、memory/YYYY-MM-DD.md、DREAMS.md分别是什么?- Context 和 Memory 的边界在哪里?
memory_search为什么要同时用 vector search 和 BM25?- memory flush 和 compaction 的关系是什么?
- Dreaming 为什么默认 disabled?
- Active Memory 适合哪些会话,不适合哪些任务?
- Memory Wiki 和 active memory plugin 的分工是什么?
能回答这些问题,再看下一篇上下文管理,就能理解为什么“写进记忆”和“进入本轮 prompt”仍然是两件事。
15. 接下来去哪
05 · Context 管理
继续看哪些信息会进入本轮上下文,以及上下文太长时 OpenClaw 怎么处理。
03 · Agent 的大脑
回到 Agent loop,确认记忆工具如何进入模型-工具循环。
官方教程:Agents
对照官方 Agents 页继续看 workspace、runtime、tools 和 agent 配置。