上周我遇到了两个截然不同的对话体验,这直接引发了我对 AI 记忆系统的思考。
场景一:使用普通 AI Agent
我:帮我优化一下 Redis 配置
AI Agent:好的,请告诉我你的 Redis 版本、内存大小、使用场景...
我:(输了一堆信息)
AI Agent:明白了,建议你...
(第二天)
我:上次那个 Redis 优化还有个问题
AI Agent:请问你之前问的是什么 Redis 问题?能再说一下你的配置吗?
我又把昨天的背景说了一遍。这让我很沮丧——大部分 AI Agent 的记忆,似乎只存在于当前对话窗口里。
场景二:使用 OpenClaw
我:帮我优化一下 Redis 配置
OpenClaw:好的,请告诉我...
(隔了好几天,中间聊了很多别的事)
我:对了,上次 Redis 那个 maxmemory-policy 改成 allkeys-lru 之后,又遇到新问题了
OpenClaw:你是说那个 4GB 内存、用作缓存的 Redis 实例吗?我看看之前的配置...
我愣了一下——它居然记得。而且不是模糊的“你之前问过 Redis”,是精确到“4GB、缓存”这些细节。
这是怎么做到的?我翻了一遍 OpenClaw 的源码和文档,发现它的 Memory 机制设计得挺有意思。
1. 记忆存储:答案简单到出乎意料
我原本以为会有一个向量数据库,或者什么复杂的知识图谱。
结果打开 ~/.openclaw/workspace/ 目录一看:
memory/
├── 2026-02-23.md
├── 2026-02-22.md
└── MEMORY.md
就是几个 Markdown 文件。
我的第一反应是:这能行?
后来我用了一段时间才明白,这个设计其实很聪明:
第一,我可以直接修改。 有一次 OpenClaw 记错了我的服务器 IP,我直接用 VS Code 打开 MEMORY.md 改了一行,问题解决。如果记忆存在向量数据库里,我连在哪修改都找不到。
第二,可以用 Git 管理。 我把 workspace/ 目录放进了 Git 仓库,每次 AI 学到了新东西,我就能看到 diff。有一次它莫名其妙记了一条“用户喜欢吃香菜”,我立刻 git checkout 回滚了。
第三,迁移机器直接拷贝。 不需要导出导入,cp -r 就行。
当然,这只是存储。真正让它能回忆起来的,是后面的搜索机制。
2. 两层记忆结构:分工明确
OpenClaw 默认采用两层结构来存储记忆:

每日日志:memory/2026-02-23.md
这个文件是仅追加(append-only)的,不修改。每次对话开始时,系统会自动加载今天和昨天的日志。
为什么要加载昨天的?因为大部分情况下,你今天问的问题跟昨天有关,跟上个月关系不大。这个设计很实用——不会塞太多无关内容,又不会漏掉近期的上下文。
长期记忆:MEMORY.md
这个文件需要手动维护,用来存储那些值得长期记住的东西——比如你的个人偏好、常用配置、重要决策。
有一个细节让我印象深刻:MEMORY.md只在私聊中加载,群聊时不会读取。
我试了一下,确实如此。在群里问 OpenClaw “我的服务器 IP 是多少”,它说不知道;私聊问,它立刻回答。这个安全设计很关键——你不会想在群里暴露自己的敏感信息。

3. 混合搜索:向量与关键词缺一不可
OpenClaw 提供了 memory_search 和 memory_get 两个工具供 AI Agent 调用。
memory_search 是语义搜索,memory_get 是按文件路径精确读取。
但真正让我感兴趣的是它的混合搜索——同时使用向量相似度和 BM25 关键词匹配。
我做过一个测试:
搜索 REDIS_PASSWORD 这个环境变量名。
纯向量搜索:找不到。因为 REDIS_PASSWORD 和 redis 密码配置 在语义上确实不像。
混合搜索:立刻定位到。因为 BM25 精确匹配了这个词。
反过来,搜索“之前那个性能问题”:
纯 BM25:找不到。因为记忆里写的是“响应时间太慢”,没有“性能”两个字。
混合搜索:找到了。向量搜索能理解“性能问题”和“响应时间太慢”是一回事。
这个组合确实比单一方案更靠谱,它平衡了语义理解和精确匹配。

4. 时序衰减:最惊艳的功能设计
这部分是我觉得 OpenClaw Memory 最用心的设计。
我之前维护过一个持续半年的项目,记忆文件积累了几百个。搜索“部署流程”,返回的结果全是半年前的——早就废弃了。
时序衰减解决的就是这个问题:新记忆权重高,老记忆权重低。
原理很简单:halfLife 参数的意思是“多少天后权重降到一半”。比如设成 14 天,那 14 天前的记忆就剩 50% 权重,28 天前剩 25%,以此类推。
我用的配置是 halfLifeDays: 14:
- 今天:100%
- 两周前:50%
- 一个月前:约 22%
- 三个月前:约 1%,基本不出现了
但有个例外——MEMORY.md 和非日期文件(比如 memory/projects.md)不会衰减。这些是永久记忆,不会因为时间久了就消失。

另一个相关功能是 MMR 多样性重排。
我搜索“数据库优化”,以前返回的 10 条结果有 8 条都在讲索引——同一个角度重复了。MMR 会刻意打散结果,让它们涵盖索引、连接池、查询重写等不同方向。
这两个功能都需要在配置里显式开启,后面我会给出具体例子。
5. 什么时候考虑 QMD 后端?
默认的 SQLite 索引器够用,但如果你要索引的目录比较多、文档量比较大,可以考虑 QMD。
QMD 是一个独立的搜索服务,把 BM25、向量搜索、重排序整合在一起。性能比 SQLite 好,但需要额外安装。
我用过一段时间,检索速度确实快。不过它目前还是实验性功能,正式环境用之前建议先充分测试。
好了,原理讲得差不多了。下面是实操部分——三个典型场景的配置示例,都是我踩过坑总结出来的。
6. 场景一:完全离线,不依赖云服务
如果你和我一样,不想把任何数据传到云端,可以使用本地嵌入模型。
前置工作:
pnpm approve-builds
# 选择 node-llama-cpp
pnpm rebuild node-llama-cpp
这一步是编译本地推理引擎,第一次会有点慢。
配置文件 ~/.openclaw/config.json5:
{
agents: {
defaults: {
memorySearch: {
provider: "local",
local: {
// 首次使用会自动下载,模型约 600MB
modelPath: "hf:ggml-org/embeddinggemma-300m-qat-q8_0-GGUF/embeddinggemma-300m-qat-Q8_0.gguf"
},
fallback: "none", // 本地失败不回退到远程
query: {
hybrid: {
enabled: true,
vectorWeight: 0.7,
textWeight: 0.3
}
},
// 除了默认的 memory/ 目录,还想索引哪些
extraPaths: [
"~/notes/tech",
"~/projects/docs"
],
cache: {
enabled: true, // 开启缓存,避免重复索引
maxEntries: 50000
}
}
}
}
}
我踩过的坑:
- 模型下载慢:国内网络可能要挂代理,或者手动下载到本地再指定路径。
- 首次索引慢:几十个文件可能要几分钟,后面有缓存就快了。
- 内存占用:本地推理需要 1-2GB 内存,小机器慎用。
7. 场景二:索引多个目录,使用 QMD 后端
如果你想索引的目录不止 memory/,还有项目文档、技术笔记等,可以考虑 QMD 后端。它比默认的 SQLite 性能更好,但需要额外安装。
安装 QMD:
bun install -g https://github.com/tobi/qmd
brew install sqlite # macOS 需要支持扩展的版本
qmd --version
配置:
{
memory: {
backend: "qmd",
citations: "auto",
qmd: {
searchMode: "search",
includeDefaultMemory: true,
// 索引额外的目录
paths: [
{ name: "projects", path: "~/projects", pattern: "**/*.md" },
{ name: "notes", path: "~/notes", pattern: "**/*.md" }
],
update: {
interval: "5m",
debounceMs: 15000,
onBoot: true
},
limits: {
maxResults: 10,
timeoutMs: 4000
}
}
}
}
我的经验:
- QMD 会自动管理索引,不需要手动触发。
- 文件修改后,最多等 15 秒(
debounceMs)就会重新索引。
- 如果 QMD 服务挂了,OpenClaw 会自动回退到内置索引器,不会完全不可用。
- 缺点是配置稍微麻烦,而且目前还是实验性功能。
8. 场景三:长期项目,需要时序衰减
这是我目前在用的配置,适合持续数月的项目:
{
agents: {
defaults: {
memorySearch: {
provider: "openai",
model: "text-embedding-3-small",
remote: {
apiKey: "${OPENAI_API_KEY}"
},
query: {
hybrid: {
enabled: true,
vectorWeight: 0.6,
textWeight: 0.4,
mmr: {
enabled: true,
lambda: 0.7 // 偏向相关性
},
temporalDecay: {
enabled: true,
halfLifeDays: 14
}
}
},
extraPaths: [
"~/projects/main-project/notes"
]
}
}
}
}
效果对比:
| 场景 |
以前(无衰减) |
现在(有时序衰减) |
| 搜索部署流程 |
返回 3 个月前的旧流程 |
返回上周更新的 |
| 搜索 API 配置 |
新旧混在一起,难以分辨 |
近期配置排前面 |
| 查历史决策 |
需要手动翻找 |
历史还在,只是权重低 |
9. SQLite 还是 QMD,该怎么选?
上面介绍了 QMD 后端,你可能会问:那我到底该用哪个?
简单说一下我的理解:
SQLite 后端(默认)
开箱即用,不需要额外配置。适合个人使用、文档不太多(几百个以内)的场景。
QMD 后端
需要单独安装,但性能更好。适合文档比较多、想索引多个目录的场景。缺点是配置稍微麻烦一点,而且目前还是实验性的。
我的选择:
- 文档不多:SQLite 后端够用了。
- 文档多、目录多:QMD 后端,性能更稳。
不管选哪个,记忆的源头都是本地的 Markdown 文件——我能看到、能改、能用 Git 管理。这正是 OpenClaw Memory 最打动我的地方。
10. 几个实用小技巧
1. 定期清理每日日志
用久了 memory/ 目录会很大,我每月归档一次:
mkdir -p memory/archive/2026-01
mv memory/2026-01-*.md memory/archive/2026-01/
2. 敏感信息只放 MEMORY.md
MEMORY.md 只在私聊加载,群聊看不到。密码、地址这类敏感信息,只往这里写。
3. 善用 extraPaths
除了 memory/ 目录,我还会把项目文档、技术笔记都加到 extraPaths 里。这样搜索时,AI 能同时参考历史对话和项目资料,思考更全面。
4. 如果不需要高级搜索
如果只想用简单的文件存储功能,不需要向量搜索,可以直接禁用记忆插件:
{
plugins: {
slots: {
memory: "none"
}
}
}
写到这里,我想回到开头的那个场景。
那个关于 Redis 配置的问题,后来我用 OpenClaw 解决了。它不仅记得我之前的配置,还记得我当时说“这个实例主要做缓存,对一致性要求不高”——这句话我自己都快忘了。
一个真正好用的记忆系统,就应该是这样:你不需要刻意提醒,它会自己记住关键上下文;当你想找的时候,它能在合适的时间点把合适的信息递给你。
OpenClaw Memory 离完美还有距离(比如本地嵌入模型的首次配置还是有点繁琐),但它的设计思路是对的——用最简单的技术(Markdown + 本地文件),解决最实际的问题(AI 的长期记忆)。
如果你也在寻找或构建一个有长期记忆能力的 AI Agent,不妨去它的 GitHub 仓库 看看,或许能给你带来一些启发。
相关资源
你对 AI 智能体的记忆系统有什么看法或实践经验?欢迎在 云栈社区 与更多开发者交流探讨。