很多人辛辛苦苦养的小龙虾,都会在某个时刻让主人产生一种挫败感:

  • 昨天刚说过的偏好,今天新开一个会话又得重讲;
  • 明明说了"记住这个",过几天再问,它像没听过;
  • 会话越长,助手越像"注意力涣散",前面已经确认过的事,后面又绕回来。

这类问题看起来像"小龙虾变笨了",怀疑给虾使用的大模型不够智能?其实大多数时候都不是模型能力问题,而是记忆机制没有被正确使用

(本文所说的小龙虾,通过 OpenClaw 部署。研究对象也是 OpenClaw。接下来将统一口径,使用 OpenClaw 来称呼。)

OpenClaw 的记忆系统并不神秘。恰恰相反,它非常工程化:记忆不是藏在黑盒里的,而是落在工作区里的 Markdown 文件、会话历史和检索索引里。 你理解了这套机制,很多"为什么它会忘"的问题都会立刻变清楚。

这篇文章在深入研究 OpenClaw 官方文档、拆解源代码之后,讲清楚三件事:

  1. OpenClaw 到底靠什么"记住"你;
  2. 为什么它会忘;
  3. 怎样把它调到一个长期稳定、可维护的状态。

一、先把一个认知纠正过来:模型本身不会跨会话记忆

大语言模型并不会像人一样,把昨天的对话自然带到今天。

它每次能看到的,只有本轮请求被送进上下文窗口的内容。如果某条信息没有进入当前上下文,模型就等于没看见;如果某条信息从来没有被写到磁盘,下次重启后也就无从谈起。

这也是 OpenClaw 记忆设计最核心的一条原则:

文件才是记忆的唯一可信来源。

按照 OpenClaw 当前官方文档,记忆是工作区中的纯 Markdown 文件:模型只会"记住"那些被写入磁盘、并在合适时机重新加载或检索出来的内容。

这件事听上去朴素,但它带来一个非常重要的推论:

  • “我已经在对话里说过了”,不等于"它下次还会记得";
  • “它刚才答应会记住”,不等于"它已经落盘";
  • “它知道我是什么意思”,不等于"这条信息已经进入长期记忆层"。

如果你把 OpenClaw 当作一个有天然长期记忆的大脑,就很容易失望;如果你把它当作一个带文件系统、检索和压缩机制的 Agent 运行时,它的行为反而会变得非常可预测。


二、从使用体验看,OpenClaw 实际上有三层"记忆"

官方文档在"记忆文件"这一层主要讲两种载体:MEMORY.mdmemory/YYYY-MM-DD.md。但从实际使用体验看,OpenClaw 的"记得住"与"记不住",是三层机制共同作用的结果:

层级载体作用典型内容
工作记忆当前会话历史维持本轮任务的连续性刚才的问答、工具调用结果、当前任务状态
短期记忆memory/保留近期上下文和运行日志会话摘要、日常运行记录、短期上下文
长期记忆MEMORY.md保留跨会话稳定信息偏好、长期事实、重要决策、环境约定

这三层各自解决的是不同问题。

1. 工作记忆:负责"眼前这件事"

当前会话历史就是工作记忆。它保证 OpenClaw 在同一段对话里还能接着前文往下走。

但它有天然上限:上下文窗口一满,就会进入压缩或裁剪流程。所以工作记忆是最不可靠的一层——适合维持当前任务,不适合承担长期保存。

2. 短期记忆:负责"最近发生了什么"

memory/ 目录可以理解成短期记忆层。官方文档把 memory/YYYY-MM-DD.md 定义为只追加、不覆盖的当日日志:今天和昨天的文件会在会话启动时读取,更早的内容主要通过 memory_search / memory_get 召回。

这一层解决的不是"长期沉淀",而是"最近发生了什么"。它更像一块短期缓冲区,用来保存近期任务推进过程中仍然可能被反复提及的信息。

这一层适合存:

  • 今天修了什么 bug;
  • 刚确认过的需求变更;
  • 会话里出现的短期结论;
  • 最近两天内可能反复提及的运行上下文。

3. 长期记忆:负责"哪些信息应该稳定存在"

MEMORY.md 是精选过的长期记忆。它不是流水账,而是一份经过筛选的长期知识。

适合写进去的通常是:

  • 你的沟通偏好;
  • 团队或项目的长期约定;
  • 不应反复解释的环境信息;
  • 重要决策及其背景。

官方文档明确说明:MEMORY.md 只在主私聊会话中加载,不会在群聊场景里自动带入。这是有意设计的隐私边界,而不是缺陷。


三、真正决定"记性"的,不只是 MEMORY.md,而是整个工作区

很多人把"记忆系统"理解成 MEMORY.md 一个文件。其实不够准确。

OpenClaw 的工作区默认在 ~/.openclaw/workspace。对记忆表现影响最大的,往往是下面几类文件:

文件作用
AGENTS.md告诉助手怎么工作、什么时候写记忆、什么信息该写到哪里
TOOLS.md记录本机环境、工具约定、常用路径与注意事项
SOUL.md / IDENTITY.md / USER.md定义助手是谁、服务谁、说话风格和边界
MEMORY.md长期记忆
memory/短期记忆文件、会话摘要和运行记录

这里最关键的,其实往往是 AGENTS.md

因为"是否主动写记忆"“什么该进长期记忆、什么只记到日记里”,本质上是行为规则问题,而不是模型自发会不会做人情判断的问题。你如果没有在 AGENTS.md 里把这件事说清楚,助手就只能凭默认行为猜。

一个够用的最小规则可以非常简单:

## Memory Rules
- 用户说"记住这个"时,立即写入当前的短期记忆文件
- 偏好、长期约定、环境事实、重要决策,整理后写入 `MEMORY.md`
- 在会话结束前,主动检查是否有值得持久化的信息
- 任何没有写入文件的信息,都不应假定为"已经记住"

这段规则的价值不在于"优美",而在于它把一个模糊习惯变成了可执行的工程约束。

还有三个容易被忽略的工作区细节

根据 OpenClaw 的官方文档:

  • 工作区注入文件有字符上限:默认单文件 20,000 字符总计 150,000 字符,超出会被截断;
  • 缺失的引导文件不会让系统崩溃,但会注入一条 missing file 标记;
  • 子 Agent 会话默认只注入 AGENTS.mdTOOLS.md,不会自动继承 MEMORY.mdUSER.md 等其他内容。

所以,如果你发现"主会话明明知道的事,子 Agent 却像第一次听说",那大概率不是检索坏了,而是上下文本来就没带过去

你可以用这些命令核对现实情况:

/context list
/context detail
/status

这一步很重要。很多关于"记忆失效"的讨论,最后追根溯源,问题其实出在:你以为它加载了,实际上它没有。


四、到底什么该写进 MEMORY.md,什么该留在 memory/ 里?

一个实用的判断标准是:看它是"稳定事实",还是"运行过程"。

同时也别把 memory/ 理解得过于整洁。真实运行里,它常常就是:

  • memory/YYYY-MM-DD.md 这种按天累计的主日记文件;
  • memory/YYYY-MM-DD-slug.md 这种按任务保存的会话快照;
  • 以及少量人工整理的补充文件。

对 OpenClaw 来说,它们都能被索引;对人类来说,则需要后期修剪和提炼。尤其如果你关心"新开一个会话后它能不能立刻接上前文",最值得维护的仍然是 memory/YYYY-MM-DD.md,因为默认启动序列直接读的是它。

应该写入 MEMORY.md 的内容

  • 长期有效的沟通偏好;
  • 项目的长期规范;
  • 常用环境和基础设施约定;
  • 重要联系人与协作方式;
  • 关键技术决策及其日期。

例如:

# 长期记忆

## 沟通与产出偏好
- 回复先给结论,再展开依据
- 默认用中文写文档,术语保留英文
- 不需要寒暄式开场

## 工程约定
- 后端主语言为 Go,前端为 React
- 默认把可观察性问题归档到 Grafana 看板,而不是口头记录

## 重要决策
- 2026-03:停止维护 v1,资源集中到 v2

应该写进 memory/YYYY-MM-DD.md 的内容

  • 今天修了什么;
  • 某个需求临时如何取舍;
  • 某次会议确认的动作项;
  • 最近两天内很可能还会继续追问的上下文;
  • 还没沉淀成长期记忆、但短期内需要延续的信息。

例如:

# 2026-03-18

- 修复导出报表在 DST 切换时的时间边界错误
- 客户确认 Q2 续签,并提出新增培训服务模块
- 下周一补一份导出链路压测报告

你还会在 memory/ 目录里看到 YYYY-MM-DD-slug.md

除了主日记文件,memory/ 目录里还经常会出现 2026-03-18-video-prompt.md2026-03-18-telegram-fix.md 这种文件。

这类文件通常不是你手动维护的主日记文件,而是内置 session-memory hook 在 /new/reset 时自动生成的会话快照。它的作用更像"把刚刚那段会话留一个摘要副本",方便后续回溯和检索,而不是承担今天的连续上下文。

它的常见格式大致像这样:

# Session: 2026-03-18 09:14:08 UTC

- **Session Key**: agent:main:telegram:group:-123456789
- **Session ID**: abc123
- **Source**: telegram

## Conversation Summary

user: 导出报表还是有问题,DST 切换那天数据错了
assistant: 已确认是时间边界处理错误,准备修复

理解这一点很重要:memory/YYYY-MM-DD.md 是主日记文件,memory/YYYY-MM-DD-slug.md 是某次具体会话的快照文件。 前者偏"今天持续发生了什么",后者偏"刚刚那次任务聊了什么"。

不建议直接塞进长期记忆的内容

  • 原始聊天流水;
  • 冗长会议纪要全文;
  • 大量随时会过期的待办明细;
  • 工具返回的原始日志;
  • 只在当前任务里有效的临时上下文。

很多人把 MEMORY.md 当成"什么都往里放的总仓库",这是最常见的误用之一。MEMORY.md 一旦膨胀,它就会在每个会话启动时稳定消耗上下文预算,最后拖累的不是记忆量,而是整体响应质量。

反过来说,memory/ 里那类对话摘录风格的文件并不是"错",它们本来就更像采集层。真正需要管理的,是噪声密度:把高价值信息提炼进 MEMORY.md,把仍需短期延续的内容补进当天的 memory/YYYY-MM-DD.md,再删掉已经过时的噪声。


五、memory_search 到底在搜什么?先理解 Embedding

OpenClaw 的 memory_search 不是普通的关键词搜索。

它的核心是向量检索。按照 OpenAI 官方的 Embeddings 文档,Embedding 本质上是把一段文本编码成一个向量;语义接近的文本,在向量空间里的距离也会更近。于是,系统就能在"措辞不同,但意思接近"的情况下把内容找回来。

这就是为什么你问:

  • “上次关于数据库性能的讨论在哪?”

它有机会命中一条并没有写"数据库性能",而是写了"延迟抖动、迁移到 Go、压测结果"的历史记录。

memory_searchmemory_get 的分工

  • memory_search:先根据语义把相关片段找出来;
  • memory_get:拿到路径后,定点读取某个文件或某一段内容。

前者像"回忆",后者像"翻原件"。

为什么配好了聊天模型,搜索仍然可能是坏的?

因为聊天模型和 Embedding 模型不是同一回事

根据 OpenClaw 当前官方文档,memory_search 默认会尝试自动选择 Embedding 提供方:优先本地模型(如果你显式配置了本地路径),否则依次尝试 OpenAI、Gemini、Voyage、Mistral;如果都不可用,记忆搜索就会保持禁用状态。Ollama 也支持,但不会被自动选中,需要手动配置。

这意味着:

  • 你能正常聊天,不代表记忆搜索已经可用;
  • 你配的是聊天 API Key,不代表 Embedding 也自动就绪;
  • 搜索返回空结果,不一定是"没记住",也可能是"根本没建索引"。

最直接的排查方式仍然是:

openclaw status --deep

Memory Search 是否处于激活状态。

技术内容多时,建议开启混合搜索

纯向量检索擅长语义召回,但对这类信息不一定稳定:

  • 错误码;
  • 函数名、类名;
  • 精确的人名、服务名;
  • 很短但很关键的标识符。

所以 OpenClaw 提供了混合检索(hybrid search),把 BM25 的关键词匹配和向量检索结合起来。对工程场景来说,这往往比"全语义化"更靠谱。

{
  "agents": {
    "defaults": {
      "memorySearch": {
        "query": {
          "hybrid": {
            "enabled": true,
            "vectorWeight": 0.7,
            "textWeight": 0.3
          }
        }
      }
    }
  }
}

如果你的短期记录里经常出现接口名、错误码、组件名,这个配置通常值得开。


六、为什么"越聊越忘"?把压缩、记忆刷新、修剪分开看

很多文章喜欢把这些机制混在一起讲,最后读者越看越乱。其实它们是三件不同的事。

1. 上下文压缩(Compaction)

当上下文太长时,OpenClaw 会把较早的对话整理成摘要,以便继续对话。这解决的是上下文窗口有限的问题。

代价是:如果某条重要信息只存在于早期对话、还没写进记忆文件,那么压缩之后,它通常就只剩下"被总结过的版本",细节可能丢失。

2. 记忆刷新(Memory Flush):压缩前,先提醒模型把该落盘的内容写下去

OpenClaw 现在支持压缩前记忆刷新:当会话接近压缩阈值时,系统会触发一个静默轮次,提醒模型先把耐久信息写入记忆文件,再进行压缩。

这是一道很实用的保险,但不要把它理解成"从此不用管记忆写入了"。它只是兜底机制,不是替代人工建模的魔法。

3. 会话修剪(Session Pruning):临时删减旧工具结果

contextPruning 解决的是另一类问题:长对话里,工具返回结果可能非常大,旧的 toolResult 会持续占用模型上下文。

OpenClaw 当前文档明确说明:

  • pruning 只会在发起模型调用前,临时裁掉旧的工具结果;
  • 不会改写磁盘上的会话历史
  • 它和 compaction 是两套机制;
  • 当前主要针对 Anthropic / OpenRouter Anthropic 模型链路生效。

这一点和 Anthropic 官方的提示缓存(prompt caching)文档正好能对上:Anthropic 的提示缓存默认 TTL 是 5 分钟,也支持 1 小时。OpenClaw 的 TTL 感知修剪,本质上是在缓存过期后,尽量减少下一次需要重新缓存的大块旧上下文,控制成本和延迟。

所以,“越聊越忘"不一定是记忆写坏了,也可能只是:

  • 会话历史被压缩了;
  • 旧工具结果被裁掉了;
  • 真正该落盘的信息从来没被写进 MEMORY.mdmemory/

七、最容易踩的六个坑

坑 1:改了工作区文件,却在旧会话里等它生效

工作区文件是在会话启动时注入的。你改完 AGENTS.mdTOOLS.mdMEMORY.md当前会话不会自动"重新读一遍”

通常要发 /new 开新会话,再观察变化。

坑 2:把 MEMORY.md 写成第二个知识库

MEMORY.md 不是越长越好。它每次启动都会消耗上下文预算。真正应该长期保留的是"稳定、稀疏、重要"的信息,而不是所有历史。

如果一份 MEMORY.md 已经长到你自己都不愿意读第二遍,它大概率已经该拆了。

坑 3:把"记住这个"留在嘴上,没有真的落盘

这是最本质的坑。模型说"好的,我记住了",不代表记忆已经持久化。只有文件变了,才算真的记住。

坑 4:多人私聊还在共用主会话

OpenClaw 文档当前仍然说明,私聊的基础默认语义是 dmScope: "main",也就是所有私聊共享主会话;不过较新的本地 CLI 引导流程在未显式设置时,会自动写入 per-channel-peer,以降低多用户场景的泄露风险。

因此,真正危险的往往是:

  • 较早安装的旧配置;
  • 手动搭建但没认真检查 dmScope 的实例;
  • 一个机器人账号被多个人同时私聊。

多人场景里,建议显式核对:

openclaw security audit

并把 session.dmScope 设为 per-channel-peer 或更细粒度模式。

坑 5:子 Agent 不知道主会话知道的事

这是设计使然。子 Agent 默认只带 AGENTS.mdTOOLS.md,不自动继承 MEMORY.md

如果某个子任务必须依赖项目背景,就应该在派生任务时显式传递,或者把真正通用的项目规则提前沉淀到 AGENTS.md / TOOLS.md

坑 6:以为搜索"没搜到",其实是 Embedding 没配好

能聊天,不等于能检索。这个坑尤其常见。

如果 openclaw status --deep 里 Memory Search 没激活,先修配置,再谈召回质量。


八、对工程实践最有用的,不是"记更多",而是"记得更有结构"

如果你把 OpenClaw 当作一个长期协作的 Agent,而不是一次性聊天工具,那么真正重要的不是"让它尽量记住一切",而是建立一套清晰的记忆治理方式。

我自己的建议是四条:

1. 把记忆当成数据建模问题,而不是人格魔法

长期事实、短期流水、当前会话,天然就不是一类东西。分层之后,很多混乱会自己消失。

2. AGENTS.md 负责规则,MEMORY.md 负责长期事实,memory/ 负责短期过程

不要让一个文件承担三种职责。职责混了,后期就一定难维护。

3. 长期记忆要"精选",短期记录要允许真实和嘈杂

长期记忆宁可少,不要虚;短期记录不必假装很整齐,但最好别永远不整理。

“今天开了个会"几乎不可检索;“确认客户要把导出格式从 Excel 扩展到 PDF/CSV"就很容易在几周后被找回来。

4. 定期检查上下文和记忆成本

至少要养成两个习惯:

/context detail
openclaw status --deep

前者看上下文被谁吃掉了,后者看记忆搜索是不是真的在工作。

如果你打算长期使用 OpenClaw,工作区最好放进私有 Git 仓库备份。因为对一个 agent 来说,工作区文件不是"配置边角料”,它们本身就是能力的一部分。


九、你需要知道的限制

OpenClaw 的记忆系统很强,但它不是一套会自动自净、自动整理、自动去噪的系统。它更像一个可持续写入、可持续检索的记忆层;至于质量如何,很大程度上取决于你怎么使用它。

1. 短期记录会变嘈杂

如果你长期只写不整理,memory/ 里的内容会越来越嘈杂。尤其是对话摘录风格的会话摘要,天然会混入大量低价值对话、重复确认和运行时噪声。

所以,OpenClaw 的记忆不是"越多越好”,而是需要定期修剪、归纳和提炼。高价值信息应该上浮到 MEMORY.md,低价值流水则应该允许它自然过时,或者在后续整理中删除。

2. 语义搜索很好用,但并不完美

memory_search 的确解决了"措辞不同也能找回"的问题,但它不是全知全能。坏查询会发生,模糊查询会发生,召回偏差也会发生。

你问得越含混,结果就越不稳定;你记录得越空泛,后续就越难找回来。换句话说,检索质量既取决于 Embedding,也取决于你当初写下来的内容质量。

3. 上下文窗口依然是硬约束

记忆可以跨会话存活,不代表你能把无限材料一次性装进同一个提示词上下文。上下文窗口、压缩机制、工具结果裁剪,这些限制始终都在。

OpenClaw 真正解决的是"写下来,之后还能找回来",而不是"永远把所有东西同时装在脑子里"。

4. 但即便如此,这仍然是 Agent 最稳妥的一条路

即使有这些限制,先写下来,再在需要时检索出来,仍然是目前 Agent 体系里非常扎实的一种记忆建模方法。

它的优点不是完美,而是:

  • 透明;
  • 可编辑;
  • 可调试;
  • 可持续改进。

这比"模型似乎记得、但你不知道它到底怎么记得"的黑盒方案,更适合长期协作。


十、如何安全编辑记忆

OpenClaw 记忆系统最好的地方,其实不是"它会记",而是你能改。这意味着它不是一个不可控的黑盒,而是一套你可以直接维护的数据层。

一个很实用的原则是:

  • 如果 OpenClaw 记错了,直接编辑它;
  • 如果某条信息已经过时,直接删掉;
  • 如果你希望某种行为更稳定,不要只写进记忆,应该放进总是会加载的文件。

具体来说:

1. 记错了,就改

不要把错误记忆当成"模型性格的一部分"。记忆文件既然是唯一可信来源,最稳的修复方式就是直接改文件,而不是反复在对话里口头纠正。

2. 过时了,就删

OpenClaw 的记忆层不会自动自净。旧约定、失效事实、错误联系人、已经结束的短期项目,如果还留在文件里,就会持续污染后续检索。

所以,删除过期信息不是"损失记忆",而是在做必要的维护。

3. 想要更强的行为变化,就放进 USER.mdSOUL.md

这一点特别重要。MEMORY.md 更适合放事实、偏好、长期背景;但如果你想改变的是更稳定的行为方式,比如:

  • 回复风格更直接;
  • 默认先给结论;
  • 不要寒暄;
  • 某类场景下更谨慎或更克制;

那么把这些内容写进 USER.mdSOUL.md,通常比写进 MEMORY.md 更稳,因为它们是每次 session 都会加载的。

如果是工作方式或执行流程层面的规则,则优先放进 AGENTS.md

换句话说:

  • MEMORY.md:记住什么事实;
  • USER.md / SOUL.md:决定你希望它长期怎么说、怎么表现;
  • AGENTS.md:决定它怎么做事。

这也是 OpenClaw 这套设计里最可贵的地方:记忆不是只能接受,你可以直接治理。


结语

OpenClaw 的记忆系统,真正值得欣赏的地方,不是它"像人一样会记住",而是它足够透明、足够工程化、足够可调试

你可以知道它记忆放在哪里; 你可以检查哪些内容进入了上下文; 你可以区分是"没写入"、还是"没加载"、还是"没搜到"。

这比一个看似聪明、实则不可解释的黑盒记忆系统,更适合长期使用,也更适合工程化协作。

如果要把全文浓缩成一句话,那就是:

OpenClaw 不是自己"有记性",而是你替它设计了一套可持久化、可检索、可压缩的记忆系统。

理解这一点之后,你就不会再把"它忘了"看成玄学,而会把它当成一个可以定位、可以修复、可以持续优化的工程问题。


参考资料