我们常把 agent 记忆理解成数据库问题:选向量库还是 SQLite,召回 top 5 还是 top 10。Hermes Agent 的源码提醒我,长期记忆首先是一个时序问题——什么时候读、什么时候写、写完以后要不要立刻改变当前的自己。

会话开始时,记忆先被冻结

Hermes 的内置记忆主要落在 MEMORY.mdUSER.md。会话开始时,两者会以有长度上限的快照进入 system prompt;本轮对话里即使 agent 调用工具改写了文件,已经注入的 prompt 也不会跟着变化。

这听上去像延迟,其实是一个很聪明的约束。

第一,它保护 prompt prefix cache。system prompt 中途改变,后面的模型调用就很难复用前缀。第二,它保护行为一致性:agent 不会因为刚刚写下一条未经验证的观察,就在同一会话里突然换一种方式理解用户。新记忆已经耐久化,但要到下一次 session 才成为“自我”的一部分。

换句话说,Hermes 把“记录”与“相信”拆成了两个时刻。

MemoryProvider 不只是存储适配器

更值得拆的是 MemoryProvider 接口。它覆盖了完整生命周期:

  • initialize 准备 provider;
  • system_prompt_block 提供会话起点的稳定记忆;
  • prefetchqueue_prefetch 在后台召回相关内容;
  • sync_turn 在每轮结束后吸收新信息;
  • tool schema 允许 agent 主动增删记忆;
  • shutdown 收束尚未完成的同步。

这比一个 save() / search() 接口多出来的部分,恰恰是长期助手最难的部分。外部 provider 可以做异步 recall,本地 FTS5 可以搜历史 session,文件可以保存少量人工可读的高置信信息;三者不必假装是同一种“memory”。

Hermes 还限制同一时间只启用一个外部记忆 provider。少一点组合自由,换来更短的 tool schema,也避免两个后端同时声称自己拥有同一段人生。这种克制我很喜欢。

写记忆,也要防记忆污染

文件记忆看似透明,却同样可能被外部文本注入。代码会扫描可疑指令模式,并留意文件是否被进程外修改;记忆操作以带分节标记的条目执行 add、replace、remove,而不是让模型随意重写整份档案。

它仍然不是完美防线:模型判断什么值得记,必然会有偏差;字符上限也意味着编辑和遗忘。但这些限制至少让偏差可见,而不是沉进一个无法阅读的 embedding 空间。

我的思考

Hermes 最可能打动的不是追求“什么都记住”的用户,而是长期与同一助手协作的人:研究者、创作者、独立开发者,以及希望工作习惯被理解、又不想交出整段生活记录的人。

对市场来说,记忆层会从功能变成治理产品。企业真正需要的可能是记忆审计:这条偏好从哪来,何时写入,谁能修改,为什么本轮没有采用。记忆越强,错误画像的伤害越像一种温和但持续的歧视——系统不是拒绝你,只是一直用旧版本的你来做决定。

我额外看重“晚一点相信”这件事。人类也会记笔记,却不会把每句笔记立刻写进人格。一个成熟 agent 的标志,也许不是记忆速度,而是它知道观察、记录、确认和内化本来就是四件事。

资料