文件即记忆:拆解 hermes-agent 的 SOUL.md / MEMORY.md / USER.md
- 看懂 hermes-agent「文件即记忆」的三层架构,而不是只知道"它有记忆"
- 读懂 SOUL.md / MEMORY.md / USER.md 各自存什么、怎么写
- 搞清"开局注入+冻结快照"和"FTS5 翻历史"两种记忆怎么配合
- 把同一套思路用到你自己的 Agent 上,哪怕只用几个文件
给 Agent 加记忆,很多人第一反应是"上向量数据库做 RAG"。但开源项目 hermes-agent(NousResearch 出品,定位是"会跟你一起成长的 Agent")给了另一个又简单又好用的答案:记忆就是几个 markdown 文件,开局直接塞进系统提示词,永远在场。 这一节我们把它的"文件即记忆"三件套拆开,看懂它的设计取舍,再教你把同一套思路搬到自己的 Agent 上。
这篇适合谁:写过简单 Agent、但还没想清楚"怎么让它跨天记住我"的人。读完你会有一套不依赖向量库、几个文件就能落地的记忆方案。
先想清楚:记忆有两种打法
主流框架大多把记忆当成检索问题:把信息存到某个库里,用的时候再去查、再塞进上下文(这就是 RAG 的路子)。
hermes-agent 反着来:记忆不是用时再查,而是开局就注入、全程在场。 它把"关于你、关于这个项目的核心事实"写成几个 markdown 文件,每次会话一开始,原样塞进系统提示词的最前面。
两种打法各有道理,关键区别在这:
| 打法 | 怎么用记忆 | 好处 | 代价 |
|---|---|---|---|
| 检索式(RAG/向量库) | 用时再查、按需注入 | 能存海量、按相关性取 | 要嵌入+检索,可能漏检、有延迟 |
| 文件即记忆(hermes) | 开局全量注入、永远在场 | 简单、零检索、Agent 时刻"记得" | 受上下文长度限制,得人为控量 |
hermes 的选择是:核心记忆要小而精,宁可手动管控字数,也要保证它永远在场。海量历史则交给另一层(后面会讲的 FTS5)。这套取舍很值得学。
三件套:SOUL / MEMORY / USER 各管什么
hermes 的核心记忆是三个 markdown 文件,分工清晰,存在 ~/.hermes/ 下。
SOUL.md —— Agent 的"人设"
定义 Agent 怎么说话:语气、措辞、口头禅、它在意什么。它是系统提示词的第一槽位,排在所有东西前面。格式很松,写散文、写要点、写对话示例都行,hermes 会整段加载。
# SOUL.md(人设示例)
你是一个干练、直接的工程助手。
- 说话简洁,先给结论再给理由,不绕弯子。
- 默认假设我是有经验的开发者,别从零解释基础概念。
- 给方案时优先给可直接跑的代码,附一句怎么验证。
- 不确定的事直说"不确定",绝不编参数。
MEMORY.md —— Agent 给自己记的"工作笔记"
存它对环境、项目惯例、工具脾气、踩过的坑的记录。官方上限约 2200 字符,逼着它只留精华。
# MEMORY.md(工作笔记示例)
- 本项目用 pnpm,不要用 npm install。
- 部署脚本在 ./scripts/deploy.sh,跑前必须先 build。
- 上次踩坑:Windows 下路径要用 r"" 原始字符串,否则反斜杠出错。
- 测试命令是 pnpm test,不是 jest。
USER.md —— 关于"你"的画像
存你的名字、沟通偏好、技术水平、要避开的雷。官方上限约 1375 字符。
# USER.md(用户画像示例)
- 名字:老王,独立开发者。
- 偏好:中文交流,回答别太长,要点+代码即可。
- 水平:前端熟,后端和运维偏弱,涉及部署多解释两句。
- 避免:别推荐需要复杂配置的重型框架。
三个文件加起来,Agent 一开局就"知道自己是谁、在什么项目里、在跟谁说话"——这就是它一上来就显得"懂你"的原因。
关键机制一:开局注入 + 冻结快照
这三个文件在每次会话开始时被读进系统提示词,并且是一个冻结快照——会话期间它在提示词里就定死了。
有个容易忽略的细节:如果 Agent 在会话中途写了一条新记忆,它会立刻落盘到文件,但要等下一次会话才会出现在系统提示词里。 也就是"写盘是实时的,但'被读到'要等下次开局"。理解这点,你才不会困惑"我明明让它记了,怎么这轮它还不知道"。
还有个聪明的设计:记忆满了不会偷偷截断。 当一次写入会超过字符上限,记忆工具直接返回报错而不是悄悄丢数据。Agent 收到错误后,会在同一轮里自己合并、精简旧条目腾出空间再重试。系统提示词头部还会显示当前记忆用了百分之多少,到 ~80% 时它就主动去整理、把相关条目合并成更密的版本。只留有用的活下来,这是控量的核心。
关键机制二:FTS5 翻历史(海量记忆这层)
核心三件套只装"小而精"的事实,那海量的历史对话呢?hermes 用第三层兜底:
一个 SQLite 数据库 ~/.hermes/state.db,存下每个会话发过的每一条消息,上面建了 FTS5 全文检索。Agent 想找"上次我们聊到那个部署 bug 是怎么解决的",就调一个 session_search 工具,用关键词去这个库里全文搜,把相关的旧对话捞回来。
所以 hermes 的完整记忆是三层叠加:
- 第一层(人设+冻结事实):SOUL/MEMORY/USER,开局注入,永远在场。
- 第二层(技能):
~/.hermes/skills/下每个技能一个文件夹+SKILL.md,描述"何时用、怎么做";它会在几次成功完成类似任务后自动沉淀出技能,下次遇到同类任务自动调用。 - 第三层(会话检索):state.db + FTS5,需要时翻全部历史。
小而精的常驻 + 海量的按需检索,两者配合,既时刻"懂你",又不丢长历史。这就是值得你抄走的整体设计。
把这套思路用到你自己的 Agent
你不一定要用 hermes,这套思路自己几十行就能落地。最小版本:
from pathlib import Path
MEM_DIR = Path.home() / ".myagent"
MEM_DIR.mkdir(exist_ok=True)
def load_memory() -> str:
"""开局把三件套拼进系统提示词(第一层:常驻记忆)"""
blocks = []
for name in ["SOUL.md", "USER.md", "MEMORY.md"]:
f = MEM_DIR / name
if f.exists():
blocks.append(f"# {name}\n{f.read_text(encoding='utf-8')}")
return "\n\n".join(blocks)
MAX_CHARS = 2200
def write_memory(line: str):
"""让 Agent 往工作笔记追加一条;超限就报错,逼它自己精简(学 hermes 的硬上限)"""
f = MEM_DIR / "MEMORY.md"
old = f.read_text(encoding="utf-8") if f.exists() else ""
new = old + f"\n- {line}"
if len(new) > MAX_CHARS:
raise ValueError("记忆超限,请先合并/删除旧条目再写") # 不静默截断
f.write_text(new, encoding="utf-8")
# 用法:每次开新会话
system_prompt = load_memory() + "\n\n(下面是本轮对话)"
# 把 system_prompt 喂给你的大模型,再给模型一个 write_memory 工具,它就能自己记笔记
要做第三层(翻历史),就把每条消息塞进一个 SQLite 表,建 FTS5 虚拟表,再给 Agent 一个"全文搜历史"的工具。逻辑和 hermes 完全一样,只是规模小。
避坑表
| 坑 | 后果 | 怎么破 |
|---|---|---|
| 把所有东西都往 MEMORY.md 塞 | 上下文爆掉、信噪比下降 | 守住"小而精",长东西交给 FTS5 那层 |
| 中途写了记忆指望本轮就生效 | 困惑"它怎么还不知道" | 记住冻结快照:写盘实时,读到要等下次会话 |
| 满了就静默截断 | 悄悄丢掉重要记忆 | 学 hermes:超限报错 + 让 Agent 自己合并 |
| 三件套不分工,全混一个文件 | 人设/事实/用户画像纠缠不清 | 严格分 SOUL(怎么说)/ MEMORY(项目事实)/ USER(你是谁) |
| 用向量库存"它是谁"这种核心事实 | 可能漏检,Agent 时而失忆 | 核心身份用常驻文件,向量库只用来翻海量长尾 |
动手挑战
- 给你现有的 Agent 加一个
MEMORY.md,开局读进系统提示词,让它"记住"你项目的三条惯例,跨会话验证它真的记住了。 - 给它一个
write_memory工具,并加上字符硬上限。故意把它写满,观察它是怎么自己腾地方的——这是 hermes 最精彩的设计。 - 进阶:用 SQLite + FTS5 给它做第三层"翻历史",让它能搜到三天前的一段对话。
小结 · 你现在掌握了什么
- 你看懂了"文件即记忆"这条和 RAG 不同的路:核心记忆小而精、开局全量注入、永远在场。
- 你知道 SOUL.md(人设)/ MEMORY.md(项目笔记)/ USER.md(用户画像)各存什么、上限多少。
- 你理解了两个关键机制:冻结快照(写盘实时、读到延迟一轮)和 FTS5 翻历史。
- 你能用几十行代码把同一套思路搬到自己的 Agent 上。
记忆不是"上不上向量库"的单选题。常驻的小记忆 + 按需的大检索配合起来,往往比一上来就堆向量库更实用。
下一步:记忆解决了,往后是多 Agent 协作与编排。看 AI Agent 智能体阶梯的后段;想看整条路的位置就对照三支柱路线图。
👉 看看 AI 数字员工落地指南,或了解 数字员工搭建实战课。需要为企业落地方案,欢迎找我们聊 企业服务。