Hermes Agent 记忆系统拆解:AI 智能体到底该怎么“记住事”?
如果你做过 AI Agent,一定会被一个问题折磨过:
到底什么东西该让模型一直记着?什么东西该用的时候再查?
很多智能体的记忆系统,一上来就想搞个“大脑”。
用户说过的话,全存。
任务过程,全存。
报错日志,全存。
连一句“今天咖啡不错”都恨不得塞进长期记忆。
结果呢?Prompt 越来越肿,缓存频繁失效,模型每轮都背着一大包旧账跑。慢,贵,还容易胡扯。
Hermes Agent 的设计就清醒得多。
它的核心思路很简单:
真正重要的信息,少量常驻。
大量历史记录,按需搜索。
做事方法,沉淀成技能。
用户画像,需要时再补充。
这篇教程咱们就拆 Hermes 的记忆系统,看看一个靠谱的 AI Agent 应该怎样“记事”。
一句话看懂 Hermes 的记忆架构
Hermes 不是一套记忆系统,而是四层组合:
| 层级 | 存什么 | 放在哪里 | 什么时候用 |
|---|---|---|---|
| 提示词记忆 | 用户偏好、环境事实、稳定规则 | MEMORY.md / USER.md | 每次对话常驻 |
| 会话搜索 | 过去聊天记录、历史上下文 | SQLite 数据库 | 需要回忆旧对话时 |
| 技能记忆 | 操作流程、修复方法、工作套路 | ~/.hermes/skills/ | 遇到类似任务时加载 |
| Honcho 用户建模 | 更深的用户画像、跨设备记忆 | 可选外部层 | 需要长期用户理解时 |
重点不在“记得多”。
重点是:
把不同类型的记忆,放在不同成本的位置。
这才是 Agent 记忆系统最该学的地方。
Hermes 发给模型的上下文长什么样?
理解记忆之前,得先看 Hermes 每轮给模型喂了什么。
它的系统提示词大致按这个顺序组装:
[0] 默认智能体身份
[1] 工具使用规则
[2] Honcho 集成内容,可选
[3] 自定义系统消息,可选
[4] MEMORY.md 固定快照
[5] USER.md 固定快照
[6] 技能索引
[7] 上下文规则文件,比如 AGENTS.md / SOUL.md
[8] 日期、时间、平台信息
[9] 对话历史
[10] 当前用户消息
这里藏着一个关键设计:
Hermes 尽量让系统提示词前半段保持稳定。
为什么?
因为大模型供应商通常会做 Prompt Caching。稳定的前缀越长,缓存命中率越高。命中缓存后,响应更快,成本更低。
所以 Hermes 不愿意每轮都改系统提示词。
它会把常用、稳定、短小的信息放进提示词。
那些大段历史、偶尔才用的旧内容,放进工具或数据库里。
一句话:
系统提示词是黄金地段,不是谁都配住进去。
第一层:提示词热记忆,越小越值钱
Hermes 的本地持久记忆存在这里:
~/.hermes/memories/
里面主要有两个文件。
MEMORY.md:智能体自己的笔记
适合存这些内容:
- 当前机器环境
- 项目路径
- 常用工具限制
- 用户反复纠正过的点
- 某些稳定规范
容量限制:约 2,200 个字符。
USER.md:用户画像
适合存这些内容:
- 用户偏好的回答风格
- 用户身份信息
- 用户常用技术栈
- 用户讨厌什么
- 用户希望 Agent 怎样配合
容量限制:约 1,375 个字符。
两个文件加起来并不大。
大概也就一千多个 token。
听起来寒酸?
恰恰是聪明。
Hermes 不想把长期记忆做成垃圾桶。它只想保留高频、高价值、稳定的信息。
MEMORY.md 和 USER.md 会怎样进入 Prompt?
会话开始时,Hermes 会读取这两个文件,然后把它们渲染进提示词。
格式大概像这样:
═══════════
MEMORY(你的个人笔记)[67% — 1,474/2,200 字符]
═══════════
用户的项目位于 ~/code/myapi,是一个 Rust Web 服务,使用 Axum + SQLx
§
这台机器运行 Ubuntu 22.04,安装了 Docker 和 Podman
§
用户喜欢简洁回答,讨厌绕圈子
几个细节很实用。
用字符数限制,而不是 token 限制
这让系统和模型解耦。
不管你后面接 GPT、Claude,还是别的模型,Hermes 都不用依赖某个 tokenizer 来判断记忆是否爆了。
用纯文本,而不是复杂数据库
条目之间用 § 分隔。
没有一上来就堆向量数据库。
没有奇怪的二进制格式。
就是 Markdown 文件。
简单,能看,能改,也好排查。
会话中途修改,不会马上污染当前系统提示词
这点很关键。
如果模型在当前会话里写入了新记忆,Hermes 会马上落盘。
但当前已经生成好的系统提示词不会立刻变化。
新记忆通常要等到:
- 开新会话
- 或触发对话压缩,重新构建上下文
才会生效。
这样做是为了保护 Prompt 缓存。
不然每写一条记忆,系统提示词就变一次,缓存直接报废。
什么内容值得写进提示词记忆?
Hermes 的记忆不是“聊天日记”。
它更像一张精选卡片。
适合写入:
- 用户明确表达过的偏好
- 稳定的工作环境信息
- 长期有效的项目事实
- 重复出现的错误修正
- 以后大概率还会用到的规范
不适合写入:
- 某次任务的临时进度
- 一次性 TODO
- 某次运行的完整日志
- 当前会话的流水账
- 很快会过期的信息
举个例子。
✅ 值得保存
用户希望代码示例尽量短,先给能跑的版本,再解释关键点。
这条很稳定。下次还会影响回答风格。
❌ 不值得保存
用户刚刚让我把第 3 行变量名改成 user_id。
这只是当前任务细节。塞进长期记忆,纯属添堵。
memory 工具:添加、替换、删除
Hermes 用一个 memory 工具管理这两个文件。
它支持三类操作:
add 添加记忆
replace 替换记忆
remove 删除记忆
比较贴心的是,replace 和 remove 可以用子字符串匹配。
你不需要知道某条记忆的 ID。
只要给出一段唯一文本就行。
比如当前记忆里有:
用户喜欢简洁回答,讨厌冗长解释。
想改成更具体的版本,可以用类似逻辑:
{
"operation": "replace",
"target": "用户喜欢简洁回答",
"content": "用户喜欢直接给结论,再补充必要步骤;不喜欢大段背景铺垫。"
}
Hermes 还会做安全检查。
它会拦截一些危险内容,比如:
- Prompt Injection 指令
- API Key、密码等凭证
- 隐藏 Unicode 字符
- 完全重复的记忆
这很重要。
记忆系统一旦被污染,Agent 会长期带病工作。比一次回答错还麻烦。
第二层:SQLite 会话搜索,专门翻旧账
短小热记忆解决不了所有问题。
用户可能会问:
上周我们聊过那个 Rust API 的鉴权方案,你还记得吗?
这种内容不该常驻系统提示词。
但也不能丢。
Hermes 的做法是:把过去会话存在 SQLite 数据库里,需要时用 session_search 搜。
流程大概是:
用户提到旧内容
↓
在历史消息里全文搜索
↓
按会话聚合结果
↓
找出相关度高的会话
↓
用便宜的辅助模型总结
↓
把精炼结果交给主模型
这个设计很务实。
它不会让主模型每轮都背着几个月的聊天记录跑。
只有当用户真的需要旧上下文时,才去翻数据库。
你可以把它理解成:
MEMORY.md是桌面便利贴- SQLite 会话库是档案柜
session_search是帮你翻档案的人
便利贴上只写每天都要看的东西。档案柜里可以存得很全,但不会摊满桌子。
第三层:压缩前的记忆冲刷,防止重要信息被洗掉
长对话一定会遇到上下文爆掉的问题。
Hermes 会对中间对话做压缩。
压缩能省空间,但有个副作用:信息会丢。
比如用户在中途说过:
以后所有 SQL 示例都用 PostgreSQL,不要用 MySQL。
如果压缩摘要漏掉这句话,后面模型就可能又开始写 MySQL 示例。
Hermes 的处理方式很聪明。
压缩前,它会触发一次“记忆冲刷”。
大致指令是:
会话即将被压缩。请保存任何值得长期记住的内容。
优先保存用户偏好、纠正意见、重复模式。
不要保存具体任务细节。
接着 Hermes 会进行一次额外模型调用。
这次只开放 memory 工具。
模型如果发现有长期价值的信息,就会写进 MEMORY.md 或 USER.md。
然后再进行压缩。
这一步很像搬家前整理桌面:
旧纸箱可以打包,但银行卡、钥匙、合同得先拿出来。
第四层:Skills,把“怎么做”也记下来
很多记忆系统只会记事实。
比如:
- 用户叫什么
- 用户喜欢什么风格
- 项目在哪个目录
但 Agent 真正干活时,还需要记住“方法”。
Hermes 用 Skills 解决这个问题。
技能文件存放在:
~/.hermes/skills/
适合沉淀成技能的内容包括:
- 某类 bug 的排查流程
- 某个项目的部署步骤
- 常见迁移任务的操作套路
- 复杂工具链的固定用法
- 已验证过的修复方案
比如,你反复让 Agent 修同一个项目的数据库迁移问题。
它可以把经验沉淀成技能:
# 修复 SQLx Migration 失败
## 适用场景
Rust 项目使用 SQLx,执行 migration 时提示字段类型不匹配或数据库未同步。
## 操作步骤
1. 检查 DATABASE_URL 是否指向正确环境。
2. 运行 `sqlx migrate info` 查看状态。
3. 对比 migrations 目录与数据库 schema。
4. 必要时执行 `cargo sqlx prepare` 更新离线缓存。
## 注意事项
不要直接删除生产数据库中的 migration 记录。
Hermes 不会把所有技能全文塞进提示词。
它通常只加载技能索引。
模型发现某个技能相关时,再读取具体内容。
这和记忆设计一脉相承:
常用索引可以常驻,大块内容按需加载。
第五层:Honcho,更深的用户建模
Honcho 是可选层。
如果本地记忆像一个笔记本,Honcho 更像用户模型服务。
它能做跨设备、跨平台的记忆连续性。
比如你今天在笔记本上和 Hermes 聊项目架构,明天在另一台机器上继续,它依然能理解你之前的偏好和背景。
但这里有个难点:
如果 Honcho 每轮都改系统提示词,Prompt 缓存又会被破坏。
Hermes 的做法是:
- 会话第一轮,把 Honcho 上下文合入系统提示词
- 后续轮次,把 Honcho 回溯内容附加到当前用户消息后面
这样系统提示词前缀保持稳定。
模型也能读到最新背景。
这就是工程上的取舍:缓存要保,记忆也要用,但别互相拆台。
Hermes 修正了 OpenClaw 的什么问题?
OpenClaw 的记忆更像 Markdown 中心化存储。
日志、长效文件、历史记录,都容易变成主要事实来源。
这种方式有个常见问题:
记忆会慢慢变成流水账。
流水账看起来完整,实际很难用。
因为模型每次都要在一堆旧内容里找重点。
Hermes 的取向更克制:
- 提示词记忆严格限量
- 历史会话放 SQLite
- 旧内容通过搜索召回
- 技能单独管理
- 用户建模可选接入
- 系统提示词尽量稳定
这套设计更适合真实 Agent。
它不会为了“我全都记得”而牺牲速度、成本和稳定性。
如果你要自己做 Agent 记忆系统,可以直接照这个思路
下面这套方案很适合落地。
1. 建一个小型热记忆文件
别急着上向量库。
先做两个 Markdown 文件:
memories/
MEMORY.md
USER.md
建议限制:
MEMORY.md:2000 ~ 3000 字符
USER.md:1000 ~ 2000 字符
里面只放长期有效内容。
2. 给记忆写入设规则
可以给模型这类指令:
只有当信息长期有效、未来多次任务可能用到时,才写入记忆。
不要保存临时任务进度、一次性 TODO、完整日志或会话流水账。
优先保存用户偏好、环境事实、反复纠正的问题和稳定规范。
这比“请记住重要信息”靠谱得多。
后者太空,模型会乱存。
3. 历史会话进数据库
用 SQLite 足够了。
可以建几张表:
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
created_at TEXT,
title TEXT
);
CREATE TABLE messages (
id TEXT PRIMARY KEY,
session_id TEXT,
role TEXT,
content TEXT,
created_at TEXT
);
再加全文索引:
CREATE VIRTUAL TABLE messages_fts USING fts5(
content,
session_id UNINDEXED
);
用户问旧内容时,走搜索,不要把所有历史塞进 Prompt。
4. 长对话压缩前做一次记忆检查
压缩前加一步:
当前会话即将压缩。
请检查是否存在值得长期保存的信息。
只保存稳定偏好、环境事实、重复修正和可复用经验。
然后只开放记忆写入工具。
这一步能救很多关键上下文。
5. 把流程沉淀成技能
不要只记“事实”。
Agent 干活最需要的是“复用方法”。
可以设计一个技能目录:
skills/
debug-sqlx-migration.md
deploy-fastapi-docker.md
refactor-react-form.md
每个技能包含:
# 技能名称
## 适用场景
## 操作步骤
## 常见坑
## 验证方式
Prompt 里只放技能索引。
需要时再加载全文。
避坑清单:做 Agent 记忆最容易翻车的地方
坑 1:把记忆当聊天记录
长期记忆不是日记本。
别存:
用户今天让我改了登录按钮颜色。
要存:
用户偏好 UI 改动先给最小 diff,不要重构无关代码。
坑 2:每轮都改系统提示词
系统提示词频繁变化,会影响缓存命中。
成本会上去,延迟也会上去。
热记忆要稳定,小而精。
坑 3:把任务进度写进长期记忆
任务进度应该在当前会话、任务状态或项目文件里。
别塞进用户画像。
没人希望 Agent 半个月后还记着“昨天正在修第 42 行”。
坑 4:不给记忆做安全过滤
记忆会影响后续很多轮对话。
必须过滤:
- 恶意指令
- 凭证信息
- 隐藏字符
- 重复内容
- 明显过期信息
坑 5:只记事实,不记方法
“用户用 Rust”是事实。
“这个项目 SQLx 离线缓存更新流程”是方法。
后者对 Agent 干活更值钱。
一个好用的记忆分层模板
你可以直接参考这个结构:
Prompt 常驻层
├── USER.md:用户偏好、沟通风格、长期身份信息
├── MEMORY.md:项目环境、稳定规则、反复修正
└── Skill Index:技能目录,不放技能全文
按需检索层
├── SQLite Sessions:历史会话全文搜索
├── Skill Files:需要时加载具体技能
└── External User Model:可选,跨设备用户建模
维护机制
├── memory add / replace / remove
├── 压缩前记忆冲刷
├── 重复内容拦截
└── Prompt Injection 与凭证过滤
关键结论
Hermes 的记忆系统最值得学的地方,不是用了多酷的技术栈。
恰恰相反,它很克制。
它承认一件事:
Agent 的记忆不是越大越好,而是要放在正确的位置。
高频稳定的信息,进入小型提示词记忆。
长尾历史,放进 SQLite 搜索。
可复用流程,沉淀成 Skills。
更深的用户理解,交给可选建模层。
这样做的结果很现实:
- Prompt 更稳定
- 缓存更容易命中
- 历史不会污染当前任务
- 记忆更像资产,而不是垃圾堆
如果你正在做自己的 AI Agent,别一上来就追求“全都记住”。
先问一句:
这条信息未来会反复用到吗?它值得占用系统提示词的黄金位置吗?
想清楚这个问题,记忆系统就已经赢了一半。