6.3 记忆机制:写入、检索与失效
本节以官方记忆系统为准讲清“记忆存在哪里、怎样被检索、怎样避免污染”。OpenClaw 的长期记忆以工作区文件为中心,并配套向量索引与内置记忆工具(例如 memory_search、memory_get)。掌握这些机制后,才能把记忆从“越积越乱”变成“可维护资产”。
6.3.1 双层记忆结构:MEMORY.md 与每日日志
根据官方设计,OpenClaw 的记忆基于“文件即真相(files are the source of truth)”的思想存储于工作区,主要由两层组成:
长期记忆(
MEMORY.md):存放精选持久化偏好、配置决定与沉淀经验,放在工作区根目录。安全与隐私边界:据官方文档约束,
MEMORY.md仅在 私聊主会话(direct chat) 中被加载约束,绝不会在群组会话(group chat)中注入,从而保护用户的私密信息。
每日日志(
memory/YYYY-MM-DD.md):存放阶段性项目进展、当天的探讨细节。会话启动时,系统默认只会读取“今天加昨天”的文件数据来维系短期事件的连贯性。
这种设计的工程意义是:把“可复用事实”与“过程噪声”分开,让事后的检索与上下文注入保持清爽的信噪比。
6.3.2 写入规则与时机:只记有价值的事实
官方关于“何时写入记忆”的 最佳实践 建议如下:
写入
MEMORY.md:记录高价值的用户偏好、重要决策或稳定状态配置。写入
memory/YYYY-MM-DD.md:记录频繁但阶段性的开发操作、项目调试进度的日常流水。立即写入:无论何时,当用户明确表达“记住这个(remember this)”时,第一时间将该条目持久化。
此外,记忆写入最常见的失败是 把推测当成了事实。我们建议把写入规则收敛为以下硬约束:
稳定:跨会话复用,短期不易过期。
可追溯:必须来自工具明确回执或有显式确诊依据,而不是基于大模型的一句猜测推理。
可纠错:允许随时撤销更新替换,拒绝将错误信息永久固化。
实战防坑:坏记忆与好记忆
❌ 坏记忆(模型的主观推测或短时情绪记录):“用户今天好像心情不好,且遇到了一个难以排查的 Node.js OOM BUG。”这种文字明天就失效了,且浪费 Token。
✅ 好记忆(客观、可追溯的事实与参数配置):“用户偏好默认在工作流脚本中使用 Python。当前生产 Kubernetes 集群为
prod-cluster-us,且需使用指定服务账号运维(来源:2月20日会话)。”
操作示例:在 MEMORY.md 用结构化小节记录事实,并附带来源与更新时间;在 memory/YYYY-MM-DD.md 记录过程性日志。
6.3.3 检索机制:混合向量搜索与精确读取
针对盘子里的(MEMORY.md 加上 memory/**/*.md)诸多碎片,官方记忆工具提供了两种主流手段取数:
记忆搜索:
memory_search— 默认采用 混合搜索算法(BM25 加上 向量相似度),将数据切成小块(400 token/分块并设置小额重叠带)。返回带详细文件路径和行号的查询片段。精确读取:
memory_get— 基于已有依据读取内容,精确命中特定行,防污染。
常见配置陷阱:embedding API 密钥依赖
memory_search 的向量检索后端需要独立的 embedding API 密钥(OpenAI、Gemini 或 Voyage),即使主对话模型使用的是 Claude,也必须额外配置。若仅设置了 Anthropic 密钥而未配置 embedding 供应商,memory_search 会 静默失效——不报错、不返回结果,表现形如记忆功能不存在。请在 openclaw.json 中确认 embedding 相关的 API 密钥已正确填写,并可通过日志确认向量索引是否正常构建。
最佳配置项:调优记忆搜索权重 你还可以通过 agents.defaults.memorySearch 配置 JSON 针对搜索权重进行调优。实测下来给向量加上略高权重有助于贴合业务:
操作要点:检索结果永远要遵循少而精的逻辑。把大量候选项一股脑子全灌入上下文,只会起到让模型”盲目重视全体噪音”的副作用。
6.3.4 索引构建管线:从文件保存到可检索
混合检索的前提是索引已就绪。OpenClaw 的索引管线在文件落盘后自动运行,无需手动触发,但理解其内部流程有助于排查”改了文件却检索不到”的常见问题。
监听与防抖
系统使用 Chokidar 对工作目录下的记忆文件(MEMORY.md 和 memory/*.md)进行实时监听。无论是智能体自动写入还是用户手动编辑,只要文件保存,就会触发索引流程。为避免高频写入导致的重复构建,监听器设置了 1.5 秒的防抖延迟——文件连续变化时,只有最后一次保存后的 1.5 秒静默期过后才会启动索引。
分块策略
索引前,系统将文件内容按约 400 token 为单位进行分块,相邻块之间保留 80 token 的重叠区域。重叠的目的是防止关键语义被切断——例如一段跨越分块边界的决策描述,在两个相邻块中都能被完整匹配。
向量生成与存储
每个文本块被送入 embedding 模型(默认 text-embedding-3-small,生成 1536 维向量),转换结果存入本地 SQLite 数据库。数据库包含四张核心表:
chunks
存储分块的原始文本、文件路径与行号范围
embeddings
存储每个分块对应的 1536 维向量
fts(全文检索)
存储分词后的倒排索引,支持 BM25 关键词检索
vector_cache
存储文本哈希值与对应向量的映射,用于去重
其中 vector_cache 表的设计值得注意:当文件内容未变化时,系统通过哈希比对跳过重复的 embedding 调用,既节省 API 费用又加速索引构建。
验收点:修改任意记忆文件后,等待约 2 秒,用 memory_search 检索刚写入的关键词,若能命中则索引管线正常工作。若持续无法命中,优先检查 embedding API 密钥配置(见 6.3.3)。
6.3.5 失效与清理:让记忆有生命周期
长期系统一定会遇到“事实过期”。建议为每条记忆补齐“来源/更新时间/有效期”,并定期做一次复核:过期则标注失效或迁移到每日日志;新事实覆盖旧事实时保留变更链;遇到冲突事实显式标注冲突点,避免模型自行选择。
过期条目标注失效或迁移到每日日志。
新事实覆盖旧事实时保留变更链。
对冲突事实显式标注冲突点,避免模型自行选择。
💡 踩坑实录:记忆搜索“静默失效”之谜
配好了 Anthropic API Key 就觉得万事大吉,结果
memory_search从来不返回结果。调试半天才发现:记忆搜索的向量检索需要独立的 embedding API 密钥(OpenAI、Gemini 或 Voyage),和主对话模型的密钥是两回事。最坑的是它不报错,只是静默返回空结果。建议配完后用openclaw doctor验证 embedding provider 状态。
最后更新于
