OpenClaw Memory
OpenClaw 的记忆就是 workspace(默认 ~/.openclaw/workspace)里的一堆纯 Markdown 文件,没有隐藏状态:模型记住的东西 = 磁盘上写下来的东西。可以(也建议)把整个 workspace 做成一个私有 git 仓库来备份。
两层记忆
| 层 | 文件 | 何时进入上下文 | 定位 |
|---|---|---|---|
| 长期(精炼) | MEMORY.md | 每次会话启动时整份注入 prompt(超限会截断) | 持久事实、偏好、长期决策;紧凑、可维护 |
| 短期(工作) | memory/YYYY-MM-DD.md | 裸 /new、/reset 时自动带上今天 + 昨天;其余靠 memory_search 检索 | 每日流水、观察、会话小结、暂时还有用的原始上下文 |
补充:DREAMS.md(可选)是 dreaming 扫描的人类可读产出,memory/.dreams/ 是它的机器状态。
两层的流向是短期 → 长期:日志先落在 memory/,随后由 agent(或 dreaming)蒸馏出耐用的结论追加进 MEMORY.md,同时删掉 MEMORY.md 里过期的条目。
判断放哪一层的一句话标准:下次开新会话,不看它就会答错的,放 MEMORY.md;只是"以后可能查得到就行"的,放 memory/。
MEMORY.md vs memory/*.md vs memory/YYYY-MM-DD.md
MEMORY.md(根目录,大写)— 唯一的长期记忆文件,只有它会被完整注入 bootstrap 上下文。小写memory.md是历史遗留,只作为openclaw doctor --fix的迁移输入,不要故意同时保留两个根文件。memory/YYYY-MM-DD.md— 带日期的每日笔记,是"短期层"的正规形态。memory/YYYY-MM-DD-<slug>.md是同一天的分片(如 bundled session-memory hook 写的),会和纯日期文件一起被加载。带日期的文件会受 temporal decay(若开启)影响,越旧排序权重越低。memory/下不带日期的文件(如memory/entehub-profile.md)— 属于 evergreen 常青档案:同样被索引、可被memory_search检索,但永不衰减,也不会自动进入 bootstrap。适合放"篇幅太大不配进MEMORY.md、但需要长期准确"的资料(项目档案、客户画像、规范细节)。
一个实用组合:MEMORY.md 里给每个项目写 3~5 行摘要,然后 - **Details**: 详见 [memory/xxx-profile.md](memory/xxx-profile.md) 指向常青档案 —— bootstrap 只花几百 token,需要细节时 agent 自己去 memory_get。
索引范围:MEMORY.md + memory/**/*.md 默认全部索引(includeDefaultMemory: true,递归子目录),存进 per-agent SQLite(~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite),文件变更会触发 1.5s debounce 的增量重建。
memory/ 子目录组织最佳实践
- 日期文件保持平铺在
memory/根下,别按2026/07/分目录 —— "今天 + 昨天"自动加载和 backfill 都按扁平日期文件名来找。 - 常青档案按主题一个文件、用稳定的 kebab-case 命名(
entehub-profile.md、amazon-ads-account.md),文件名本身就是检索关键词。 - 数量多了再按域分子目录(
memory/clients/、memory/projects/、memory/reference/),子目录一样会被递归索引;不要为了三五个文件提前分层。 - 保留给系统的路径别占用:
memory/.dreams/(dreaming 机器状态)、memory/dreaming/<phase>/YYYY-MM-DD.md(阶段报告)。 - 单个档案别无限膨胀 —— chunk 默认 400 token / 80 token overlap,过长的大杂烩文件会让检索命中变模糊,按主题拆开更好。
- 写之前先读:只写具体更新,不要留空占位;密钥类内容除非明确要求,不要写进记忆文件。
配置激活
短期/长期两层文件本身开箱即用,不需要配置;需要配置的是三件事:检索、注入预算、自动蒸馏。
1. 语义检索(memory_search)
不配 embedding provider 时只有关键词检索(FTS5,含 CJK trigram)。配上任一 provider 即启用向量 + 混合检索:
{
"agents": {
"defaults": {
"memorySearch": {
"enabled": true,
"provider": "openai"
}
}
}
}provider 可选 openai(默认,text-embedding-3-small)、gemini、voyage、mistral、deepinfra、bedrock、ollama、lmstudio、local(GGUF)、openai-compatible。显式指定的远程 provider 不可用时不会静默降级为关键词检索,会直接返回 unavailable;想要故意只用关键词就设 provider: "none"。
改动 provider / model / chunking / 索引范围后向量索引会失效,需要重建:
openclaw memory status # 查看 provider 与索引状态
openclaw memory status --deep # 分别报告 embeddings 与本地向量库
openclaw memory search "查询词"
openclaw memory index --force # 重建索引2. 注入预算
MEMORY.md 涨过预算时磁盘文件不动,但注入 prompt 的副本会被截断 —— 这是"该把细节挪去 memory/"的信号。
agents.defaults.bootstrapMaxChars单文件上限,默认20000agents.defaults.bootstrapTotalMaxChars全部 bootstrap 文件合计上限,默认60000
用 /context list、/context detail 或 openclaw doctor 看 raw vs injected 大小和是否被截断。
3. 自动蒸馏
compaction memory flush(默认开启):压缩会话前先跑一轮静默 turn,提醒 agent 把重要上下文落盘,避免压缩丢信息。关掉:agents.defaults.compaction.memoryFlush.enabled: false。也可以给这一轮单独指定便宜模型:
{
"agents": {
"defaults": {
"compaction": { "memoryFlush": { "model": "ollama/qwen3:8b" } }
}
}
}dreaming(默认关闭,opt-in):后台按 light → REM → deep 三阶段跑,只有 deep 阶段在通过 minScore / minRecallCount / minUniqueQueries 三重门槛后才会把内容追加进 MEMORY.md,过程写入 DREAMS.md 供人工复核。开启后 memory-core 会自动维护一条 cron(默认 0 3 * * *):
{
"plugins": {
"entries": {
"memory-core": {
"config": {
"dreaming": {
"enabled": true,
"timezone": "Asia/Hong_Kong",
"frequency": "0 3 * * *"
}
}
}
}
}
}聊天里也可以 /dreaming status、/dreaming on、/dreaming off。
把历史日记重放一遍看看系统认为哪些"够持久"(只写 DREAMS.md,不直接改 MEMORY.md):
openclaw memory rem-backfill --path ./memory --stage-short-term
openclaw memory rem-backfill --rollback4. 别忘了 agent 侧的约定
AGENTS.md 里的 session-start 仪式才是让 agent 真正去读记忆的那一半:开场读 SOUL.md、USER.md、memory/ 今天+昨天、MEMORY.md;捕捉决策、偏好、约束、未闭环事项。默认模板已包含,自定义 AGENTS.md 时别把这段删了。
