OpenClaw 记忆重复查询:机制本身就有,分层只是其中一种思路
用 OpenClaw 当个人助手,我注意到一个隐蔽问题:同一份记忆,会既被自动注入、又被显式搜索,在上下文里出现两次。
排查下来发现这不是 bug,而是 OpenClaw 记忆机制本身就有两条路径,它们天然会重叠。
问题:重复查询从哪来
OpenClaw 的记忆召回有两条路:
路径 A:自动注入(trigger recall)
- 每个交互回合,系统自动把你的消息和记忆里的触发短语做比对。
- 命中强触发时,自动把 MEMORY.md / USER.md 里的条目注入到隐藏上下文(最多 3 条)。
- 特点是:自动、前置、只看 MEMORY.md 和 USER.md。
路径 B:显式搜索(memory_search 工具)
- agent(模型)在需要时主动调用
memory_search工具去检索。 - 特点是:按需、全库(覆盖日文件、knowledge 等)。
问题就在这: 触发词命中 → 路径 A 已把某条记忆塞进上下文;agent 又显式搜 → 路径 B 再把同一份搜出来。同一个内容出现两次,浪费 token、稀释注意力。
一种处理思路:分层 + 命中即停
这里给的只是众多处理方式中的一种,能缓解一部分问题,不是唯一解、也不是"就该这么做"。
核心思路:给两条路径定优先级,命中就停,不重复搜。
| 层级 | 来源 | 触发 | 成本 |
|---|---|---|---|
| L1 | MEMORY.md / USER.md | 自动注入 + 会话加载 | 秒回,0 成本 |
| L2 | knowledge/index.md 导航 | 知道去哪取,直接取 | 毫秒级 |
| L3 | 向量搜索(memory_search) | L1/L2 没命中才查历史 | 数百 ms~数 s |
| L4 | Outline(MCP) | 前三层都没有才调 | 1.5~2.5s |
怎么缓解重复:
- L1 命中即停:触发式注入已经把记忆塞进来了,agent 可以考虑不再调 L3 搜同一份。
- 判断依据:当前问题已被自动注入的记忆覆盖(L1 满足),直接用它回答,不再显式
memory_search。 - 只有 L1/L2 确实没有相关记忆时,才落到 L3/L4。
可能的好处: 减少重复、省 token、省延迟(L1 秒回,不进 L3 的 8s embedding、L4 的 2.5s MCP)。
但要看到取舍: 如果 L1 没搜到相关记忆,可能漏召回。用不用、怎么调,取决于实际场景。
为什么这条思路能成立
OpenClaw 的 memory 文档提到:自动注入只覆盖 MEMORY.md / USER.md(promoted/trusted entries),日文件和知识库不会自动注入。
这意味着两条路径在覆盖范围上天然不同:
- MEMORY.md / USER.md → 走自动注入这条路径。
- 日文件 / knowledge → 通常靠显式 memory_search 检索。
分层可以顺着这个边界来划分职责。这只是机制背景,方便理解思路的由来,不代表只能这么做。
落地时可以考虑的点
- 记忆写对地方:轻量长期事实进 MEMORY.md(走自动注入);流水进日文件(可显式搜);成体系进 Outline。
- 问答时命中即停:L1 已覆盖的,可不再重复调 L3/L4。
- 必要时调
maxResults:默认 6,注入前可调小,减少冗余命中。
小结
重复查询是 OpenClaw 记忆双路径(自动注入 + 显式搜索)机制本身的产物。 分层 + 命中即停只是其中一种缓解思路,能解决一部分重复和 token/延迟问题,也有取舍。用不用、怎么调,取决于你的实际场景。