📚 系列导航:上一篇 Hermes Agent 自改进边界指南 已经讲清“自改进边界:哪些经验不该写进 Skill”;本篇聚焦 Hermes Agent 记忆系统;下一篇 Hermes Agent 会话搜索教程 继续学习“会话搜索与 SQLite FTS5 原理”。
先给结论:Hermes 不把所有历史硬塞进上下文,而是把记忆拆成会话、持久事实和程序性 Skill 三层。 三层分别回答“说过什么”“稳定事实是什么”“这件事怎么做”,各自用不同的存储和加载方式。
ℹ️ 版本说明: 原稿基于 Hermes Agent v0.16.0(2026 年 6 月)源码整理。本文保留其版本化机制分析;命令、数量和界面请以 Hermes Agent 官方文档 与本地输出为准。
Hermes Agent 为什么需要分层记忆
判断一个 Agent 好不好用,我有个土办法:连着用它十次,看它认不认得你。
多数工具是金鱼,七秒记忆。这次告诉它你的项目用 httpx 不用 requests,下次它照样给你写 requests。它不是不听话,是真的不记得。每开一个新会话,它就是一张白纸。
Hermes 想做的是老友:你不用每次重新自我介绍,它知道你是谁、在忙什么、讨厌什么。要做到这点,光靠「把历史塞进上下文」是不行的。聊得越久,上下文越长,最后又变回那条撑死的金鱼。
真正的解法是分层。把「刚才说了什么」「关于你的稳定事实」「怎么做某件事」拆成三种不同的记忆,各用各的存储,各管各的事。这就是 Hermes 的三层记忆。
| 层 | 管什么 | 存哪 | 类比 |
|---|---|---|---|
| 会话记忆(情景) | 什么时候说过什么 | SQLite + FTS5 全文索引 | 翻得到的聊天记录 |
| 持久记忆(语义) | 关于你和环境的稳定事实 | MEMORY.md + USER.md 两个文件 | 贴在桌前的便利贴 |
| Skill 记忆(程序性) | 某件事具体怎么做 | skills/ 下的 markdown | 写好的操作手册 |
这一节我重点讲中间那层。会话记忆放到下一节单独说,那里有个更精彩的故事;Skill 记忆前面讲学习循环时已经铺过。持久记忆是这两个月补全得最彻底的一块,旧版本只是一句「SQLite 状态」带过,现在它长成了一套挺讲究的体系。
MEMORY.md 与 USER.md 的区别
持久记忆其实就是两个 markdown 文件,躺在 ~/.hermes/memories/ 里。一个叫 MEMORY.md,一个叫 USER.md。
分两个文件不是为了好看。MEMORY.md 装的是 Agent 自己的笔记:这个项目的约定、某个工具的怪癖、上次踩过的坑。USER.md 装的是关于你的画像:名字、角色、偏好、说话风格。一个是「我(Agent)记住的事」,一个是「我对你的理解」。
两个库都有字符预算,到顶就得自己取舍。MEMORY.md 约 2200 字符,USER.md 约 1375 字符,加起来不到一千个汉字。这个限制是故意的。记忆不是越多越好,便利贴贴满一墙就等于没贴。Agent 被迫只留最该留的,反而保持了精度。
一个细节:它数的是字符不是 token。注释里写得很直白:字符数跟模型无关,换个模型也不会变。这种「不为某个模型的分词器买账」的克制,是整个产品的性格。
持久记忆写盘与冻结快照机制
这是持久记忆里我最喜欢的一个设计,也是旧书完全没讲的。
先说个矛盾。记忆当然要持久,你这一轮存的东西,最好马上落盘别丢。但记忆又是要喂给模型的,它会被塞进系统提示里。问题来了:如果会话进行到一半,记忆变了,系统提示跟着变,那么前缀缓存就废了。
前缀缓存是省钱省延迟的命根子。模型每次推理,开头那一长串固定不变的提示(系统提示、工具定义、记忆)可以直接命中缓存,不用重新算。一旦中途改了一个字,缓存从那个字往后全部作废,后面每一轮都要重新付费、重新等待。一段长对话里,这笔账能差出很多。
Hermes 的解法很巧:写盘是实时的,给模型看的是冻结的。

其实就是:你这一轮存进去的记忆,确实当场就写进了硬盘,丢不了。但它不会立刻进模型的脑子—要等到下一次会话开始,才作为新快照注入。换来的是,这整段对话的前缀缓存一直完好。
源码里它维护了两套状态:一套是冻结的快照,专门喂系统提示;一套是活的条目,工具响应反映的是它。一个负责稳定,一个负责真实,互不打架。我觉得这是那种「想清楚了才写得出来」的设计,不复杂,但点子很正。
Hermes Agent 记忆投毒风险
有了持久、会跨会话延续的记忆,就多了一个别人没怎么操心的麻烦:记忆本身可以被投毒。
想象一下,某段对话里混进了一句恶意指令,被 Agent 当成「值得记住的偏好」存进了 MEMORY.md。因为记忆会以冻结快照进系统提示、还会跨会话持续,这一条脏数据,就能毒掉之后一整段甚至好几段会话。这比单次的提示注入危险得多,它有持久性。
Hermes 的应对是「进门两道安检」:

记忆写入时的威胁扫描
记忆要存盘的那一刻,先过一遍威胁模式检测,可疑内容拦在门外。
记忆加载到快照前的二次扫描
命中威胁的那一条,在快照里被替换成 [BLOCKED: …] 占位,模型看不到它的原文;但活状态里原文保留,你还能自己查看、自己删掉。
这套防御不是记忆层单独造的轮子。威胁模式来自同一个来源文件,跟工具结果扫描、上下文文件扫描共用一套。后面讲安全的那一章会专门拆这个「三个咽喉点防注入」的体系,记忆只是其中之一,这里先埋个伏笔。
还有个更朴素的防护:如果别的进程(某个补丁工具、一条 shell 追加、你手动改、或者另一个并发的会话)往 MEMORY.md 里塞了它解析不回来的内容,memory 工具会拒绝写入,先把现状备份成 .bak ,提示你先处理冲突。宁可停下报警,也不静默覆盖你的数据。
💡 核心建议
这套设计的潜台词是:记忆越强大,越要把它当成不可全信的输入来对待。一个会永久记住你的 Agent,必须同时是一个会怀疑自己记忆的 Agent。能力和警惕,是一起长出来的。
Hermes 与 Claude Code 记忆机制对比
讲到这,你可能会想起 Claude Code 的记忆。它也有个 MEMORY.md,每次会话开头读一遍,了解你是谁、在做什么。我自己天天用,体验确实好。两者像,但底层心智不太一样。
| 维度 | Claude Code auto-memory | Hermes 持久记忆 |
|---|---|---|
| 载体 | 单个 MEMORY.md(约 200 行上限) | MEMORY.md + USER.md 双库,各有字符预算 |
| 事实/画像 | 混在一份文件里 | 「关于环境」和「关于你」物理分开 |
| 写入时机 | 触发式(你说「记住」或满足条件) | nudge 定时提醒 + 上下文将丢失前抢存 |
| 缓存友好 | 会话内一般稳定 | 显式冻结快照,为前缀缓存而设计 |
| 防注入 | 较轻 | 写入扫 + 加载扫 + BLOCKED 占位 |
不用急着评高下。Claude Code 的记忆更轻、更顺手,因为它跑在你盯着的桌面上,出了岔子你随手就改了。Hermes 把记忆做得这么重,是因为它的设定是住在云端、24 小时无人值守的数字同事。没人盯着的东西,得自己长出免疫系统。同一个 MEMORY.md 文件名,背后是两种部署现实。
它还有两个行为层的小机关。一个叫 nudge,每隔大约十轮就提醒 Agent 一句「有什么值得存的吗」,免得它光顾着干活忘了记笔记。一个叫 flush,在上下文快要丢失之前(压缩、重置、退出的那一刻)再给 Agent 一轮机会抢存记忆,但只有这次聊得够久(默认六轮以上)才触发,避免把没营养的短对话也记下来。
Hermes 外部记忆 Provider
严格说,记忆不止三层。三层是内建的,出厂自带、零配置、全本地、不要钱。在它们之外,Hermes 还留了一个可选的外挂位:外部记忆 provider,做的是更深的跨会话用户建模,比如 Honcho。
这一层不是默认开的,要自己去 hermes memory setup 里选一个装上,可能还得配 API key。目前目录里并排放着八个候选,但硬规矩是同一时刻只能开一个,多了会被拒,免得一堆后端互相打架、把工具列表撑爆。
这个安排很能说明 Hermes 的取舍:基础的记住你,它出厂就替你办好了,不挑你装没装别的服务;想要更花哨的用户建模,门开着,但要你自己走进去。
下一节我们钻进第一层,会话记忆。那里有个我特别想讲的故事:Hermes 把一件本不该用大模型来干的活,从大模型手里要了回来,结果又快、又准、还不要钱。
常见问题
Hermes Agent 的记忆保存在哪里?
持久事实主要保存在 MEMORY.md 和 USER.md,会话历史进入可检索存储,程序性经验则放进 Skills。不同层解决的问题不同,不应混成一个无限增长的文件。
Hermes 新写入的记忆会立即生效吗?
记忆可以立即写盘,但当前会话给模型使用的快照通常保持冻结,以保护提示缓存稳定。新记忆会在后续会话重新加载时进入上下文。
这篇教程里的版本数字会变化吗?
会。原稿以 Hermes Agent v0.16.0 为分析基线,平台、工具、命令参数和默认配置可能继续变化;实际操作前请核对当前官方文档和本地命令帮助。