首页
/ OpenClaw × Mem0 记忆整合机制详解:memory-dream 技能的 Dream 协议、触发门槛与源码实现

OpenClaw × Mem0 记忆整合机制详解:memory-dream 技能的 Dream 协议、触发门槛与源码实现

2026-09-04 13:16:23作者:胡唯隽

在 Mem0 为 OpenClaw 智能体提供的长期记忆插件(@mem0/openclaw-mem0)中,memory-dream 是 skills 模式的三大协议技能之一,负责记忆库的周期性"巩固"(consolidation):审查全部已存记忆、合并重复、清除噪声与凭据、重写低质条目,并执行 TTL 过期策略。阅读本文后,你将完整掌握这份 Dream 协议的四阶段流程与质量标准,并能从 dream-gate.tsskill-loader.tsindex.ts 等源码中理解自动触发的三门槛(时间/会话/记忆数)设计、文件锁防并发机制,以及 openclaw mem0 dream 手动触发命令的工作原理。

OpenClaw 与 Mem0 记忆插件架构示意图

1. memory-dream 在记忆生命周期中的定位

OpenClaw 插件默认运行在 skills 模式下,智能体通过三个技能掌控记忆的写入、召回与清理:

  • Triagememory-triage)——从对话中提取值得长期保留的事实;
  • Recall——每轮响应前检索相关记忆并注入上下文;
  • Dreammemory-dream)——周期性记忆整合:合并重复项、消解冲突、修剪过期条目。

skill-loader.tsloadDreamPrompt() 可以看到,dream 技能与 triage 不同:领域叠加层(domain overlay)对它有生效路径,但自定义提取规则(customRules)明确标注为仅适用于 triage,因为"提取规则不适用于 recall/dream"(源码注释)。也就是说,SKILL.md 正文就是 dream 会话的完整协议,插件只会在其上追加用户配置的门槛参数。

该技能的 frontmatter 声明了关键元信息(SKILL.md):

  • user-invocable: true:用户可直接要求智能体执行记忆清理、整合或审查;
  • description 中还说明它"在足够活动量后也会自动触发(可配置)"(Also triggers automatically after sufficient activity (configurable));
  • metadata.openclaw.requires.env 要求 MEM0_API_KEYOPENAI_API_KEYANTHROPIC_API_KEY 三类环境变量之一可用,即整合操作依赖已配置好的 Mem0 后端与 LLM。

Dream 协议的核心隐喻写在正文开头:把原始观察(raw observations)压缩为干净、可长期保留的知识。整个流程被强制划分为四个阶段,"按顺序执行,不得跳过"(Follow these four phases in order. Do not skip phases)。

2. 协议可用的八个记忆工具

Dream 会话中智能体只能使用插件注册的八个记忆工具(与 README 中 Agent Tools 表格一致)。SKILL.md 对每个工具给出了精确的参数契约:

工具 用途 关键参数
memory_search 跨全部已存记忆的语义搜索 query(必填)、limituserId/agentId(范围覆盖)、scope"all" 默认 / "session" / "long-term")、categories(类别数组过滤)
memory_add 向长期记忆写入新事实 facts(必填,数组,同批次必须同一 category)、category(8 类之一)、importance(0.0–1.0)
memory_get 按 ID 取回单条记忆 memoryId(必填)
memory_list 列出某用户/智能体的全部记忆 userIdagentIdscope"all" 默认)
memory_update 原地更新记忆文本,原子操作且保留编辑历史 memoryId(必填)、text(必填,整体替换旧文本)
memory_delete 按 ID、按查询或批量删除 memoryIdall(需 confirm: true)、userIdagentId
memory_event_list 列出最近的后台处理事件(仅平台模式)
memory_event_status 查询指定后台事件的状态 event_id(必填)

两个值得注意的契约细节:

  1. 类别即保留策略memory_addcategory 参数决定 TTL 与不可变性。从 skill-loader.tsDEFAULT_CATEGORIES 可看到默认策略:identity(0.95,永久,immutable)、configuration(0.95)、rule(0.9)、preference(0.85)、decision/technical(0.8)、relationship(0.75)、project(0.75,ttl: "90d")、operational(0.6,ttl: "7d")——这直接对应后文 3a 阶段的两条删除时限。
  2. memory_update 优先于"删了再加"。SKILL.md 明确指出"prefer memory_update over forget-then-store because it is atomic and preserves edit history"。插件的 oss.historyDbPath 配置项(见 types.ts)即为开源模式下 SQLite 编辑历史库(~/.mem0/history.db)。

3. 四阶段协议:从盘点到报告

Phase 1: Orient(定向盘点)

改动之前先摸清记忆现状:

  1. 调用 memory_list 加载全部已存记忆;
  2. 按 category 计数并记录总数;
  3. 通过时间戳找出最旧与最新的记忆;
  4. 记录列表中直接可见的问题:重复项、过短条目、缺少时间锚点(temporal anchor)的条目。

本阶段禁止任何修改。目标是理解"你正在处理的是什么"。

Phase 2: Gather Targets(圈定目标)

用工具调查并识别需要处置的记忆。协议要求先用 memory_search 配合 created_at 过滤条件找出自上次整合以来新增的记忆——这些是最可能需要合并或清理的对象。

随后把每个目标分类为三种动作之一:

  • DELETE:包含凭据、已过 TTL、纯噪声、原始工具输出、孤立时间戳;
  • MERGE:两条及以上记忆用不同措辞表达同一事实,或一系列记忆在追踪同一实体的增量变化;
  • REWRITE:表述模糊、缺少时间锚点、用第一人称而非第三人称、类别错误、过于冗长。

Phase 3: Consolidate(执行整合)

按以下优先级顺序执行 Phase 2 圈定的动作。

3a. 删除危险与过期条目——立即用 memory_delete 删除:

  • 凭据、API key、token、密码、secret(匹配插件在运行时注入的已知凭据前缀与认证模式);
  • 无上下文的纯时间戳;
  • 被存为记忆的原始工具输出;
  • 心跳(heartbeat)或 cron 执行记录;
  • 被存为记忆的泛化确认语("ok"、"got it");
  • 超过 7 天的 operational 记忆;
  • 超过 90 天的 project 记忆。

这里"运行时注入的凭据模式"有源码实证:skill-loader.ts 中定义了 DEFAULT_CREDENTIAL_PATTERNS

const DEFAULT_CREDENTIAL_PATTERNS = [
  "sk-", "m0-", "ghp_", "AKIA", "ak_",
  "Bearer ", "bot\\d+:AA",
  "password=", "token=", "secret=",
];

并且 skill-loader.tsloadSkill()memory-dreammemory-triage 都会调用 renderTriageKnobs(),把 skills.triage.credentialPatterns(用户可覆盖上述默认值)渲染为 "Credential patterns to scan: …" 段落追加到 dream 协议文本末尾。这解释了 SKILL.md 中"matching known credential prefixes and auth patterns injected by the plugin at runtime"的确切含义:凭据匹配清单不是写死在技能文件里的,而是每次加载时按用户配置动态拼接。

两条 TTL 时限(operational 7 天 / project 90 天)则与 DEFAULT_CATEGORIESttl: "7d" / ttl: "90d" 一一对应;ttlToExpirationDate()skill-loader.ts)会把 "7d" 这类 TTL 换算成具体到期日,供 triage 写入时打上过期标记,dream 再据此清理。

3b. 合并重复项——当两条及以上记忆表达同一事实时:

  1. 选信息最完整的版本作为基底;
  2. 对最佳版本调用 memory_update,把其他版本的缺失细节吸收进来;
  3. 对冗余条目调用 memory_delete

合并时须遵守四条规则:

  • 保留用户对观点与偏好的原话
  • 保留两个版本中的时间锚点;
  • 合并结果不超过 50 词
  • 合并后的记忆必须自包含(在其余条目被删除后依然可独立理解)。

3c. 重写低质条目——当记忆需要改进但不属于重复时,调用 memory_update 提交改进后的文本。触发重写的五种情形:

  • 使用第一人称("I prefer")而非第三人称("User prefers");
  • 时效敏感信息缺少时间锚点;
  • 表述模糊且可具体化("likes python" → "User prefers Python for backend development");
  • 类别归属错误;
  • 超过 50 词且可在不损失信息的前提下压缩。

Phase 4: Report(报告)

全部操作完成后,按固定模板输出总结:

Consolidation complete.
- Reviewed: [total count]
- Deleted (credentials/secrets): [count]
- Deleted (expired/stale): [count]
- Merged: [count] groups into [count] memories
- Rewritten: [count]
- Final count: [total remaining]
- Issues found: [any notable problems or observations]

4. 质量目标(Quality Targets)

整合完成后,记忆库应达到以下六项验收标准:

  • 含凭据或 secret 的记忆数为 0
  • 重复记忆(同一事实的不同措辞)数为 0
  • 所有 project 与 operational 记忆带时间锚点("As of YYYY-MM-DD");
  • 所有记忆使用第三人称表述;
  • 所有记忆类别正确
  • 每条记忆 15–50 词、自包含、原子化(一条记忆只陈述一个事实)。

5. 自动触发:Dream Gate 三门槛与文件锁

SKILL.md 声明"activity 足够后自动触发(可配置)",其实现完全在 dream-gate.ts 中,状态持久化在插件的 stateDir 下(README 持久化表中对应 <pluginStateDir>/dream-state.json),可跨网关重启存活。

5.1 状态结构与默认门槛

interface DreamState {
  lastConsolidatedAt: number; // 毫秒时间戳,0 = 从未整合
  sessionsSince: number;      // 上次整合以来的交互会话数
  lastSessionId: string | null;
}

const DEFAULTS: DreamGateConfig = {
  minHours: 24,     // 距上次整合至少 24 小时
  minSessions: 5,   // 至少 5 个交互会话
  minMemories: 20,  // 记忆总数至少 20 条
};

dream-gate.ts

这三个门槛在 types.tsSkillsConfig.dream 中全部可配,插件 README 的配置参考表还暴露了 skills.dream.enabledskills.dream.auto 两个开关(auto 默认 true,控制是否按活动门槛自动触发)。

5.2 廉价门槛先行:避免无谓 API 调用

门槛检查刻意分为两级,checkCheapGates()dream-gate.ts)只做本地文件读取——时间门槛(hoursSince < minHours 则拒绝)与会话门槛(sessionsSince < minSessions 则拒绝)都从同一个 dream-state.json 读出;只有廉价门槛通过后才调用 provider.getAll() 拉取记忆总数,交由 checkMemoryGate()dream-gate.ts)做昂贵的计数检查。index.ts 中的 before_prompt_build 钩子按此顺序执行:"Check CHEAP gates first (local file reads only). Only hit the API for memory count if time + session gates pass."

5.3 锁与完成记录

  • 获取锁acquireDreamLock()dream-gate.ts)以 wx 排他标志原子创建 dream.lock(内含 pid 与 startedAt),两个进程竞争时只有一个成功;超过 1 小时LOCK_STALE_MS)的陈旧锁会被先清除再竞争,防止崩溃后永久死锁;
  • 会话计数incrementSessionCount() 在每次交互回合结束时调用,按 sessionId 去重,同一会话内的多轮不会重复计数;
  • 完成记录recordDreamCompletion()lastConsolidatedAt 置为当前时间并把 sessionsSince 清零,重置整个计数周期。

5.4 注入、验证与失败回滚

index.ts 中,当三门槛与锁全部通过,插件把 loadDreamPrompt() 生成的完整协议文本包进 <auto-dream> 标签,通过 prependContext 注入当轮上下文:"Before responding to the user, run a memory consolidation pass. Follow the protocol below, then respond normally."

agent_end 钩子(index.ts)随后做了两件事:

  1. 仅放行触发会话dreamSessionId 是会话级的,防止其他会话误报完成("Prevents cross-session false completion");
  2. 验证真实写入:扫描最后一条 assistant 消息中的工具调用,只有出现 memory_addmemory_updatememory_delete 三者之一才认定整合成功(memory_list/memory_search 等只读操作不算),然后释放锁并 recordDreamCompletion()。若本轮失败、或注入了 dream 但模型没执行任何写操作,则只释放锁、不记录完成——下一个符合门槛的回合会重新触发。

整套门控逻辑由 tests/dream-gate.test.ts 覆盖:时间门槛过近拒绝、会话数不足拒绝、双门槛通过、minMemories 计数边界、新锁获取(含 wx 标志断言)、1 小时内新锁拒绝、2 小时陈旧锁回收,以及 recordDreamCompletion 的计数器重置。

6. 手动触发:openclaw mem0 dream

除自动触发外,README 提供了 CLI 手动入口(cli/commands.ts 中注册):

# 只查看记忆盘点,不做任何修改
openclaw mem0 dream --dry-run

# 生成完整整合提示词
openclaw mem0 dream

实现细节值得注意:

  • --dry-run 会先调用 provider.getAll({ user_id, source: "OPENCLAW" }) 拉取全量记忆,按 metadata.category(回退到 categories[0],再无则记为 uncategorized)分类计数并打印清单,然后停止("Dry run — no changes made.");
  • 非 dry-run 时,命令并不直接改写记忆,而是把 loadDreamPrompt() 的输出包在 <dream-protocol> 中、再把全部记忆以 <all-memories count="N" user="uid"> 清单形式拼接,在每条记忆前标注 [id] (category, importance, created),最后追加"Begin consolidation…"指令,整段提示词写到 stdout,并提示"Paste it into an OpenClaw session to run consolidation"——即把协议与数据交给一个带工具调用能力的智能体会话去真正执行 Phase 1–4;
  • 所有命令支持 --json 输出(如 openclaw mem0 dream --dry-run --json 返回 { ok, count, categories }),便于脚本或上层 agent 消费。

7. 配置参考:skills.dream 与相关开关

dream 相关的配置面(types.tsREADME 配置参考):

配置键 类型 默认值 说明
skills.dream.enabled boolean true 是否启用记忆整合技能
skills.dream.auto boolean true 是否按活动门槛自动触发
skills.dream.minHours number 24 两次整合之间的最小间隔(小时)
skills.dream.minSessions number 5 触发前所需的最小交互会话数
skills.dream.minMemories number 20 记忆总数低于此值则不值得整合
skills.triage.credentialPatterns string[] 内置 10 种模式 覆盖凭据扫描模式,会注入 dream 与 triage 协议文本
skills.categories Record 9 个默认类别 覆盖各 category 的 importance / ttl / immutable

典型 openclaw.json 配置(摘自 README):

{
  "plugins": {
    "slots": { "memory": "openclaw-mem0" },
    "entries": {
      "openclaw-mem0": {
        "enabled": true,
        "config": {
          "apiKey": "${MEM0_API_KEY}",
          "userId": "alice",
          "skills": {
            "triage": { "enabled": true },
            "recall": { "enabled": true },
            "dream": { "enabled": true }
          }
        }
      }
    }
  }
}

从源码结构看,dream 的自动触发还有一条隐含约束:index.ts 中触发条件包含 !isSubagent,即子智能体回合不参与自动 dream;会话计数同样只在交互触发(非 heartbeat/cron 等非交互 trigger)时递增——这与协议 3a 阶段要求删除"heartbeat or cron execution records"相呼应:系统既避免把后台任务产生的噪声写入记忆,也避免它们消耗整合名额。

8. 小结

memory-dream 展示了 Mem0 OpenClaw 插件"以协议文件驱动 agent 行为"的设计范式:SKILL.md 本身是完整的四阶段操作手册(Orient → Gather Targets → Consolidate → Report),定义了凭据零容忍、TTL 时限(operational 7 天 / project 90 天)、合并规则(≤50 词、第三人称、自包含)与量化报告模板;而 dream-gate.ts 用"廉价门槛先行 + 文件锁 + 写操作验证"三件套,让这份协议可以安全地自动运行——不频繁、不并发、不虚报完成。对运维者而言,需要关注的落盘文件是 dream-state.json(整合状态)与 dream.lock(并发锁),需要关注的可观测信号是日志中的 auto-dream triggered / completed / will retry 事件;对开发者而言,扩展清理规则的正确方式是编辑 SKILL.md 的 Phase 规则或经 skills.triage.credentialPatternsskills.categories 注入覆盖项,而不是修改门控代码。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384