Skip to content

Workspace Memory v2(离线):研究笔记

目标:一个类似 Clawd 的 workspace(agents.defaults.workspace,默认 ~/.openclaw/workspace),其中“记忆”以“每天一个 Markdown 文件”的形式存储(memory/YYYY-MM-DD.md),外加少量稳定文件(例如 memory.mdSOUL.md)。

本文提出一种 offline-first 的记忆架构:保留 Markdown 作为可审阅、可编辑的权威事实来源(canonical, reviewable source of truth),同时通过派生索引提供 结构化 recall(搜索、实体摘要、置信度更新)。

为什么要改?

当前方案(每天一个文件)非常适合:

  • “只追加”(append-only)的日志记录
  • 人类手工编辑
  • 基于 git 的持久化 + 可审计性
  • 低摩擦记录(“直接写下来就行”)

但它在这些方面较弱:

  • 高召回检索(“我们对 X 做过什么决定?”,“上次尝试 Y 是什么时候?”)
  • 以实体为中心的回答(“讲讲 Alice / The Castle / warelay”)——不想反复翻很多文件
  • 观点/偏好的稳定性(以及它变化时的证据)
  • 时间约束(“在 2025 年 11 月期间,什么结论是成立的?”)与冲突解决

设计目标

  • 离线:不依赖网络;可在 laptop/Castle 上运行;无云依赖。
  • 可解释:检索结果应可归因(文件 + 位置),并能与推理内容分离。
  • 低仪式感:日常记录仍是 Markdown,不要求重度 schema。
  • 渐进式:v1 仅做 FTS 也有价值;语义/vector 与图谱是可选升级。
  • 对 agent 友好:让“在 token 预算内 recall”更容易(返回小包的事实集合)。

北极星模型(Hindsight × Letta)

需要融合两部分:

  1. Letta/MemGPT 风格的控制循环
  • 保持一小块“核心内容”永远在上下文中(persona + 关键用户事实)
  • 其余内容放在上下文外,通过工具检索
  • 写入记忆是显式的 tool call(append/replace/insert),落盘后,再在下一轮 turn 重新注入
  1. Hindsight 风格的记忆基底(memory substrate)
  • 区分“观察到的”vs“相信的”vs“摘要出来的”
  • 支持 retain/recall/reflect
  • 带置信度的观点可以随证据演进
  • 支持实体感知检索 + 时间查询(即便没有完整知识图谱)

建议架构(Markdown 事实来源 + 派生索引)

Canonical store(利于 git)

~/.openclaw/workspace 作为可供人类阅读的 canonical memory。

建议的 workspace 布局:

~/.openclaw/workspace/
  memory.md                    # 小:持久事实 + 偏好(偏“核心”)
  memory/
    YYYY-MM-DD.md              # 每日日志(追加;叙事)
  bank/                        # “类型化”的记忆页面(稳定、可审阅)
    world.md                   # 关于世界的客观事实
    experience.md              # agent 做过的事(第一人称)
    opinions.md                # 主观偏好/判断 + 置信度 + 证据指针
    entities/
      Peter.md
      The-Castle.md
      warelay.md
      ...

备注:

  • 每日日志还是每日日志:不必改成 JSON。
  • bank/ 文件是 策展/整理过的(curated),由反思任务产出,但依然可以手工编辑。
  • memory.md 仍保持“小 + core-ish”:你希望 Clawd 每次 session 都能看到的内容。

Derived store(机器 recall)

在 workspace 下加入派生索引(不一定要进 git):

~/.openclaw/workspace/.memory/index.sqlite

索引由以下部分支撑:

  • 用于事实 + 实体链接 + 观点元数据的 SQLite schema
  • 用于词法 recall 的 SQLite FTS5(快、体积小、离线)
  • 可选的 embeddings 表,用于语义 recall(仍然离线)

索引永远应该是 可从 Markdown 重建 的。

Retain / Recall / Reflect(操作闭环)

Retain:把每日日志规范化为“事实”

Hindsight 在此处最关键的洞见:存储 叙事性、可自洽的事实,而不是很小的碎片。

memory/YYYY-MM-DD.md 的实用规则:

  • 每天结束时(或过程中),增加一个 ## Retain 章节,写 2–5 条 bullet,要求:
    • 叙事性(跨回合上下文不丢失)
    • 自洽(未来单独读这一条也能理解)
    • 带 type 标签 + 实体提及

示例:

## Retain
- W @Peter: Currently in Marrakech (Nov 27–Dec 1, 2025) for Andy’s birthday.
- B @warelay: I fixed the Baileys WS crash by wrapping connection.update handlers in try/catch (see memory/2025-11-27.md).
- O(c=0.95) @Peter: Prefers concise replies (<1500 chars) on WhatsApp; long content goes into files.

最小解析需求:

  • 类型前缀:W(world)、B(experience/biographical)、O(opinion)、S(observation/summary;通常由系统生成)
  • 实体:@Peter@warelay 等(slug 映射到 bank/entities/*.md
  • 观点置信度:可选的 O(c=0.0..1.0)

如果不希望作者思考这些:reflect 任务可以从日志正文里推断这些 bullet;但显式的 ## Retain 章节是最容易提升质量的“杠杆”。

Recall:在派生索引上查询

Recall 需要支持:

  • 词法:精确查找术语/名字/命令(FTS5)
  • 实体: “讲讲 X”(实体页 + 实体关联事实)
  • 时间: “11 月 27 日前后发生了什么” / “从上周以来”
  • 观点: “Peter 喜欢什么?”(包含置信度 + 证据)

返回格式应对 agent 友好,并引用来源:

  • kindworld|experience|opinion|observation
  • timestamp(来源日期,或在事实中抽取到的时间范围)
  • entities["Peter","warelay"]
  • content(叙事性事实内容)
  • sourcememory/2025-11-27.md#L12 等)

Reflect:产出稳定页面 + 更新信念

Reflection 是一个定时任务(daily 或 heartbeat ultrathink),用于:

  • 从近期事实更新 bank/entities/*.md(实体摘要)
  • 根据强化/矛盾更新 bank/opinions.md 的置信度
  • 可选:提出对 memory.md 的编辑建议(“core-ish”的持久事实)

观点演进(简单、可解释):

  • 每条观点包含:
    • statement
    • confidence c ∈ [0,1]
    • last_updated
    • evidence links(支持 + 反驳的 fact IDs)
  • 当新事实到来时:
    • 通过实体重叠 + 相似度找到候选观点(先 FTS,后 embeddings)
    • 用小幅度增量更新置信度;大幅度跳变需要强烈矛盾 + 重复证据

CLI 集成:独立 vs 深度集成

建议:深度集成到 OpenClaw,但核心逻辑仍保持可分离的 library。

为什么要集成进 OpenClaw?

  • OpenClaw 已经知道:
    • workspace 路径(agents.defaults.workspace
    • session 模型 + heartbeats
    • logging + 排障模式
  • 你希望 agent 自己能调用这些工具:
    • openclaw memory recall "…" --k 25 --since 30d
    • openclaw memory reflect --since 7d

为什么仍然要拆出 library?

  • 让 memory 逻辑可以在不依赖 gateway/runtime 的情况下做测试
  • 便于在其它场景复用(本地脚本、未来桌面应用等)

形态: 这里的 memory tooling 目标是一个小型 CLI + library 层,但目前仍是探索阶段。

“S-Collide” / SuCo:何时使用(研究)

如果 “S-Collide” 指的是 SuCo(Subspace Collision):这是一种 ANN 检索方法,通过在子空间中进行学习/结构化的“碰撞”来获得较好的 recall/latency 权衡(论文:arXiv 2411.14754, 2024)。

~/.openclaw/workspace 的务实建议:

  • 不要一开始就用 SuCo。
  • 先用 SQLite FTS +(可选)简单 embeddings;你会立刻得到大部分 UX 收益。
  • 只有在以下条件满足时,再考虑 SuCo/HNSW/ScaNN 这类方案:
    • 语料很大(数万/数十万 chunk)
    • brute-force embedding search 变得太慢
    • recall 质量确实被词法搜索卡住

离线友好的替代方案(按复杂度递增):

  • SQLite FTS5 + 元数据过滤(零 ML)
  • Embeddings + brute force(chunk 数少时意外地能走很远)
  • HNSW index(常见、稳健;需要库绑定)
  • SuCo(研究级;如果有可嵌入的成熟实现会很有吸引力)

开放问题:

  • 在你的设备(laptop + desktop)上,“个人助理记忆”最好的离线 embedding 模型是什么?
    • 如果你已经有 Ollama:用本地模型做 embedding;否则在工具链里带一个小型 embedding 模型。

最小但有用的试点

如果要做一个最小但仍然有用的版本:

  • 增加 bank/ 实体页,并在每日日志里加入 ## Retain 章节。
  • 用 SQLite FTS 做 recall,并带引用(path + line numbers)。
  • 只有当 recall 质量或规模需要时,才引入 embeddings。

参考

  • Letta / MemGPT 概念:“core memory blocks” + “archival memory” + 基于工具调用的自编辑记忆。
  • Hindsight Technical Report:“retain / recall / reflect”、四网络记忆、叙事性事实抽取、观点置信度演进。
  • SuCo:arXiv 2411.14754 (2024):“Subspace Collision” 近似最近邻检索。