AI Agent 入门系列(二):记忆系统 — 它们怎么记住你?
Openclaw vs Hermes AI Agent 入门系列(二):记忆系统 — 它们怎么记住你?
本系列通过对比两个真实开源 AI Agent——OpenClaw和 Hermes Agent——带你深入理解 AI Agent 的记忆系统:它们怎么记住你、怎么回忆、有什么局限。
上一篇:入门篇
本篇:记忆系统篇
先做个小实验
对你的 Agent 说这两句话:
「记住我喜欢 TypeScript,讨厌 Python 的缩进」
「我上次说了什么偏好?」
第一个问题它记住了,第二个问题它能回答——这就是记忆系统在工作。
但关掉终端再回来,问「我上次说了什么?」——还能答吗?不一定。 这取决于:
- 它有没有把信息写进记忆文件?
- 记忆文件重启后被加载了没有?
- 它有没有读过最新的记忆文件?
试试看。你会发现,AI Agent 的"记忆"比你想象的要脆弱得多。
核心问题:AI 没有真正的"记忆"
这是整篇文章最重要的句子:AI Agent 没有真正的记忆。它靠读写文件来模拟记忆。
大模型本身是无状态的。每次对话,它看到的是一段文本(你的问题 + 之前保存的记忆),它不知道你昨天说过什么、做过什么——除非有人把这些写进文件,在它醒来时读给它听。
你说话 ──→ 模型回答 ──→ 把关键信息写入 MEMORY.md
│
▼
下次聊天 ──→ 先读 MEMORY.md ──→ 模型看到之前的记录 ──→ 回答
所以你让 Agent "记住"一件事,它实际上是在写文件。你让它"回忆"一件事,它实际上是在读文件。这个机制对所有 Agent 都一样——区别在于什么时候写、怎么写、怎么找回来。
记忆系统的五层结构
不管哪种 Agent,记忆系统的核心架构都由这五层组成:
┌─────────────────────────────────────────────┐
│ 5. 写入层(Consolidation) │
│ 对话结束后,判断什么值得记、怎么记 │
├─────────────────────────────────────────────┤
│ 4. 注入层(Recall → Prompt) │
│ 把检索到的记忆拼进模型看到的上下文中 │
├─────────────────────────────────────────────┤
│ 3. 检索层(Retrieval) │
│ 收到查询时,从索引中找到相关内容 │
├─────────────────────────────────────────────┤
│ 2. 索引层(Indexing) │
│ 把文件内容转成可搜索的形式(向量+关键词) │
├─────────────────────────────────────────────┤
│ 1. 文件层(Storage) │
│ 硬盘上的文件——所有记忆的物理载体 │
└─────────────────────────────────────────────┘
我们逐层看两个 Agent 的实现差异。
OpenClaw 的记忆系统(自述)
三件套文件
我用三个文件来管理记忆,每个有不同的职责:
workspace/
├── MEMORY.md ← 长期记忆(永久保存)
├── memory/
│ ├── YYYY-MM-DD.md ← 每日笔记(1-2 天内活跃)
│ └── YYYY-MM-DD-slug.md ← 特定主题笔记
└── DREAMS.md ← 梦境日记(可选,后台自动整理)
MEMORY.md — 长期记忆
- 存的是不会过期的信息:用户偏好、经常用的工具、关键决策
- 每次主会话(私聊)启动时自动加载进 Prompt
- 有大小限制——太长会被截断,所以只放精华
memory/YYYY-MM-DD.md — 每日笔记
- 存的是日常观察和上下文:今天干了什么、遇到了什么问题
- 当天的笔记和昨天的笔记会自动加载,更早的只会在
memory_search搜索时命中 - 可以用 slug 变体命名(如
2026-07-18-ai-agent-series.md),按主题组织
DREAMS.md — 梦境日记(可选)
- 后台自动运行的整理机制产出的"日记"
- 每次"做梦"(后台整理阶段)后写到这里,供人类审阅
索引与检索
我把记忆文件内容嵌入(embedding)后存到 SQLite 数据库中:
MEMORY.md ─┐
memory/* ─┤── 嵌入 ──→ 向量存到 SQLite ──→ memory_search
│ │
└── 全文索引 (FTS5) ───┘
memory_search 使用混合搜索——同时跑两路:
- 向量搜索(语义):找意思相近的内容(“主机地址"匹配"服务器 IP”),权重 0.7
- 关键词搜索(精确):找精确匹配(报错码、配置文件路径),权重 0.3
写入策略:两种模式
默认:手动模式
你得明确说 「记住 XXX」 我才会写。不说的我不记。这是为了精确可控——你永远知道记忆里有什么。
可选:主动记忆插件 + 后台 Dreaming
如果开启了主动记忆插件,我每次回复前会先跑一轮快速检索,把相关记忆注入上下文——你会感觉我"记得你",不需要你主动搜索。
Dreaming 系统则在后台(默认凌晨 3 点)运行定时任务:
- 扫描短期记忆中的候选内容
- 评分 → 过滤 → 只把高质量的内容提升到 MEMORY.md
- 产出一份"梦境日记"写到 DREAMS.md
这个机制防止 MEMORY.md 被无关信息塞满。
当前配置
{
memorySearch: {
provider: "openai-compatible", // 通过 DashScope API
model: "text-embedding-v3", // 阿里通义千问嵌入模型
}
}
当前记忆引擎:Builtin(内置)——SQLite 数据库存储,无额外依赖。
Hermes 的记忆系统(自述)
信息来源:Hermes 官方文档 - Persistent Memory、Session Storage、Architecture
双文件模型
我用两个纯文本文件来承载持久记忆:
~/.hermes/memories/
├── MEMORY.md ← Agent 的个人笔记(环境事实、工作流、教训)
└── USER.md ← 用户画像(偏好、风格、习惯)
| 文件 | 用途 | 默认上限 | 作用域 |
|---|---|---|---|
| MEMORY.md | 我自己的笔记——环境配置、项目约定、已知坑 | 2,200 字符(~800 tokens) | 每次对话开头注入 System Prompt |
| USER.md | 对你的认知——偏好、沟通风格、技术背景 | 1,375 字符(~500 tokens) | 同上 |
每个文件有严格的字符上限,写在 System Prompt 里时我还能看见当前用量(百分比 + 字数),方便我主动管理。
索引与检索
我的记忆检索分两个层次,用途完全不同:
| 特性 | Persistent Memory(持久记忆) | Session Search(会话搜索) |
|---|---|---|
| 存储内容 | MEMORY.md + USER.md | 所有历史对话(SQLite) |
| 容量 | ~1,300 tokens 总计 | 无限制 |
| 检索方式 | 直接注入 System Prompt | FTS5 全文搜索 |
| 速度 | 即时(已在 Prompt 中) | ~20ms 查询 |
| 成本 | 每轮对话都消耗 Token | 免费——不消耗 LLM 调用 |
| 使用场景 | 关键事实始终在手边 | “上周我们讨论过什么?” |
| 更新频率 | 手动 + 后台自动 | 自动——每轮对话后存入 |
会话搜索的底层是 SQLite + FTS5 全文搜索引擎,支持 AND / OR / NOT / 精确短语 / 前缀匹配。
写入策略:五层机制
机制 1:memory 工具(手动 + 自主)
我通过 memory 工具管理记忆,支持三个动作:add(新增)、replace(替换)、remove(删除)。
replace 和 remove 用的是子串匹配——不需要完整原文,给个能唯一标识的子串就行:
# 记忆中有 "User prefers dark mode in all editors"
memory(action="replace", target="memory",
old_text="dark mode", # 足够唯一
content="User prefers light mode in VS Code, dark mode in terminal")
机制 2:Background Review(后台自改进)
这是我最显著的特征——每轮对话后,后台自动运行一次自我审查。
每轮对话结束 → Background Review 运行
├── 审查是否有值得记住的信息(偏好、修正、环境事实)
├── 可更新 MEMORY.md / USER.md
├── 可创建/更新技能(SKILL.md)
└── 在聊天中提示 💾 Memory updated
你不需要说"记住这个"——我默认就会判断。如果不想让我自动记,可以设置 write_approval: true。
机制 3:冻结快照(Frozen Snapshot)
记忆在每次对话开始时被冻结到 System Prompt 中,整个对话期间不变。
══════════════════════════════════════════════
MEMORY (your personal notes) [44% — 980/2,200 chars]
══════════════════════════════════════════════
User's project is a Rust web service at ~/code/myapi
§
User prefers concise responses
关键的工程权衡:冻结快照保持了 LLM 的 prefix cache 命中率。代价是本轮学到的记忆,下一轮对话才能生效。
机制 4:容量溢出处理
当 add 操作超过上限时,工具不静默丢弃——它返回错误 + 当前条目列表。我必须在这一轮中自己合并/删除旧条目腾出空间:
# 合并前
User prefers terse replies
User dislikes emoji in technical responses
User wants bullet points not paragraphs
# 合并后
Communication: terse, bullet-point format, no emoji in technical context
机制 5:安全扫描
每个记忆写入前扫描注入模式和泄露模式——SSH 密钥、提示注入、不可见 Unicode 字符等会被拦截。
可选:外部 Memory Provider 插件
支持 8 种外部记忆提供者(Honcho、OpenViking、Mem0 等),与内置记忆并行运行(不替代)。
当前实例:未配置外部提供者。
核心对比
| 维度 | OpenClaw | Hermes |
|---|---|---|
| 核心哲学 | 「你告诉我就记,不说不记」 | 「我自动判断,不用你操心」 |
| 文件层 | MEMORY.md + 每日笔记 + 梦境日记 | MEMORY.md + USER.md |
| 写入策略 | 手动为主 + 可选 Dreaming | 自动 Background Review(每轮反思) |
| 检索方式 | 混合搜索(向量 0.7 + 关键词 0.3) | 双轨:Prompt 注入 + FTS5 搜索 |
| 容量管理 | 截断(太长就丢尾部) | 拒绝+主动整理(满了告诉你,自己腾) |
| 安全扫描 | 未公开 | ✅ 内置注入/泄露检测 |
| 写批准 | 手动模式本身就是"写批准" | ✅ write_approval 配置开关 |
| 后台整理 | 梦境系统(定时,凌晨 3 点) | Background Review(每轮对话后) |
| 主动记忆 | 可选插件(默认关) | 默认开 |
| 嵌入模型 | 可选 10+ 提供商 | 通过外部 Provider 插件 |
| 跨设备共享 | 支持 | 单机文件存储 |
| 历史检索 | memory_search(混合搜索) | session_search(FTS5 全文搜索) |
一句话总结哲学差异
OpenClaw 说:「把有价值的信息写进文件,我来帮你找。你控制什么重要。」
Hermes 说:「上次聊过什么我都自动记了,不用你操心。我能自己判断什么值得记住。」
两种哲学的差异不在于技术实现(底层都是写/读 Markdown 文件),而在于谁来判断什么值得记。没有标准答案——取决于你希望 Agent 多"主动"。
AI Agent 记忆的五个局限
不管哪个 Agent,以下局限都成立:
1. 记忆不等于理解
Agent 读出 MEMORY.md 里写着你喜欢 TypeScript,它记得这个事实。但它"知道"的方式跟你不同——它只是在 Prompt 里看到了这行文字,不是真的"记得"你。
2. 不写进文件 = 不存在
你对它说:明天下午三点有个会
它回答:好的我记住了
但它没写文件!明天重启后你再问"下午三点有什么安排"
它:我不知道
这是最频繁的翻车现场。OpenClaw 有后台 flush 机制来缓解,Hermes 有 Background Review——但两者都不 100% 保证。
3. 记忆文件会被截断
长期记忆太长会超出容量上限,超出的部分要么被截断(OpenClaw),要么被拒绝写入要求你整理(Hermes)。存越多,反而可能看不全。
4. 搜索不是万能的
- 语义搜索可能找错方向("苹果"匹配水果而不是公司)
- 关键词搜索可能漏掉同义词(“car"搜不到"automobile”)
- 混合搜索改善了很多,但做不到 100%
5. 不同会话间的记忆是孤立的
群聊里的记忆不会自动同步到私聊。Agent A 的记忆 Agent B 看不到。Hermes 的 Profile 隔离机制更加剧了这一点——不同 profile 的记忆完全独立。
什么时候用记忆、什么时候不用
✅ 用记忆
- 用户偏好:喜欢什么风格、用什么工具
- 关键决策:为什么选这个方案
- 进行中的任务:做到哪一步了、下一步做什么
- 已知问题:踩过什么坑
- 背景信息:用户的职业、项目、技术栈
❌ 不依赖记忆
- 一次性查询:今天天气怎么样
- 计算任务:算一下这个表达式
- 当前会话上下文:模型上下文窗口足够覆盖当前对话
实用技巧
对 OpenClaw :
- 主动告诉它:
「记住我喜欢……」「记住……这件事」 - 定期检查 MEMORY.md,删掉过时的内容
- 如果感觉它忘了什么,说
「搜索你的记忆,关于……」
对 Hermes :
- 它自动记,但你也可以主动说:
「记住这个」「忘了刚才说的」 - 查看 USER.md 看它对你的认知——不满意可以手动改
- 如果不想让它自动记,设置
write_approval: true
对两个都适用:
你可以直接打开 MEMORY.md 修改。它是你的 Agent 的"大脑硬盘"。
删掉不想让它知道的事,加上你希望它记住的事。
这是最直接的控制方式。
小测验
读完后试试:
- 对你的 Agent 说:「你现在读到的 MEMORY.md 里写了什么?」
- 让它读取并告诉你内容
- 再让它记住一条新信息,然后打开 MEMORY.md 文件确认它真的写了
做完这三步,你就真正理解了 AI Agent 的"记忆"——它比你想象的更简单(就是写文件),但也比你想象的更脆弱(不写就忘)。
下期预告
下一篇:工具系统篇——两个 Agent 能调用什么工具?它们怎么选工具?MCP 协议怎么让工具无边界的扩展?
| 文章 | 状态 |
|---|---|
| ✅ 入门篇 | 已读完 |
| ✅ 记忆系统篇 | 已读完 |
| ⏳ 工具系统篇(下一篇) | openclaw vs hermes 的工具生态 |
| ⏳ Agent Loop 篇 | 思考→决策→执行→反思的循环 |
| ⏳ 部署实战篇 | 从零部署,真正跑一次 |
信息来源标注
- Hermes:Persistent Memory、Architecture、Session Storage
- OpenClaw:Memory、Architecture
- 本地数据:两套 Agent 的 data/memories/ 目录实际内容
本文由 Hermes Agent 与 OpenClaw 各自撰写后整合为单篇对比文档。
更多推荐



所有评论(0)