乐于分享
好东西不私藏

openclaw记忆系统全方位分析

openclaw记忆系统全方位分析

深度体验 OpenClaw(小龙虾)一段时间后,我已经基于它搭建了自媒体自动发布、数据分析、设备故障诊断等多个 Skill,实战下来一个非常明确的感受:在程序员这个方向上,它真的能替代掉 80% 的日常工作。

但想真正用好小龙虾,绝不是停留在 “会用” 的层面,而是要吃透它的底层架构与设计思想。只有理解核心机制,才能把它用成真正的生产力工具,而不是简单的玩具。

今天,我先从它最关键、最核心的记忆系统入手,做一次完整拆解与分析。

源码:https://github.com/openclaw/openclaw

核心定位与架构

  • 核心原则:Markdown 文件为唯一事实来源,拒绝黑盒,所有记忆落地为本地可编辑的纯文本文件。
  • 默认插件:由 memory-core 提供记忆搜索工具,可通过 plugins.slots.memory = "none" 禁用。  
    源码:https://github.com/openclaw/openclaw/tree/main/extensions/memory-core
  • 存储路径:默认位于工作空间 ~/.openclaw/workspace,可通过agents.defaults.workspace 配置。

双层记忆体系

记忆层级
路径(记忆文件)
核心作用
加载规则
短期记忆memory/YYYY-MM-DD.md
记录当日对话、决策与临时上下文,仅追加模式
会话启动自动加载今日 + 昨日
长期记忆MEMORY.md
(可选)
存储用户偏好、长期约定、核心决策等持久化信息
仅在主私人会话加载,群组会话不加载

何时写入记忆

什么时候写入长期记忆

满足以下任意一种 → 必须写入 MEMORY.md

  1. 个人偏好、习惯、风格设定
  2. 重要决策、规则、约定
  3. 需要永久记住的事实、知识
  4. 用户明确说:记住这个
  5. 需要跨会话、跨天保留的内容

总结:要永久记住、反复使用、不会过期的 → 长期记忆

举例:当我在对话框输入保存文件到哪个地方,自动会写入MEMORY.md

什么时候写短期记忆

满足以下任意一种 → 写入 当日短期记忆文件

  1. 当天的对话、上下文
  2. 当天的任务、待办、临时信息
  3. 当天的运行日志、中间结果
  4. 不需要长期保存、只在近期有用的内容
  5. 不需要跨天长期记住的临时信息

总结:当天用、近期用、会过期、临时的 → 短期记忆

memory/YYYY-MM-DD.md  此文件夹默认没有,触发会生成。

举例:存天气

自动记忆刷新

  • 触发时机会话 Token 接近压缩阈值时(由 softThresholdTokens 控制,默认软阈值为上下文窗口 - 预留 Token - 4000)。
  • 行为:静默触发智能体回合,提醒将关键信息写入持久化文件,用户无感知(默认响应 NO_REPLY)。
  • 配置:通过 agents.defaults.compaction.memoryFlush 启用 / 禁用,需保证工作空间可写。
{  agents:{    defaults:{      compaction:{        reserveTokensFloor:20000,        memoryFlush:{          enabled: true,          softThresholdTokens:4000,          systemPrompt:"Session nearing compaction. Store durable memories now.",          prompt:"Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store.",},},},},}

记忆管理工具

Agent 可通过显式工具操作记忆,核心工具如下:

工具名
功能
适用场景
memory_search
按关键词 / 语义检索记忆片段
快速查找历史笔记、用户偏好
memory_get
按路径读取完整记忆文件
展开详细上下文
memory_store
显式写入记忆(支持长期 / 会话级)
手动固化关键信息
memory_forget
删除指定记忆
清理冗余 / 错误信息

记忆工具的工作原理

  • memory_search = 语义搜索记忆片段 → 不读全文
  • memory_get = 精准读取某个文件 → 可读部分行
  • 都必须开启 memorySearch.enabled 才能用
  • 文件访问有权限控制,不能乱读

1. memory_search到底做什么?

  1. 搜哪里?

    搜两个地方:

    • 根目录 MEMORY.md
    • memory/ 文件夹下所有 .md 文件(所有日记、短期记忆)
    • 可能还有历史会话片段 (后文会说明历史会话片段搜索机制
  2. 怎么搜?

    语义搜索不是搜关键词,是搜意思

    比如你问 “我喜欢什么颜色”,它能找到 “用户偏爱蓝色”。

  3. 怎么切分内容?

    把文件切成一块一块

    就像把书切成一页一页,但页边重叠一点,保证句子不被砍断。

    • 每块大约 400 token
    • 块和块之间重叠 80 token(防止切断语义)
  4. 返回什么?

    • 片段内容(一小段,最多 700 字符)
    • 哪个文件
    • 第几行到第几行
    • 匹配分数
    • 用了什么模型
  5. 绝对不返回什么?

    不返回完整文件!

    不会把整个 MEMORY.md 扔给模型,只会扔最相关的一小段

2. memory_get到底做什么?

  1. 干什么?

    直接读文件内容不是搜,是读取

  2. 怎么读?

    你告诉它:

    • 读哪个文件(相对路径)
    • 从第几行开始
    • 读多少行
  3. 能读哪些文件?

    默认只能读:

    想读其他文件?

    必须配置在 memorySearch.extraPaths 才能读 ,否则不让读,安全限制。

    • MEMORY.md
    • memory/ 下的文件

支持通过 memorySearch.extraPaths 配置索引非工作空间的 Markdown 文件(绝对 / 相对路径均可),实现跨目录记忆整合。  (记忆不一定要保存到.openclaw中,可以灵活寻找保存路径)

额外记忆路径配置

agents: {  defaults: {    memorySearch: {      extraPaths: ["../team-docs""/srv/shared-notes/overview.md"]    }  }}

3. 共同限制:必须开启才能用

配置里必须打开:

memorySearch.enabled = true  //决定两个工具

如果是 false,memory_search 和 memory_get 都不能用,Agent 完全无法访问记忆。

模型搜索记忆机制

OpenClaw 的记忆搜索 :混合搜索,向量搜索(懂意思,不懂精确字符) + BM25 关键词搜索(懂精确字符,不懂意思

模型索引记忆内容及时机

1. 索引什么内容?(文件类型)

仅 Markdown文件类型,包含:MEMORY.md、memory/*/.md,以及 memorySearch.extraPaths 下的任何 .md 文件

2. 索引存在哪?(索引存储)

  • 索引不是存在文本,是存在 SQLite 数据库
  • 每个智能体(Agent)独立一个库,互不干扰
  • 路径长这样:
   ~/.openclaw/memory/xxx-xxx-xxx.sqlite
  • 可以配置路径,支持 {agentId} 占位符

3. 索引新鲜度(最重要、最核心)

a、监视器一直在盯着你的记忆文件

你改了 MEMORY.md 或日记,系统立刻知道

b、但不会马上更新索引,而是等 1.5 秒(去抖动)

文件修改后,OpenClaw 不会立刻更新索引,而是等 1.5 秒没再改动,才真正执行一次索引同步。

c、真正更新索引的时机

只会在这 3 种时候异步更新

  1. 新开会话
  2. 执行记忆搜索
  3. 定时自动更新

好处:不卡、不占资源、不影响速度

4. 重新索引触发器(模型 / 配置一变就全量重建)

这是安全机制,保证搜索永远准确:

只要你改了以下任意一项:

  • 向量模型(本地 / OpenAI/Gemini)
  • 模型名称变了
  • API 地址变了
  • 分块大小变了
  • 重叠 token 变了

系统就知道:

旧索引作废 → 自动全部删掉 → 重新全量建索引

你完全不用管,它自己处理。

本地电脑查看样子:

会话记忆搜索

会话记忆让 Agent 拥有了 “完整历史视角”,但它依然遵循文件优先、本地优先、安全隔离的设计原则。

会话索引是选择加入的(默认关闭)。

  • 会话记忆 = 让 Agent 搜历史聊天
  • 默认关闭,手动开启
  • 后台索引,不卡界面
  • 达到 100KB / 50 条 才索引  (可根据参数改)
  • 只能搜片段,不能读全文
  • 每个 Agent 独立隔离
  • 存在本地磁盘,注意权限

你可以选择性地索引会话记录并通过 memory_search 呈现它们。

agents: {     defaults: {         memorySearch: {             experimental: {                 sessionMemory: true             },             sources: ["memory""sessions"        }     } }

配置参数

agents:{    defaults:{        memorySearch:{            sync:{                sessions:{                    deltaBytes:100000// ~100 KB                     deltaMessages:50// JSONL 行数 }}}}}

其他

嵌入缓存

支持 SQLite 缓存块嵌入,这样重新索引和频繁更新(特别是会话记录)不会重新嵌入未更改的文本。,默认最大缓存条目 50000。

defaults: {memorySearch: {cache: {enabled:true,maxEntries:50000      }    }  }}

安全与边界

  • 隔离性:多 Agent 记忆完全隔离,按 Agent ID 独立存储索引与向量。
  • 隐私保护MEMORY.md 仅在私人会话加载,群组会话不加载,避免敏感信息泄露。
  • 信任边界:会话日志存储于本地磁盘,需注意磁盘访问权限管控。