这是一份面向学习和借鉴的设计笔记。它说明 OpenClaw 如何让 AI Agent 记住长期信息、查找历史细节、在上下文压缩前保存重要内容,并把零散记录逐步整理成可靠的长期记忆。
OpenClaw 的核心思路可以概括为一句话:把记忆当作可治理的数据生命周期,而不是把它藏在模型或向量数据库里。 人能看到和编辑关键记忆;模型只能通过明确的文件、工具和运行时能力读取或写入记忆;索引负责帮模型找到内容,但原始文件仍然是事实来源。
一页读懂
如果不用工程术语,可以把 OpenClaw 的记忆系统理解成三件东西:
- 一本精简的人设和长期档案:
MEMORY.md,只放长期稳定、反复有用的信息。 - 一套按天保存的工作日志:
memory/YYYY-MM-DD.md,记录当天发生的细节、任务、决策和观察。 - 一个图书馆目录:SQLite、全文检索和向量索引,帮助 agent 在需要时找到旧内容。
这三件事分工不同:
MEMORY.md像简历或个人资料,短、准、长期有效。memory/像工作笔记,详细、可追加、可回看。- 搜索索引像目录卡片,可以重建,不应该成为唯一真相。
OpenClaw 不会把所有历史都塞进 prompt。它只把启动时真正需要的高信号内容放进上下文,详细历史通过 memory_search 和 memory_get 按需读取。这样既保留了长期连续性,又控制了 token 成本和隐私风险。
这套设计解决什么问题
长期运行的 Agent 会遇到四类记忆问题:
- 记不住:跨天、跨会话后,用户偏好和项目约定丢失。
- 记太多:把完整聊天历史塞进 prompt,成本高、速度慢、还容易污染回答。
- 记不准:模型凭印象回答,把临时结论当成事实。
- 记不安全:私聊内容、群组内容、后台任务内容混在一起,边界不清。
OpenClaw 的答案不是单靠 RAG,也不是单靠 prompt summary,而是组合出一条完整路径:
会话内容
-> 需要保存的短期事实写入 memory/
-> 搜索索引让旧内容可被找回
-> 多次被使用的内容进入 dreaming 整理
-> 高价值候选再进入 MEMORY.md
-> 启动和回答时按需加载
这条路径的重点是分层:详细内容留在文件里,常用结论进入长期记忆,检索工具负责连接两者。
关键设计原则
1. 文件是事实来源
OpenClaw 把长期记忆和工作记忆放在普通文件里,主要是 Markdown。这样做的好处是直接:
- 人可以打开、搜索、编辑、删除。
- Git 可以 diff、review、回滚。
- 索引损坏时可以从文件重建。
- 模型不能拥有一份看不见的隐藏记忆。
这并不表示系统里只有 Markdown。OpenClaw 仍会使用 SQLite、JSONL、embedding、plugin 后端等辅助数据结构。但这些结构承担的是索引、状态、缓存或外部服务连接,不应该取代人类可审查的事实来源。
2. prompt 只放必要内容
Agent 的上下文窗口是有限资源。OpenClaw 不把 daily memory 或完整 transcript 默认塞进每轮 prompt,而是区分:
- 启动时需要知道的内容:从 bootstrap files 和有限 startup context 注入。
- 回答时临时需要的历史:通过记忆工具检索。
- 长期稳定事实:放入精简的
MEMORY.md。
这个原则让记忆系统更像 “先查资料再回答”,而不是 “把所有资料背下来再回答”。
3. 压缩前先落盘
长对话接近上下文上限时,系统会压缩旧消息。压缩可以保留主线,但可能丢失细节。OpenClaw 在压缩前安排一次受限的静默写入,把当前窗口中值得保留的事实追加到 daily memory。
这一步很关键:它让重要信息先变成可检索文件,再离开上下文窗口。
4. 长期记忆需要晋升,不是随手写入
不是所有信息都应该进入 MEMORY.md。一次性任务、临时猜测、失败尝试和完整日志应该留在 memory/。只有多次被使用、被确认、跨会话有价值的信息,才适合晋升为长期记忆。
OpenClaw 用 dreaming 机制做后台整理和候选晋升,避免普通回答轮次随意污染长期记忆。
5. 读取和写入权限分开
读历史和写记忆是两种风险等级。OpenClaw 的工具设计明显更谨慎地限制写入,例如 pre-compaction flush 默认只能追加到当天 daily file,不能改写 MEMORY.md、DREAMS.md 或 bootstrap files。
这对其他项目很重要:记忆系统的安全性主要来自数据边界和权限边界,不只来自检索算法。
存储层:记忆放在哪里
MEMORY.md:长期记忆档案
MEMORY.md 是根目录下的 canonical memory file,用来保存长期有效、跨会话有价值的信息。
适合放入 MEMORY.md:
- 用户稳定偏好,例如回复语言、测试偏好、沟通方式。
- 项目级约定,例如发布流程、验证方式、代码边界。
- 长期任务状态,例如某个迁移计划的当前阶段。
- 已确认的经验教训,例如反复出现的问题和解决方式。
不适合放入 MEMORY.md:
- 一次性聊天细节。
- 大段日志、命令输出、完整 diff。
- 未确认的模型猜测。
- token、手机号、凭证、私密配置。
OpenClaw 会把 MEMORY.md 作为 bootstrap files 的一部分处理,并受字符预算限制:单个 bootstrap 文件默认最多注入 12000 字符,总 bootstrap 注入默认最多 60000 字符。源码中 canonical 文件名是大写 MEMORY.md;小写 memory.md 只作为 legacy repair 输入,不是正常注入路径。
memory/:日常工作记忆
memory/ 目录保存详细工作记录。常见形态包括:
memory/YYYY-MM-DD.md:当天的 daily memory。memory/YYYY-MM-DD-HHMM.md:session-memory hook 在/new或/reset时保存的近期会话摘要。- 其他 Markdown 文件:可以通过配置纳入检索。
这些文件的定位是 “详细历史”,不是 “每次启动全量注入”。普通回答时,agent 应通过 memory_search 和 memory_get 查找其中的内容。
startup context 是一个例外。它会在 /new、/reset 等重启类流程需要模型继续运行时读取最近 daily memory。默认窗口是最近 2 天,单文件最多读取 16 KiB、注入 1200 字符,总计最多 2800 字符;配置上限是最多 14 天、单文件 64 KiB/10000 字符、总计 50000 字符。每天最多额外带入 4 个 slugged daily files。裸 /new 和 /reset 只会被确认,不会为了加载 startup memory 单独调用模型。
DREAMS.md 与 memory/.dreams/:整理区
Dreaming 是后台整理机制。它会把工作记忆里的高价值内容变成候选摘要,并记录整理状态。
DREAMS.md面向人,便于查看 dreaming 结果、历史回填和候选记忆。memory/.dreams/面向机器,保存 recall、promotion、session corpus、phase signal 等状态。
只有更严格的 deep dreaming 流程才会写入 MEMORY.md。这把 “候选整理” 和 “长期记忆写入” 分开,降低长期记忆被污染的概率。
session transcript:完整历史,但不是默认记忆
OpenClaw 的完整会话历史会作为 session transcript 保存。它不是自动等同于长期记忆,也不应该无条件进入检索语料。
当配置允许时,session 内容可以被清洗、转换并索引到 sessions corpus。这个路径有可见性过滤,会跳过 checkpoint、backup 等不适合作为普通记忆结果的内容。这样可以在需要时搜索旧会话,同时避免把所有原始聊天噪声都当成记忆。
读取流程:Agent 如何想起旧事
OpenClaw 把 “启动时注入” 和 “运行中检索” 分开。
启动时,agent workspace 会加载一组 bootstrap files,例如:
AGENTS.mdSOUL.mdTOOLS.mdIDENTITY.mdUSER.mdHEARTBEAT.mdBOOTSTRAP.mdMEMORY.md
这些文件进入 Project Context,并受预算限制。子 agent、cron 等特殊会话还会有额外过滤。
运行中,memory-core plugin 会把记忆工具暴露给模型:
memory_search:按 query 搜索memory、sessions、wiki或allcorpus。memory_get:根据搜索结果读取更完整的文件片段。
系统提示会引导模型在回答 “以前做过什么”“用户偏好是什么”“某个项目状态是什么” 这类问题前先使用记忆工具,而不是凭空回忆。
OpenClaw 还支持 active memory:一个可选的轻量 agent 可以在后台提前召回可能相关的记忆。它适合直接聊天和明确配置的 agent,不应被理解为所有 channel 默认共享一份私有记忆。
搜索流程:为什么既要关键词也要向量
默认 builtin memory 使用本地 SQLite 管理文件、chunk 和全文索引。memory host 默认扫描 canonical root memory 与 memory/ 目录,也可以纳入可配置 extra paths。Markdown 会被拆成 chunk,默认估算 400 tokens 一段、80 tokens overlap。索引会跳过 symlink,并在启用时支持 multimodal metadata。
搜索分成两类:
- 关键词搜索:基于 SQLite FTS5/BM25,适合查函数名、错误码、文件名、命令、issue 编号。
- 向量搜索:基于 embedding,适合查意思相近但措辞不同的内容。
只做向量搜索会漏掉很多精确符号;只做关键词搜索又不擅长语义相似问题。OpenClaw 选择 hybrid search,把两类结果合并。
当前实现会取向量结果和文本结果的 union,然后按 chunk id 合并分数。默认参数包括:
vectorWeight = 0.7textWeight = 0.3maxResults = 6minScore = 0.35candidateMultiplier = 4maxCandidates = 200
核心公式是:
finalScore = vectorWeight * vectorScore + textWeight * textScore
之后还可以叠加:
- temporal decay:时间衰减,默认关闭,half-life 默认 30 天。
- MMR:多样性重排,默认关闭,lambda 默认 0.7。
- strict fallback relaxation:严格阈值下无结果但关键词召回存在时,对关键词支撑的结果放宽阈值。
embedding provider 的自动选择大致按已注册 provider 的 autoSelectPriority 排序。当前常见顺序是 local、GitHub Copilot、OpenAI、Gemini、Voyage、Mistral、DeepInfra、Bedrock。ollama 支持配置,但不是当前自动选择链路的一部分。
如果向量能力不可用,OpenClaw 可以退化为 FTS-only 搜索。向量查询优先使用 sqlite-vec KNN;sqlite-vec 不可用时,会退回到进程内 cosine scan。
写入流程:什么时候把内容变成记忆
OpenClaw 的写入路径可以分成三种。
人或 agent 明确写入 daily memory
普通工作中,适合把临时但有价值的内容写入 memory/YYYY-MM-DD.md。例如:
- 今天做过哪些验证。
- 某个 bug 的复现条件。
- 一个尚未完全确认的设计判断。
- 后续要继续跟进的任务。
这类内容详细但不一定长期稳定,所以先进入 daily memory,而不是直接进入 MEMORY.md。
会话重启时保存近期上下文
session-memory hook 会在 /new 或 /reset 时异步保存近期会话上下文,默认取最近 15 条消息,并可配置 LLM slug。它的作用是让会话切换后仍能找到刚刚发生的上下文。
压缩前静默 flush
当上下文预计接近上限时,OpenClaw 会在 compaction 前触发 pre-compaction memory flush。触发判断可以简化理解为:
预计 token >= 上下文窗口 - 保留区 - 软阈值
源码中的判断形态是:
projectedTokens >= contextWindow - reserveTokensFloor - softThresholdTokens
关键默认值和约束:
softThresholdTokens默认 4000。- transcript 超过 2 MiB 时可强制 flush。
- 每个 compaction cycle 最多 flush 一次。
- 默认目标是
memory/YYYY-MM-DD.md。 MEMORY.md、DREAMS.md和 bootstrap files 在这个阶段是 read-only。- 写入工具只允许对目标 daily file 做 append-only write。
- 静默轮次以
NO_REPLY结束,不向用户发送常规回答。 - heartbeat、CLI、read-only sandbox 等场景会跳过或收敛该行为。
这一步的产品含义很简单:在模型即将失去细节上下文前,先把值得保留的信息变成文件。
Dreaming:从工作笔记提炼长期记忆
Dreaming 可以理解成 “后台整理”。它不只是摘要,而是把分散在 daily memory、session corpus 和 recall 记录里的信息整理成更稳定的候选记忆。
它包含几类动作:
- recall tracking:记录哪些短期记忆被搜索命中、被使用。
- short-term promotion:根据多种信号评分,判断是否值得晋升。
- consolidation:把多个相关片段合并成更简洁的候选知识。
- grounded backfill:用已有文件作为依据补齐或修正候选,不凭空生成。
short-term promotion 不是简单的 “出现 3 次就晋升”。源码中使用加权信号,例如:
- frequency:0.24
- relevance:0.30
- diversity:0.15
- recency:0.15
- consolidation:0.10
- conceptual:0.06
默认晋升门槛还会考虑最小分数、召回次数、唯一 query 数等条件。深度 dreaming 的条件更严格,例如更高 minScore、更多 unique queries、recency half-life 和 max age 限制。
对其他项目而言,最值得借鉴的是这个边界:工作记忆可以宽松记录,长期记忆必须谨慎晋升。
plugin 后端与可替换性
OpenClaw 的 core 不应该知道某个具体记忆服务的私有策略。它通过 memory capability、工具、host SDK 和 plugin runtime 把记忆实现挂接进来。
当前源码和文档中可以确认的记忆相关实现包括:
- builtin memory:默认本地 SQLite、FTS5、embedding hybrid search。
- QMD:基于 Markdown/sidecar 的记忆后端,强调文件可移植性。
- Honcho:外部记忆服务集成。
- memory-lancedb plugin:基于 LanceDB 的外部记忆 plugin。
- memory-wiki plugin:作为 companion plugin 提供 wiki 型资料检索。
设计边界上要注意:
- active memory slot 通常只有一个 owner,避免多个后端同时主动注入互相竞争的上下文。
- wiki 这类 companion 检索可以和主 memory backend 并存,但要通过 corpus、工具描述和权限边界区分。
- core 应依赖通用 capability 和工具契约,不应写死某个具体 plugin 的内部策略。
给其他项目的复用方案
如果要在另一个 Agent 项目里复用这套思想,可以从五层开始:
- 长期档案:一个小型、人工可审查的
MEMORY.md,只放长期稳定事实。 - 工作日志:按天或按任务追加写入
memory/,保留细节但不直接注入 prompt。 - 混合检索索引:对工作日志做关键词 + embedding 检索,结果通过工具按需读取。
- 压缩前保存:上下文压缩前先把高价值细节写入 work log,写入范围受限。
- 后台整理:根据多次召回、相关性、时间和人工审查,把工作记忆提纯到长期记忆。
一个最小目录结构可以是:
project/
MEMORY.md # 精选长期事实
memory/
2026-05-24.md # 当天追加式工作日志
.dreams/ # 可选:机器整理状态
index.sqlite # 可重建的检索索引
推荐从这些规则开始:
- 启动时只注入
MEMORY.md的高信号片段,不注入完整历史。 - daily memory 通过 search/get 工具读取,不每轮自动加载。
- 每次压缩前要求模型追加值得保留的事实、决策、待办和约束。
- 长期记忆写入需要更高门槛,最好带来源和人工 review。
- 定期运行 consolidation,把重复日志变成简洁、可维护的长期条目。
常见反模式
迁移这套机制时应避免:
- 把完整聊天历史直接注入 prompt,导致成本和隐私风险失控。
- 把向量数据库当作唯一事实来源,导致无法人工检查、无法 diff、无法回滚。
- 让模型在普通回答轮次中随意重写长期记忆。
- 不区分私聊、群组、后台任务、subagent 的记忆可见性。
- 只做 “记住这个” 的显式写入,不做压缩前 flush 和后台 consolidation。
- 只做相似度搜索,不支持关键词、文件名、错误码等精确检索。
- 把 daily memory 当成长期档案,长期不整理,最后变成无法维护的日志堆。
安全与隐私边界
记忆系统最容易出问题的地方不是算法,而是边界。
需要特别注意:
- 私有长期记忆和共享 channel 不能默认混用。群组、公开频道、cron、subagent 都需要单独的加载规则。
- 原始 transcript 不应无条件进入长期记忆或共享检索语料。
- 写入权限要比读取权限更窄。pre-compaction flush 只能 append 到 daily file,是一个值得复用的约束。
MEMORY.md要保持小而准;越像垃圾场,越会损害 prompt 质量和隐私边界。- embedding/vector index 不是事实来源,系统应能从原始文件重建索引。
技术读者关注点
如果要进一步看源码,可以从这些入口开始:
- root memory 文件名和 legacy repair:
src/memory/root-memory-files.ts - bootstrap file 加载:
src/agents/workspace.ts - system prompt 和 Project Context:
src/agents/system-prompt.ts - memory search 配置默认值:
src/agents/memory-search.ts - startup daily memory:
src/auto-reply/reply/startup-context.ts - pre-compaction flush:
src/auto-reply/reply/memory-flush.ts - flush 工具权限:
src/agents/pi-tools.ts - session-memory hook:
src/hooks/bundled/session-memory/handler.ts - memory host 扫描和 chunk:
packages/memory-host-sdk/src/host/internal.ts - SQLite schema:
packages/memory-host-sdk/src/host/memory-schema.ts - session corpus:
packages/memory-host-sdk/src/host/session-files.ts - memory-core capability:
extensions/memory-core/index.ts - memory tools:
extensions/memory-core/src/tools.ts - prompt guidance:
extensions/memory-core/src/prompt-section.ts - search manager:
extensions/memory-core/src/memory/manager.ts - vector/keyword search:
extensions/memory-core/src/memory/manager-search.ts - hybrid scoring:
extensions/memory-core/src/memory/hybrid.ts - flush plan:
extensions/memory-core/src/flush-plan.ts - short-term promotion:
extensions/memory-core/src/short-term-promotion.ts
相关文档入口:
docs/concepts/memory.mddocs/concepts/memory-search.mddocs/concepts/memory-builtin.mddocs/concepts/dreaming.mddocs/concepts/active-memory.mddocs/concepts/compaction.mddocs/reference/memory-config.mddocs/reference/session-management-compaction.mddocs/reference/token-use.mddocs/plugins/memory-lancedb.mddocs/plugins/memory-wiki.md
最后总结
OpenClaw 记忆机制最值得学习的不是某个单点算法,而是整体治理方式:长期记忆是小而准的人工可审查档案,工作记忆是可追加的详细日志,搜索索引负责召回,压缩前先保存关键事实,后台整理再把高价值内容晋升为长期记忆。
这种设计适合长期运行、需要跨会话连续性、又必须控制隐私和上下文成本的 Agent 系统。