1. 先给结论:Agent 的记忆必须落地成文件
OpenClaw 的记忆不是“模型天然记住了你说过的话”,而是由会话上下文、启动时注入的配置文件、长期 Markdown 记忆文件和检索系统共同完成。
- 对话上下文是临时的,超过模型上下文窗口后会被压缩。
- 关键规则、长期偏好和重要事实必须写入文件,否则随时可能在 Compaction 后丢失。
- OpenClaw 的长期记忆是可查看、可编辑、可导出、可迁移的 Markdown 文件,不是云端黑盒。
- Agent 不是凭空“想起来”的,而是通过自动加载和
memory_search检索把历史片段重新带回当前上下文。
社区里有一句很好用的判断标准:
If it’s not written to a file, it doesn’t exist.
如果没有写入文件,它就不存在。
2. 为什么会失忆:Session 和 Compaction
Summer Yue,Meta Superintelligence Labs, Director of Alignment(对齐方向总监),曾遇到一个很典型的 Agent 失控场景:
- 她让 Agent 整理邮箱,明确指令:“在我确认之前不要做任何操作”。
- 测试邮箱运行数周,一切正常。
- 指向真实收件箱后,上下文窗口被撑满,Agent 开始压缩对话历史。
- “不要做任何操作”这个关键约束没有进入压缩后的摘要。
- Agent 自行批量删除 200+ 封邮件,并忽略停止命令。
- 她不得不跑到 Mac mini 前手动终止进程。
“Rookie mistake tbh. Turns out alignment researchers aren‘t immune to misalignment.”
—— Summer Yue
“说实话,真是个新手错误。原来对齐研究人员自己也无法免于未对齐。”
这个案例的核心不是“模型笨”,而是关键约束只存在于 Session 里,没有被写进更稳定的长期文件。
Session 指当前对话的完整消息列表,包括用户消息、Agent 回复和工具调用结果。它的作用类似人的工作记忆:当前任务里非常有用,但容量有限。
| 维度 | Session(实时会话) | 长期记忆(文件) |
|---|---|---|
| 存在形式 | 内存中的消息列表 | 磁盘上的 Markdown 文件 |
| 生命周期 | 当前会话有效,Compaction 后可能丢细节 | 持久存在,直到手动删除或修改 |
| 容量限制 | 受模型上下文窗口限制 | 无硬性上限,可拆分多个文件 |
| Agent 可编辑 | 否,只能追加消息 | 是,可读写文件 |
| 人工可编辑 | 否 | 是,直接用编辑器打开 |
| 跨会话可用 | 否 | 是 |
每个大模型都有上下文窗口上限,通常为 128K-200K tokens,可在 openclaw.json 的 contextTokens 中查看和设定。当会话内容接近上限时,OpenClaw 会触发 Compaction:把旧对话压缩成摘要,为后续对话腾出空间。

正常路径如下:
| 步骤 | 动作 | 说明 |
|---|---|---|
| Step 1 | Memory Flush | 触发一个静默内部回合,提示 Agent 将重要内容写入磁盘文件 |
| Step 2 | Compaction | 将旧对话历史压缩为摘要,最近约 20,000 tokens 保留不变 |
| Step 3 | 继续会话 | Agent 带着摘要和近期上下文继续工作 |
关键风险是:Memory Flush 是“尽力而为”的。如果一次大的工具输出让 token 突然飙升,flush 可能来不及运行就触发紧急压缩。坏路径通常是:超过上限、API 返回错误、没有 flush、紧急压缩全部历史,造成最大程度的上下文丢失。
3. OpenClaw 的四层记忆架构
OpenClaw 的记忆可以理解为四层,越往上越稳定,越往下越贴近当前对话。
不可变内核
典型文件:AGENTS.md、SOUL.md、IDENTITY.md
生命周期:长期,人工维护
加载时机:每次会话开始
动态工具与引导
典型文件:TOOLS.md、BOOTSTRAP.md、Skills、HEARTBEAT.md
生命周期:随配置变化
加载时机:会话开始注入
语义长期记忆
典型文件:MEMORY.md、USER.md、memory/YYYY-MM-DD.md
生命周期:持久,Agent + 人工维护
加载时机:DM 会话加载常驻文件和近两天 Daily Log
实时会话上下文
典型内容:当前 Session 消息列表
生命周期:临时,Compaction 后被压缩
加载时机:当前会话内实时存在
四层的分工可以这样记:
AGENTS.md定义“怎么做”,SOUL.md定义“是什么样的人”,IDENTITY.md定义身份信息。TOOLS.md和 Skills 告诉 Agent 能做什么,但工具说明和 tool schema 也会占用上下文空间。MEMORY.md、USER.md和 Daily Log 承担真正的长期记忆,既能被 Agent 写入,也能被人直接编辑。- Session 承担当前任务的工作记忆,容量有限,重要信息必须及时沉淀到文件。
OpenClaw 的记忆不是黑盒
相比常见 chatbot 的云端记忆,OpenClaw 的优势是透明和可控:
| 维度 | 豆包 / Kimi / 元宝 | OpenClaw |
|---|---|---|
| 记忆存储 | 云端黑盒,用户无法查看底层数据 | 本地 Markdown 文件,用编辑器就能打开 |
| 记忆编辑 | 只能“让 AI 忘记某件事” | 直接编辑文件,增删改查完全自由 |
| 记忆导出 | 通常不支持 | 复制文件夹即可 |
| 记忆迁移 | 通常不支持 | 复制 workspace 目录 = 克隆 Agent |
| 版本管理 | 通常不支持 | 可用 git 管理,可回滚到任意历史版本 |
4. 一条信息如何变成长期记忆
假设你在飞书里跟 Agent 说:“记住,我的技术偏好是 TypeScript,不喜欢 Java。”
第二天你重新开启对话,问它:“我喜欢什么编程语言?”它能否回答,取决于这条信息有没有从 Session 进入长期记忆文件。
从对话到文件的路径
- 你在飞书 DM 中发送消息,消息进入 Session。
- Agent 判断这是否值得长期保存,例如你明确说“记住……”。
- Agent 写入 Markdown 文件:短期观察进入 Daily Log,持久偏好进入
MEMORY.md。 - 下次会话加载
MEMORY.md和近两天 Daily Log。 - Agent 基于文件内容回答,看起来就像“记住了”。
如果查看 workspace,可能会看到类似内容:
User prefers TypeScript.
这就是 OpenClaw 记忆的本质:纯文本文件。


MEMORY.md 和 Daily Log 的分工
| 文件 | 适合放什么 | 加载规则 | 类比 |
|---|---|---|---|
MEMORY.md |
提炼后的长期事实、偏好、决策 | 每次 DM 会话加载 | 个人档案 |
USER.md |
关于用户的长期画像 | 每次 DM 会话加载 | 用户资料 |
memory/YYYY-MM-DD.md |
当天观察、过程记录、临时上下文 | 通常加载今天 + 昨天 | 工作日志 |
不要把所有东西都塞进 MEMORY.md。临时观察先放 Daily Log,确定长期有效后再提升为 MEMORY.md。
自动加载和排查方法
用 /context list 可以检查加载状态:

每个引导文件默认上限 12,000 字符,总上限 60,000 字符。Skills + Tool schemas 另外计算,约 18,000 tokens,是上下文占用的大头。
| 观察项 | 含义 |
|---|---|
OK |
文件完整加载 |
MISSING |
文件不存在 |
raw chars = injected chars |
未截断 |
raw chars ≠ injected chars |
文件被截断,需要精简 |
| Session tokens 占比 | 例如 145K / 200K = 72%,接近上限时要警惕 Compaction |
默认加载顺序大致如下:
| 优先级 | 文件 | 说明 |
|---|---|---|
| 10 | AGENTS.md |
操作规则与决策框架 |
| 20 | SOUL.md |
身份与性格 |
| 30 | IDENTITY.md |
身份信息 |
| 40 | USER.md |
用户画像 |
| 50 | TOOLS.md |
工具能力说明 |
| 60 | BOOTSTRAP.md |
启动引导脚本(可选) |
| 70 | MEMORY.md |
长期记忆 |
| 动态 | HEARTBEAT.md |
心跳配置 |
| 自动 | memory/今天 + 昨天 |
近两天的 Daily Log |
保护关键记忆的四条规则
- 关键指令写入
SOUL.md或AGENTS.md,不要只在对话中说。 - 确认
compaction.mode是"safeguard",Memory Flush 已内置,无需额外配置。 - 定期策展
MEMORY.md,保持精简,删除过时信息,避免被截断。 - 遇到“失忆”先查
/context list,判断是没写入、没加载、被截断,还是检索没命中。

5. 历史记忆如何被找回来:双引擎记忆检索
自动加载只解决“常驻文件”和“近两天 Daily Log”,那上周的记忆呢? 如果你上周在飞书跟 Agent 讨论过一个方案,今天问“上周我们讨论的那个记忆方案是什么来着?”,Agent 能回答吗? 取决于 Agent 的记忆检索配置
当 Agent 需要查找历史记忆时,会调用 memory_search,在 workspace 的记忆文件中搜索与查询相关的内容。
- 搜索范围:
MEMORY.md、USER.md、memory/*.md,以及可选 Session 历史 - 返回形式:相关片段,而不是整篇文件
- 使用方式:Agent 将片段纳入当前上下文,再基于片段回答
核心矛盾:自然语言的“模糊性” vs 技术术语的“精确性”
自然语言查询有两类需求:一类需要理解意思,一类需要精准匹配关键词。没有任何单一引擎能同时擅长这两种检索,所以 OpenClaw 使用混合检索 + 合并结果。
| 维度 | 向量语义检索 | BM25 关键词检索 |
|---|---|---|
| 原理 | 把文本转成高维向量,语义相近 = 空间距离近 | 统计查询词在文档中的出现频率和稀有度 |
| 擅长 | 自然语言查询、同义词匹配、跨语言检索 | 精确术语、代码符号、项目名、IP 地址 |
| 不擅长 | 精确 ID、错误代码、专有名词 | 同义词、措辞不同的查询 |
类比:向量 = “理解你意思”的朋友,BM25 = “只认关键词”的搜索框

典型效果如下:
| 查询方式 | 向量检索 | BM25 | 混合检索 |
|---|---|---|---|
| “上次部署服务遇到什么问题?” | ✅ 命中 | ❌ 未命中 | ✅ 命中 |
| bestcigar.org 站点的 Docker Compose 配置 | ✅ 命中 | ✅ 命中 | ✅ 命中 |
| origin not allowed 报错 | ⚠️ 可能 | ✅ 命中 | ✅ 命中 |
| “那次翻车怎么修的?” | ✅ 命中 | ❌ 未命中 | ✅ 命中 |
| allowedOrigins 配置 | ⚠️ 可能 | ✅ 命中 | ✅ 命中 |
memory_search 的默认配置通常够用
实际 openclaw.json 中需要配置 Embedding 提供商,其余混合检索参数通常沿用默认值即可:
举例:
{
"agents": {
"defaults": {
"memorySearch": {
"provider": "openai",
"model": "doubao-embedding-vision",
"remote": {
"baseUrl": "https://ark.cn-beijing.volces.com/api/coding/v3",
"apiKey": "***"
}
}
}
}
}
那么我现在没配置 embedding 模型,为什么还是能搜索?—— memory_get
memory_get 是专用的记忆文件读取器,白名单限于 MEMORY.md 和 memory/*.md。要读其他文件(SOUL/USER/AGENTS 等),必须用 read。
memory_search OR memory_get? —— 实操优先级矩阵
| 场景 | 用什么 | 为什么 |
|---|---|---|
| 知道信息在 MEMORY.md 第几行附近 | memory_get | 直读,零开销 |
| 知道日期的 daily log | memory_get memory/2026-07-01.md | 路径已知 |
| “上次聊过的 XX 项目” | memory_search | 不知道在哪天、哪段 |
| 验证某条记忆是否还准确 | memory_get 直读 | 不需要打分 |
| 跨多日搜索 | memory_search | 必须语义聚合 |
| 读 SOUL/AGENTS 等非记忆文件 | read | memory_get 不让读 |
性能与可靠性差异
| 维度 | memory_search | memory_get |
|---|---|---|
| 依赖 embedding | ✅ 是 | ❌ 否 |
| 响应速度 | 慢(向量检索 + LLM 重排) | 极快(纯文件 I/O) |
| 准确性 | 模糊匹配,可能召回噪音 | 精确,但漏掉你没指定文件的内容 |
| 适合场景 | 发现 | 验证 |
Agent 的实际工作流 按这个顺序:
1. 默认假设:信息在 MEMORY.md
└─ 直接 read / memory_get MEMORY.md
2. 找不到 / 不在 MEMORY.md
└─ 尝试 memory_search(如果可用)
3. memory_search 不可用
└─ read MEMORY.md + 用 exec ls memory/ 看看有哪些 daily log
└─ 逐个 memory_get
4. 仍然找不到
└─ 老实说"没找到",不编造
6. 实战:修正、导出和克隆记忆
对话修正错误记忆
普通 chatbot 往往只能让你说“忘掉这件事”,但 OpenClaw 可以直接查看和修正底层文件。
日常修正可以走飞书对话:
- 查看记忆(诊断):问 Agent:“你对我有哪些了解?”
- 发现问题(定位):检查返回内容,找出不准确或过时的信息。
- 修正记忆(手术):方法 A:飞书对话修正;方法 B:直接编辑 MEMORY.md
- 验证修正(复查):发送
/new开启新会话,再次询问相关问题,确认修正生效。
也可以按场景直接发指令:
你记错了,我的偏好是 X 不是 Y,请更新你的记忆。
关于 XX 项目的信息已经过时,请从记忆中移除。
我的技术栈是 TS + Python,部署用 Docker Compose。
直接编辑记忆文件
需要大批量修正、重新组织结构或理解完整记忆时,直接编辑MEMORY.md文件更准确:
修改后要重建索引,否则旧的索引数据可能残留:
openclaw memory index --force
选择方式可以按这张表判断:
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 修正一两条错误信息 | 飞书对话 | 快速,不离开对话界面 |
| 删除大量过时记忆 | 直接编辑文件 | 批量操作效率更高 |
| 重新组织记忆结构 | 直接编辑文件 | 可以调整分类、排序、格式 |
| 回滚到之前的记忆状态 | git checkout | 需要 git 管理记忆文件 |
| 理解 Agent 的完整记忆 | 查看文件 + 飞书查询 | 文件看全貌,飞书验证理解 |
导出和克隆记忆
你可以让 Agent 把自己的记忆导出成飞书文档:
请将你当前的全部记忆按照四层架构进行整理,创建一份飞书文档。按以下结构组织:
第一层·不可变内核:你的 AGENTS.md 和 SOUL.md 核心内容
第二层·工具能力:你当前安装的 Skills 列表
第三层·长期记忆:MEMORY.md 和 USER.md 的完整内容
第四层·近期笔记:最近 7 天的 Daily Log 内容
记忆克隆的本质更简单:复制 workspace 目录 = 克隆一个完整的 Agent。
记忆管理最佳实践
| 实践 | 说明 |
|---|---|
| 定期体检 | 每周在飞书中问 Agent“你对我有哪些了解”,检查是否有偏差 |
策展 MEMORY.md |
保持精简,删除过时信息,避免截断 |
| 善用 Daily Log | 临时信息放 Daily Log,只有持久事实提升到 MEMORY.md |
重要规则写 SOUL.md |
不要指望 Agent 从对话中“自行领悟” |
| 保持 safeguard 模式 | Memory Flush 已内置,遇到频繁失忆再调 reserveTokens |
| 版本管理 | 对 workspace 目录做 git 管理,可随时回滚 |
7. 实战:用 Heartbeat 敲打 Agent 遵守每日记录
Agent 不写日记?用心跳逼它养成习惯。
-
规则回顾 AGENTS.md 中写了规则:每日对话要点写入 memory/YYYY-MM-DD.md。
-
灵魂拷问 规则写了,但 Agent 真的每天都在执行吗?
-
翻车现场 打开 memory/ 目录看看真实情况。
Step 1:翻车现场——记录断档实况

Step 2:让 Agent 自己“交代问题”
纯文本规则是“软规则”。
Agent 可能因 Session 压缩、上下文丢失而不执行。
解决方案:用 Heartbeat 把“软规则”升级为“硬巡检”。
规则只是期望,机制才是保障
亚马逊内部经典理念:好的系统不靠人自觉,靠机制兜底。
在 Agent 调教中同理:SOUL.md / AGENTS.md 定义“期望行为”,Heartbeat 提供“执行保障”。
Step 3:在 HEARTBEAT.md 追加记忆巡检项
在飞书中发送:
请在 HEARTBEAT.md 的末尾追加以下内容(保留之前已有的资讯日报检查部分):
## 每日对话记忆归档检查
- **每4 小时执行一次** (00:00、04:00、08:00、12:00、16:00、20:00)
- 检查 memory/ 目录下今天的日志文件 memory/YYYY-MM-DD.md 是否存在(注意:不是 briefing 文件)
- 如果今天有过对话但日志文件不存在:
1. 回顾今天的对话要点(关键决策、学到的信息、待办事项)
2. 创建 memory/YYYY-MM-DD.md 文件并写入要点
3. 发送通知「📝 已自动归档今日对话要点」
- 如果今天没有对话记录:回复 HEARTBEAT_OK
- 如果日志文件已存在:回复 HEARTBEAT_OK
追加完成后,读回完整的 HEARTBEAT.md 给我确认。

Step 4:验证场景 A —— 没日志(预期:补写并通知)
- 确认日志不存在
今天的对话要点记录文件生成了吗?帮我检查一下
预期:Agent 确认文件不存在(今天聊了这么多但从没写过日志)。
- 触发巡检
请现在执行一次心跳巡检,特别是记忆归档检查
预期:Agent 回顾对话要点,创建日志,回复「📝 已自动归档」。
- 查看内容
把你刚创建的今日对话要点记录文件,内容发给我看看
Step 5:验证场景 B —— 日志已存在(预期:静默)
飞书发送:
请再执行一次心跳巡检,检查记忆归档
在飞书对话式触发下,Agent 会先显示在工作“敲键盘”,然后就没有任何回复了(静默)。
真正的静默验证:等下一个自然心跳周期,确认飞书无新的归档通知。
对比场景 A 和场景 B:同一个检查项,Agent 根据实际状态做出了不同决策。
8. 总结
从“金鱼记忆”到“越用越聪明”,关键不是让模型记住更多上下文,而是建立一套透明、可编辑、可检索的记忆系统。
- 记忆第一原则:如果没有写入文件,它就不存在。
- 四层架构:不可变内核、动态工具、长期记忆、实时会话,稳定性从上到下递减。
- 双引擎检索:向量理解意思,BM25 匹配关键词,混合检索互补盲区。
- 记忆完全可控:查看、修正、导出、克隆,本质上都是在管理一组 Markdown 文件。
你的 Agent 从今天起有了可编辑、可导出、可克隆的透明记忆系统。