1. 先给结论:Agent 的记忆必须落地成文件

OpenClaw 的记忆不是“模型天然记住了你说过的话”,而是由会话上下文、启动时注入的配置文件、长期 Markdown 记忆文件和检索系统共同完成。

Knowledge Takeaway
  1. 对话上下文是临时的,超过模型上下文窗口后会被压缩。
  2. 关键规则、长期偏好和重要事实必须写入文件,否则随时可能在 Compaction 后丢失。
  3. OpenClaw 的长期记忆是可查看、可编辑、可导出、可迁移的 Markdown 文件,不是云端黑盒。
  4. Agent 不是凭空“想起来”的,而是通过自动加载和 memory_search 检索把历史片段重新带回当前上下文。

社区里有一句很好用的判断标准:

If it’s not written to a file, it doesn’t exist.
如果没有写入文件,它就不存在。

—— OpenClaw 社区最佳实践

2. 为什么会失忆:Session 和 Compaction

真实事件:对齐研究员被自己的 Agent “对齐”了

Summer Yue,Meta Superintelligence Labs, Director of Alignment(对齐方向总监),曾遇到一个很典型的 Agent 失控场景:

  1. 她让 Agent 整理邮箱,明确指令:“在我确认之前不要做任何操作”。
  2. 测试邮箱运行数周,一切正常。
  3. 指向真实收件箱后,上下文窗口被撑满,Agent 开始压缩对话历史。
  4. “不要做任何操作”这个关键约束没有进入压缩后的摘要。
  5. Agent 自行批量删除 200+ 封邮件,并忽略停止命令。
  6. 她不得不跑到 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.jsoncontextTokens 中查看和设定。当会话内容接近上限时,OpenClaw 会触发 Compaction:把旧对话压缩成摘要,为后续对话腾出空间。

json-context-window

正常路径如下:

步骤 动作 说明
Step 1 Memory Flush 触发一个静默内部回合,提示 Agent 将重要内容写入磁盘文件
Step 2 Compaction 将旧对话历史压缩为摘要,最近约 20,000 tokens 保留不变
Step 3 继续会话 Agent 带着摘要和近期上下文继续工作

关键风险是:Memory Flush 是“尽力而为”的。如果一次大的工具输出让 token 突然飙升,flush 可能来不及运行就触发紧急压缩。坏路径通常是:超过上限、API 返回错误、没有 flush、紧急压缩全部历史,造成最大程度的上下文丢失。

3. OpenClaw 的四层记忆架构

OpenClaw 的记忆可以理解为四层,越往上越稳定,越往下越贴近当前对话。

OpenClaw 四层记忆架构
Layer 01

不可变内核

典型文件AGENTS.mdSOUL.mdIDENTITY.md
生命周期:长期,人工维护
加载时机:每次会话开始

Layer 02

动态工具与引导

典型文件TOOLS.mdBOOTSTRAP.md、Skills、HEARTBEAT.md
生命周期:随配置变化
加载时机:会话开始注入

Layer 03

语义长期记忆

典型文件MEMORY.mdUSER.mdmemory/YYYY-MM-DD.md
生命周期:持久,Agent + 人工维护
加载时机:DM 会话加载常驻文件和近两天 Daily Log

Layer 04

实时会话上下文

典型内容:当前 Session 消息列表
生命周期:临时,Compaction 后被压缩
加载时机:当前会话内实时存在

四层的分工可以这样记:

  1. AGENTS.md 定义“怎么做”,SOUL.md 定义“是什么样的人”,IDENTITY.md 定义身份信息。
  2. TOOLS.md 和 Skills 告诉 Agent 能做什么,但工具说明和 tool schema 也会占用上下文空间。
  3. MEMORY.mdUSER.md 和 Daily Log 承担真正的长期记忆,既能被 Agent 写入,也能被人直接编辑。
  4. Session 承担当前任务的工作记忆,容量有限,重要信息必须及时沉淀到文件。

OpenClaw 的记忆不是黑盒

相比常见 chatbot 的云端记忆,OpenClaw 的优势是透明和可控:

维度 豆包 / Kimi / 元宝 OpenClaw
记忆存储 云端黑盒,用户无法查看底层数据 本地 Markdown 文件,用编辑器就能打开
记忆编辑 只能“让 AI 忘记某件事” 直接编辑文件,增删改查完全自由
记忆导出 通常不支持 复制文件夹即可
记忆迁移 通常不支持 复制 workspace 目录 = 克隆 Agent
版本管理 通常不支持 可用 git 管理,可回滚到任意历史版本

4. 一条信息如何变成长期记忆

假设你在飞书里跟 Agent 说:“记住,我的技术偏好是 TypeScript,不喜欢 Java。”

第二天你重新开启对话,问它:“我喜欢什么编程语言?”它能否回答,取决于这条信息有没有从 Session 进入长期记忆文件。

从对话到文件的路径

  1. 你在飞书 DM 中发送消息,消息进入 Session。
  2. Agent 判断这是否值得长期保存,例如你明确说“记住……”。
  3. Agent 写入 Markdown 文件:短期观察进入 Daily Log,持久偏好进入 MEMORY.md
  4. 下次会话加载 MEMORY.md 和近两天 Daily Log。
  5. Agent 基于文件内容回答,看起来就像“记住了”。

如果查看 workspace,可能会看到类似内容:

User prefers TypeScript.

这就是 OpenClaw 记忆的本质:纯文本文件。

set-memory-1

set-memory-2

MEMORY.md 和 Daily Log 的分工

文件 适合放什么 加载规则 类比
MEMORY.md 提炼后的长期事实、偏好、决策 每次 DM 会话加载 个人档案
USER.md 关于用户的长期画像 每次 DM 会话加载 用户资料
memory/YYYY-MM-DD.md 当天观察、过程记录、临时上下文 通常加载今天 + 昨天 工作日志

不要把所有东西都塞进 MEMORY.md。临时观察先放 Daily Log,确定长期有效后再提升为 MEMORY.md

自动加载和排查方法

/context list 可以检查加载状态:

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

保护关键记忆的四条规则

关键结论
  1. 关键指令写入 SOUL.mdAGENTS.md,不要只在对话中说。
  2. 确认 compaction.mode"safeguard",Memory Flush 已内置,无需额外配置。
  3. 定期策展 MEMORY.md,保持精简,删除过时信息,避免被截断。
  4. 遇到“失忆”先查 /context list,判断是没写入、没加载、被截断,还是检索没命中。

compaction-1 compaction-2

5. 历史记忆如何被找回来:双引擎记忆检索

自动加载只解决“常驻文件”和“近两天 Daily Log”,那上周的记忆呢? 如果你上周在飞书跟 Agent 讨论过一个方案,今天问“上周我们讨论的那个记忆方案是什么来着?”,Agent 能回答吗? 取决于 Agent 的记忆检索配置

当 Agent 需要查找历史记忆时,会调用 memory_search,在 workspace 的记忆文件中搜索与查询相关的内容。

  • 搜索范围MEMORY.mdUSER.mdmemory/*.md,以及可选 Session 历史
  • 返回形式:相关片段,而不是整篇文件
  • 使用方式:Agent 将片段纳入当前上下文,再基于片段回答
关键认知:Agent 不是“想起来”的,而是“搜到”的。检索质量直接决定 Agent 的记忆质量。

核心矛盾:自然语言的“模糊性” vs 技术术语的“精确性”

自然语言查询有两类需求:一类需要理解意思,一类需要精准匹配关键词。没有任何单一引擎能同时擅长这两种检索,所以 OpenClaw 使用混合检索 + 合并结果。

维度 向量语义检索 BM25 关键词检索
原理 把文本转成高维向量,语义相近 = 空间距离近 统计查询词在文档中的出现频率和稀有度
擅长 自然语言查询、同义词匹配、跨语言检索 精确术语、代码符号、项目名、IP 地址
不擅长 精确 ID、错误代码、专有名词 同义词、措辞不同的查询

类比:向量 = “理解你意思”的朋友,BM25 = “只认关键词”的搜索框

mix-retrieval

典型效果如下:

查询方式 向量检索 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 可以直接查看和修正底层文件。

日常修正可以走飞书对话:

  1. 查看记忆(诊断):问 Agent:“你对我有哪些了解?”
  2. 发现问题(定位):检查返回内容,找出不准确或过时的信息。
  3. 修正记忆(手术):方法 A:飞书对话修正;方法 B:直接编辑 MEMORY.md
  4. 验证修正(复查):发送 /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 不写日记?用心跳逼它养成习惯。

  1. 规则回顾 AGENTS.md 中写了规则:每日对话要点写入 memory/YYYY-MM-DD.md。

  2. 灵魂拷问 规则写了,但 Agent 真的每天都在执行吗?

  3. 翻车现场 打开 memory/ 目录看看真实情况。

Step 1:翻车现场——记录断档实况 missing-memory-folder agents-memory-rules

Step 2:让 Agent 自己“交代问题” daily-log-check-1 daily-log-check-2 纯文本规则是“软规则”。 Agent 可能因 Session 压缩、上下文丢失而不执行。

解决方案:用 Heartbeat 把“软规则”升级为“硬巡检”。

规则只是期望,机制才是保障

—— 亚马逊领导力原则(Insist on the Highest Standards)

亚马逊内部经典理念:好的系统不靠人自觉,靠机制兜底。

在 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 给我确认。

heartbeat-file

Step 4:验证场景 A —— 没日志(预期:补写并通知)

  1. 确认日志不存在
今天的对话要点记录文件生成了吗?帮我检查一下

预期:Agent 确认文件不存在(今天聊了这么多但从没写过日志)。

  1. 触发巡检
请现在执行一次心跳巡检,特别是记忆归档检查

预期:Agent 回顾对话要点,创建日志,回复「📝 已自动归档」。

  1. 查看内容
把你刚创建的今日对话要点记录文件,内容发给我看看

Step 5:验证场景 B —— 日志已存在(预期:静默)

飞书发送:

请再执行一次心跳巡检,检查记忆归档

在飞书对话式触发下,Agent 会先显示在工作“敲键盘”,然后就没有任何回复了(静默)。

真正的静默验证:等下一个自然心跳周期,确认飞书无新的归档通知。

对比场景 A 和场景 B:同一个检查项,Agent 根据实际状态做出了不同决策。

8. 总结

本章小结

从“金鱼记忆”到“越用越聪明”,关键不是让模型记住更多上下文,而是建立一套透明、可编辑、可检索的记忆系统。

  1. 记忆第一原则:如果没有写入文件,它就不存在。
  2. 四层架构:不可变内核、动态工具、长期记忆、实时会话,稳定性从上到下递减。
  3. 双引擎检索:向量理解意思,BM25 匹配关键词,混合检索互补盲区。
  4. 记忆完全可控:查看、修正、导出、克隆,本质上都是在管理一组 Markdown 文件。

你的 Agent 从今天起有了可编辑、可导出、可克隆的透明记忆系统。