我从 OpenClaw 的记忆架构中学到了什么,以及我是如何在 OpenCode 中构建一个轻量版本的。


问题所在

AI 编程 Agent 是无状态的。每次新会话都从零开始——你需要重新解释项目结构、技术栈和各种决策。对于长期项目来说,这严重拖累生产力。

OpenClaw 是怎么做的

OpenClaw 使用纯 Markdown 文件作为记忆载体:

  • SOUL.md — AI 的个性和行为规则
  • USER.md — 用户画像与偏好
  • MEMORY.md — 精选的长期记忆
  • memory/YYYY-MM-DD.md — 每日原始会话日志

关键创新在于自我维护:AI 会定期审阅每日日志,将有价值的信息提取到 MEMORY.md 中,并清理过时条目。在上下文压缩之前(当会话过长时),它会触发一次静默的"记忆刷写",在重要信息丢失前将其保存。

这构建了一个自然的层级结构:每日日志作为短期记忆,MEMORY.md 作为中期记忆,USER.md/SOUL.md 作为永久身份。

我在 OpenCode 上的简化版本

OpenClaw 的完整系统包括向量嵌入、混合搜索和自动心跳——对于交互式编程 Agent 来说过于复杂。我的核心洞察是:你不需要每日日志。OpenCode 在上下文中保留了完整的对话记录,所以只需在会话结束时直接将摘要写入 MEMORY.md 即可。

基本配置

project/
├── AGENTS.md      # 包含"会话开始时读取 MEMORY.md"的指令
├── MEMORY.md      # 项目特定的决策和进度
└── ...

~/.config/opencode/
└── opencode.json  # /save 命令在此注册

MEMORY.md 存放在每个项目根目录下——记录技术决策、进度和架构笔记。

USER.md 是全局的(只有一份),由自定义 MCP 服务器维护——存储跨项目通用的用户偏好。

/save 命令

1
2
3
4
5
6
7
8
{
  "command": {
    "save": {
      "description": "将会话摘要写入项目记忆",
      "template": "回顾我们的整个对话。执行以下操作:\n1. 如果 MEMORY.md 存在则读取它\n2. 追加新的关键决策、技术发现、已解决的 bug 和进度\n3. 删除过时或已被取代的条目\n4. 保持 MEMORY.md 在 200 行以内\n5. 绝不存储密钥或 token"
    }
  }
}

会话结束 → 输入 /save → AI 回顾对话 → 更新 MEMORY.md → 下次会话从上次断点继续。

为什么不用全局记忆?

我最初设计了一个 GLOBAL_MEMORY.md 来聚合所有子项目的记忆,配合 /sync-memory 命令。后来放弃了——跨项目引用极少出现,真正需要时直接让 AI 去读另一个项目的 MEMORY.md 就行。不要过度设计。

经验总结

从简单开始。 一个 MEMORY.md 加一个手动 /save 命令,就能捕获完整记忆系统 80% 的价值。

文件优于数据库。 Markdown 是人类可读的、可以用 git 追踪的,AI 可以用内置工具直接读写它。无需额外基础设施。

手动触发优于自动触发。 像"在对话中自动更新记忆"这样的指令并不可靠——AI 会忘记。一个显式的 /save 命令才是可靠的。

最大的差距在于从零到一。 “没有记忆"和"基础记忆"之间的差距是巨大的。“基础"和"高级"之间的差距是微乎其微的。先发布简单版本。