AI 记忆这件事,表面看是“怎么让模型记住更多东西”,真落到工程里,麻烦点反而是:怎么让它少记废话。
一段对话结束,窗口一关,AI 就像什么都没发生过。它不记得上次 PR 里定过的规则,不记得你强调过“测试必须跑真实数据库”,也不记得某个设计为什么被否掉。最直觉的方案是把历史全塞回上下文,但这条路很快会撞墙:上下文窗口有限,历史越多,噪音越多,模型越容易在一堆旧信息里迷路。
OpenClaw 的 memory-core 走的是另一条路:让记忆自己证明价值。它不试图在第一次写入时就判断一条信息是否值得永久保存,而是把记忆放进一个持续筛选、召回、评分、晋升的闭环里。被反复用到、在不同场景下依然有价值的内容,才有资格进入长期记忆。
本文用一条具体规范贯穿整个流程:
测试必须使用真实数据库,不接受 mock。
看这条规范如何从一次 PR 评审里的日记,经过梦境系统的多轮提炼,最后进入持久记忆。
一、三层记忆文件
memory-core 没有把所有内容塞进一个统一数据库,而是拆成三个文件层级。这个设计很朴素,但很关键:不同置信度的内容不应该混在一起管理。
| 文件 | 写入方 | 存放内容 | 置信度 |
|---|---|---|---|
memory/YYYY-MM-DD.md |
AI 手写 | 对话中值得保留的内容,自由格式草稿 | 最低,未经筛选 |
DREAMS.md |
梦境系统 | 候选区块、评分记录、梦境日记 | 中等,经过阶段性加工 |
MEMORY.md |
深度梦境 | 通过评分后的持久记忆 | 最高,反复验证后写入 |
这三个文件不是平行关系。
memory/YYYY-MM-DD.md 是原料仓,MEMORY.md 是最终结论,DREAMS.md 更像一层展示日志。它记录每天梦境系统挑出了什么、怎么评分、写了什么梦境日记,但真正的状态流转并不依赖重新解析 DREAMS.md。
这里有个容易误解的点:梦境系统不是每天把 DREAMS.md 读回来继续加工。真实交接靠的是内部状态库:
- 一个基础数据库,记录碎片本身、召回次数、标签等信息;
- 一个状态数据库,记录碎片被轻度梦境、REM 梦境选中的历史。
同一条“测试必须使用真实数据库”,在三个文件里的形态完全不同。
memory/2026-06-15.md 里可能是这样:
## PR 评审
发现问题:mock 数据库让上季度的迁移 Bug 逃过了测试,在生产才暴露。
规范:今后所有测试必须使用真实数据库,不接受 mock。
DREAMS.md 里变成候选和梦境记录:
# Dream Diary
*June 15, 2026, 3:01 AM PDT*
有些教训是用生产事故买来的...
## Light Sleep
- Candidate: 测试必须使用真实数据库,不接受 mock
- confidence: 0.64
- evidence: memory/2026-06-15.md:5-8
- recalls: 4
- status: staged
## REM Sleep
- Candidate Truth: 测试规范——真实数据库
- confidence: 0.61
- consolidated: 5 days
最终进入 MEMORY.md 时,会被压缩成更稳定的结论:
测试必须使用真实数据库,不接受 mock。上季度 mock 测试掩盖了一次数据库迁移失败,在生产环境才暴露。
这就是 memory-core 的核心节奏:先允许粗糙写入,再用后续使用行为慢慢筛掉噪音。
二、记忆生命周期
OpenClaw 的记忆生命周期可以拆成五步:
前四步是线性的:
- 写入日记;
- 轻度梦境切块;
- REM 梦境提炼规律;
- 深度梦境晋升长期记忆。
真正让系统闭合的是第五步:读取。
每次 AI 通过 memory_search 命中一条记忆,系统都会更新这条记忆的召回计数、查询场景、召回日期等信息。也就是说,读取不是单纯消费,它同时也是一次投票。
这点很有工程味道。
很多记忆系统的问题,是写入时过度自信。模型当下觉得重要,不代表三天后还重要。memory-core 把判断权往后推,用真实召回行为来验证价值。代价是记忆不会立刻“升格”,需要一段时间积累;收益是长期记忆更干净,不容易被一次性噪音污染。
三、写入:先让 AI 写日记
写入不是实时发生,也不是用户显式触发。它嵌在每次会话回复的尾部。
每次 AI 回复结束后,系统按固定顺序做两件事:
- 判断是否需要压缩上下文;
- 判断是否需要刷新记忆,也就是写入当天日记。
顺序是固定的:压缩先,刷新后。
原因也现实。如果当次发生了压缩,刷新紧接其后可以把新内容及时落盘,避免下一轮压缩把刚发生的事情吞掉。没有压缩时,刷新也独立运行,不依赖压缩触发。
写入提示词很克制,大概只告诉 AI:
压缩前记忆刷新。将持久记忆写入 memory/YYYY-MM-DD.md。
如文件已存在,只追加新内容,不覆盖已有条目。
MEMORY.md、DREAMS.md 等工作区文件视为只读,不得修改。
如无内容可存,回复 ⟨silent⟩。
这里没有强行规定“什么必须写”。这是一个值得注意的选择。
如果系统用规则自动抽取对话,很容易捞出大量过程性垃圾:临时命令、试错方案、已经废弃的思路、某次排查里的中间状态。让 AI 在回复结束前自己判断哪些内容值得留下,相当于借模型的语义理解做第一轮过滤。
通常值得写进日记的,是几类东西:
- 明确决策,比如技术选型、规范约定;
- 用户偏好,比如测试方式、代码风格、部署习惯;
- 长期任务状态,比如某个 PR、迁移、重构还没收尾;
- 有复用价值的事故原因和解决思路。
不值得写的,是一次性操作、临时探索、已经完成且不会再被引用的细节。
“测试必须使用真实数据库”这条规范,之所以值得写,不只是因为它是一条规则,更因为它背后有事故动机:mock 测试掩盖了迁移失败,问题最终在生产暴露。
Markdown 结构不是装饰
日记写入当天的 memory/YYYY-MM-DD.md,只追加,不覆盖。
这里还有一个小但重要的细节:最好用 ## 标题分区。它不只是为了人读起来舒服,还会影响后面的切块。
比如 AI 写下:
## PR 评审
规范:测试必须使用真实数据库,不接受 mock。
上季度 mock 测试掩盖了一次数据库迁移失败,在生产才暴露。
轻度梦境摄入时,会把标题作为上下文前缀,生成类似这样的碎片:
PR 评审: 规范——测试必须使用真实数据库,不接受 mock。
这能避免碎片变成孤立句子。很多记忆检索的质量问题,其实不是向量模型不行,而是切出来的文本本身没上下文。
四、轻度梦境:把日记变成碎片
日记只是草稿。写进去的内容信噪比仍然参差不齐,大多数事情只出现一次,不该进入长期记忆。
梦境系统默认关闭,需要配置 dreaming.enabled = true 才会运行。开启后,它通常在每天凌晨 3 点按顺序执行:
Light Sleep → REM Sleep → Deep Sleep
轻度梦境的任务最基础:把自由格式日记转成可追踪的结构化碎片。
轻度梦境扫描过去 2 天的内容,来源有两路:
memory/*.md日记文件;- 会话 JSONL 转录文件。
两路来源初始分不同:
| 来源 | 初始分 | 原因 |
|---|---|---|
| 日记碎片 | 0.62 | 已经过 AI 主动筛选 |
| 会话碎片 | 0.58 | 更接近原始记录,噪音更高 |
日记会按 Markdown 结构切块。标题作为上下文前缀,列表和段落按类型分组;遇到类型切换、超过 4 行或超过 280 字符时,会切成新块。
切块后的碎片写入基础数据库,核心字段包括:
| 字段 | 含义 |
|---|---|
key |
碎片唯一 ID |
snippet |
碎片文本 |
recallCount |
被 memory_search 命中的次数 |
conceptTags |
从内容中提取的概念标签 |
totalScore |
多次摄入或召回累积的质量分 |
conceptTags 的提取也比较工程化:先匹配固定词汇表,再识别带分隔符的复合词,比如 memory-core、recall.count,最后再从普通文本里分词。上限 8 个,先到先得。
这不是什么复杂 NLP,但够用。标签的作用也不是替代向量检索,而是给后续 REM 和深度梦境提供辅助信号。
候选选拔
基础数据库里可能有几百条碎片,轻度梦境不会全部写进 DREAMS.md,而是选一批候选。
一条候选大概长这样:
## Light Sleep
- Candidate: 测试必须使用真实数据库,不接受 mock
- confidence: 0.64
- evidence: memory/2026-06-15.md:5-8
- recalls: 4
- status: staged
这里的 confidence 可以理解为历史平均质量分:
confidence = totalScore / recallCount
分数越稳定,说明这条碎片越不只是偶然出现。
同时,轻度梦境还会在状态数据库里记录:
| 字段 | 含义 |
|---|---|
lightHits |
被轻度梦境选中的总次数 |
lastLightAt |
最近一次被轻度梦境选中的时间 |
remHits |
被 REM 梦境选中的总次数 |
lastRemAt |
最近一次被 REM 梦境选中的时间 |
这就是后续阶段判断“它是否持续被注意到”的依据。
梦境日记的意义
轻度梦境在写完候选后,还会调用 LLM,把今晚的碎片写成一段第一人称梦境日记,追加到 DREAMS.md 的 # Dream Diary 区块。
这个设计乍看有点浪漫,甚至有点不工程。但仔细想,它解决的是一个很实际的问题:纯候选列表缺少语义背景。
冷冰冰的总结可能是:
2026-06-15:确立测试规范,要求使用真实数据库。上季度 mock 测试导致迁移失败在生产暴露。
梦境日记可能是:
有些教训是用生产事故买来的。一个在本地跑得很好的 mock,掩盖了数据库迁移时的一个边界条件——等到真实的压力下来,才暴露出来。从那以后,这里有一条不成文但已写进代码仓库精神里的规矩:测试必须承受真实的重量。
后者不只是“文艺”。它把事实、动机、后果放在一起。几天后检索“测试规范”时,AI 命中的不只是规则本身,还有规则为什么存在。
当然,这里也有取舍:让 LLM 生成散文会引入表达漂移,甚至可能把语气写得过满。OpenClaw 的做法是把梦境日记放在 DREAMS.md,而不是直接放进 MEMORY.md。它可以参与检索和积累,但不能直接成为最高置信度的持久记忆。
这是比较稳的边界。
五、REM 梦境:在候选里找规律
REM 梦境不重新扫描日记文件。它读状态数据库,找到轻度梦境本轮标记过、尚未被 REM 消费的碎片。
这点很重要:DREAMS.md 里的 ## Light Sleep 区块只是展示记录,不是阶段交接的数据源。真正的交接靠状态数据库。
REM 做两件事。
第一,基于 conceptTags 找今晚的强主题。比如一批候选里大量出现:
- 测试规范;
- 数据库;
- 生产安全。
系统会计算每个标签在候选条目中的占比,并做一个饱和处理。大致逻辑是:如果一半条目都有某个标签,这个标签已经足够称为今晚的主导主题,不需要等到 100%。
强度达到阈值后,这些主题会传给 LLM,作为 REM 版梦境日记的素材。
第二,对候选做置信度评分。评分维度包括:
| 分量 | 作用 |
|---|---|
| 历史平均得分 | 衡量内容本身质量 |
| 读取强度 | 命中次数,对数压缩 |
| 跨天巩固 | 是否分布在多个日期 |
| 概念覆盖 | 标签丰富度,辅助判断 |
这里权重最高的是历史平均得分。这个选择很合理:REM 的窗口比较窄,如果过度看频次,很容易把最近某次密集讨论推上去。高频不一定高价值,尤其在同一个上下文里连续追问时。
对于“测试必须使用真实数据库”这条规范,如果它在几次 PR、测试讨论、新成员提问里都被召回,REM 就会把它推到更高置信度的候选列表里。
REM 版梦境日记和轻度版的区别,也来自输入素材不同。
轻度版看的是“今晚发生了什么”:
今天又回到了那个 PR。mock 数据库的问题再次被提起,有人在评论里说上季度的迁移失败就是这么来的。
REM 版更像“这段时间发现了什么规律”:
三周,四次 PR,都绕回同一个问题:有人在 mock 里悄悄绕过了数据库边界。这条规范不是哪次会议定下来的,是一次次生产事故教出来的。
两者最终都写进同一个 DREAMS.md 日记流。系统没有给 REM 日记显式更高优先级,而是让检索相似度自己竞争。
这是另一个工程取舍:引入权重体系可以更可控,但也会带来调参复杂度。OpenClaw 选择让更精炼的内容在语义检索中自然占优,简单,但依赖生成质量。
六、深度梦境:进入长期记忆
深度梦境是最终关卡,也是唯一能写 MEMORY.md 的入口。
候选来自基础数据库中满足资格的碎片,不要求必须先被 REM 选中。也就是说,REM 是强背书,但不是唯一通道。
深度梦境评分由六个主维度加一个阶段加成组成。
| 维度 | 权重 | 衡量内容 | 防止的问题 |
|---|---|---|---|
| 相关度 | 0.30 | 历史平均检索得分 | 低质量内容靠频次混入 |
| 频率 | 0.24 | 累计命中次数 | 只出现一次就晋升 |
| 查询多样性 | 0.15 | 不同查询场景或召回天数 | 单次深度对话刷高分 |
| 近期活跃 | 0.15 | 最近是否仍被使用 | 陈旧内容滞留 |
| 跨天巩固 | 0.10 | 是否跨多天验证 | 单日集中操作伪造价值 |
| 概念覆盖 | 0.06 | 标签数量 | 辅助判断,权重较低 |
| 阶段加成 | 最多 0.15 | Light / REM 历史背书 | 鼓励经过阶段筛选的内容 |
这个评分体系的核心思路很清楚:不要被单一信号骗了。
一次长对话可以把命中次数刷得很高,但不代表这条内容适合长期保存;一条信息跨了很多天被偶尔提到,也不一定说明它有足够复用价值。所以深度梦境同时看频率、多样性、时间跨度、近期活跃和上游阶段背书。
查询多样性
查询多样性想回答的问题是:
这条记忆有没有在不同场景下被用到?
只看唯一查询数会有问题。同一晚连续问 10 个不同问题,唯一查询数很高,但可能都属于同一个任务。只看召回天数也不够,一条信息每周被同类问题提一次,天数会累积,但场景未必多样。
所以系统会综合唯一查询数和召回天数,取能更好代表多样性的信号。正常项目周期里,一条真正有价值的规范,出现在 5 个左右不同查询场景已经足够说明问题。
跨天巩固
跨天巩固看两个东西:
- 被召回了多少天;
- 首次召回到最近召回跨了多久。
前者代表真实使用记录,后者代表时间跨度。
只看天数会被连续几天集中操作刷满;只看跨度会被“第一天用一次,第二十一天又用一次”拉高。两个指标合起来,才更接近“这条记忆是否稳定存在于工作流中”。
这里的时间参考单位取 7 天也比较合理。很多项目节奏以周为单位,如果一条规范跨过多个工作周仍然被用到,它大概率不是一时兴起。



























































