Hermes Agent 是怎么"记住你"的?
摘要
Hermes Agent 能"记住你",不是靠更大的上下文窗口,而是靠一套四层分工的长期记忆系统:USER.md(1,375 字符 / 约 500 tokens)负责"你是谁",MEMORY.md(2,200 字符 / 约 800 tokens)负责"我们做过什么",SQLite + FTS5 会话档案负责"任何一句原话都可以数周后精确翻回来",Skills 负责"我该怎么做这类事"。写入由 Agent 在 Compression / Checkpoint / Nudge / 用户显式指令四种时机主动组织,召回同时结合结构化默认加载、FTS5 精确命中、LLM 语义摘要三条腿——这才让"记住你"从概念落到工程。
引子:大部分 AI 助手让人失望的第一个瞬间
不是它答错了什么,而是——
"你上次不是刚跟我说过吗?"
上下文窗口从 8k 一路飙到 200k、1M,但"记住你"从来不是靠塞更多 token 能解决的:一次会话内的 200k 上下文,会话一断就烟消云散。真正想让 Agent 长期记住你,必须回答三个反问:
- 什么值得被写入长期记忆?(写入闸门在哪?)
- 记忆应该以什么形态存下来,才能几周后仍然可以被找到?
- 找的时候,Agent 是靠向量相似度,还是靠别的东西?
Hermes 用一整套长期记忆系统正面回答了这三个问题。下面把它拆成 5 层来看。
一、先定义"记住"是什么
在人类语境里,"记住你"至少包含三层意思:
- 知道你是谁——名字、职业、偏好、常用工具链。
- 知道我们一起做过什么——之前聊过的项目、给过的结论、踩过的坑。
- 知道该怎么和你打交道——你喜欢简短还是详细?先结论还是先过程?
一个只有大上下文窗口的模型,能在一次对话内同时做到这三点;但只要会话一断,第 1、3 点就重置了。
Hermes 的思路是:把这三层分别落到不同的持久层里,各自用最合适的方式维护——第 1 点交给 USER.md,第 2 点交给 MEMORY.md,第 3 点由 USER.md 中的偏好字段 + Honcho 用户建模共同维护。
二、写入:Agent 主动组织,而不是随手记
Hermes 的长期记忆不是"每说一句话就记一条",而是由 Agent 在四种明确时机主动组织并落盘:
| 触发时机 | 作用 |
|---|---|
| Compression(压缩) | 上下文接近上限时,先把当前会话里"值得长期保留"的信息抽出来,再压缩当前 context |
| Checkpoint(检查点) | 完成一个子任务、切换话题等里程碑时,主动记一次 |
| Nudges(周期性提示) | 系统周期性地"戳"一下 Agent:"看看有没有值得写入长期记忆的内容?"这避免了信息在长会话里悄悄丢失 |
| 用户显式指令 | 用户直接说"以后记住我在 X 项目里用的是 Y",会被识别为高优先级记忆写入 |
关键在于:决定是否写入长期记忆的是 Agent 自己,而不是全量落盘。这一步过滤,是"记忆质量"的第一道闸门——也是它和"每句话都存"的 Chat 历史最本质的区别。
一个具体的经济账:如果没有这层过滤,一个日活 50 次的用户,一年会往长期记忆里灌进大约 1,800 万 tokens 的原始对话;而 Hermes 的做法能把这个数字压到 1% 以下,同时保留几乎全部关键事实。
三、存储:四层分工,各司其职
Hermes 把长期记忆拆成四种,分别放在不同的位置,每一层都有明确的容量上限:
| 层 | 载体 | 典型容量 | 加载时机 | 主要职责 |
|---|---|---|---|---|
| 用户画像 | USER.md | ~1,375 字符 / ~500 tokens | 每次会话必载 | 你是谁、角色、偏好、常用栈、沟通风格 |
| 事实记忆 | MEMORY.md + memories/ | ~2,200 字符 / ~800 tokens | 每次会话必载 | 事件、决定、结论、跨会话要复用的事实 |
| 会话档案 | SQLite + FTS5 全文索引 | 无上限(数月历史) | 按 query 命中时载入 | 任何一句原话都可以数周后精确翻回来 |
| 程序性记忆 | skills/ 目录(SKILL.md) | 单文件 KB 级 | 场景匹配时高优先级装载 | "遇到这种情况我该怎么做"(本分类另有专篇) |
除此之外,Hermes 还有一份 SOUL.md——Agent 自己的"人格描述",属于 Agent 的自我模型,不属于用户记忆,但会和用户记忆共同构成上下文底座。
为什么每一层都设死上限?
有人会问:既然上下文窗口这么大,为什么 USER.md 只给 500 tokens?
三条理由:
- 系统提示每多 1,000 tokens,每天 50 次调用一年浪费 1,800 万 tokens——一等一的成本压力。
- 每次会话必载的东西,必须精挑细选——它是系统提示的一部分,臃肿了会挤压真正的任务上下文。
- 上限逼出取舍——容量满了不会静默丢弃,而是逼 Agent 主动整合(后面第五节讲)。
这也是 Hermes 的核心哲学:"记住"不是"存下",是"经过取舍的存下"。
一个不能忽视的补充组件:Honcho
Hermes 还引入了一个叫 Honcho 的组件,做的是 dialectic user modeling——通俗讲,就是不断从对话里抽取"关于用户的可复用陈述",反哺 USER.md 的维护。
结构化文件不擅长的"隐性偏好"(比如"这个用户总在下午 3 点后不耐烦"、"用户对语气助词特别敏感"),就靠这一层纯 LLM 驱动的推断来补齐。
四、召回:结构化 + 全文 + 语义,三条腿走路
传统 RAG 方案的召回,很依赖向量相似度。但只用向量,会遇到两个老大难问题:"你重要不代表你和 query 相似"、"细节被稀释在整段里"。
Hermes 的召回策略更像"混合检索":
| 检索方式 | 触发场景 | 典型延迟 |
|---|---|---|
| 结构化默认加载 | 每次对话启动 | 几乎为零(就是系统提示的一部分) |
| FTS5 全文检索 | 用户问具体事:"上次那个报错是啥来着?" | ~20ms 命中,~1ms 翻页 |
| LLM 语义摘要 | 需要跨条目整合的问题 | 秒级,用便宜模型跑(如 Gemini Flash) |
这三层配合,才让"记住你"不只停留在"我们向量相似",而是"我真的知道你说过什么"。
一个便利贴的类比可以帮你理解这个分层:USER.md 是贴在显示器边框上的便利贴(每次抬眼就看得到),MEMORY.md 是桌上的日记本(每次抬眼也看得到,但内容更多),SQLite+FTS5 是书柜里的档案盒(不常翻,但要找一定找得到),Skills 是肌肉记忆(该做的时候身体自己知道)。
五、更新:记忆是活的,不是流水账
一个常被忽视的点:记忆不仅要能写入,还要能被修改和淘汰。Hermes 在这点上有三条明确策略:
理由 1:新旧冲突时,优先更新而不是并列写入
避免"分裂人格"——不能同时存在"用户偏好 Vue / 用户改用了 React / 用户又回到了 Vue"三条并列的记录。Hermes 的做法是:偏好类字段覆盖旧值,事实类保留历史但更新"当前状态"字段。
理由 2:长期没被引用的记忆条目,会被判定为"低价值"逐步降权
MEMORY.md 有硬上限(2,200 字符),容量满了的时候会返回:
{
"success": false,
"error": "Memory at 2,100/2,200 chars. Consolidate now...",
"current_entries": [...],
"usage": "2,100/2,200"
}这不是错误,而是闸门信号:Agent 必须做取舍,把陈旧的、低价值的条目合并或删除,才能继续写。
理由 3:用户明确否认的信息,立刻删除
不是"记录一条相反的",而是物理删除——保持世界模型自洽。
也就是说,Hermes 更接近"编辑一份活的档案",而不是"追加一份日记"。
六、这套机制想真的跑通,还差一个东西
再好的记忆机制,也需要一个前提:Agent 得一直活着。
如果你把 Hermes 装在自己笔记本上,笔记本一合盖就"打盹",后台自省循环(nudge)就停摆;换设备、系统重装还要手动搬 ~/.hermes/ 目录;FTS5 索引每次重装都要从零重建。
这时候,云托管方案就变得非常有意义。LightVela 是云托管的 Hermes Agent 服务:
- 独立云端实例,24×7 在线,
MEMORY.md/USER.md/SQLite 会话档案永久驻留; - 后台 nudge 循环持续运行,Agent 真正做到"你不用它的时候也在成长";
- 数据仅存于你的专属服务器;
- 手机、笔记本、Telegram、飞书……多渠道进来都是同一个"认识你的 Agent"。
Hermes 把"记住你"做成了工程实现;LightVela 让这套工程实现的每一天都在你身边生效。
小结
- Hermes 的"记住你"不是靠更大的窗口,而是靠主动整理 + 分层存储 + 混合召回 + 持续更新。
- 每一层都有明确容量:
USER.md500 tokens,MEMORY.md800 tokens,SQLite 无上限,Skills 场景化。 - 好的 Agent 记忆系统,一定是"编辑档案"而不是"追加日记"——上限逼出取舍。
- LightVela 想做的,是把这份能力从命令行带到产品里,让"被记住"成为默认体验。