我是零一,同你一起见证AI颠覆世界。
Hermes 刚上手时很好用,感觉它能真的记住你,但用过一段时间后记忆就不行了,究竟怎么回事,本文同你一探究竟。
昨天我跟 Hermes 说:"把上次的 Docker 部署笔记总结一下。"它回我:"请使用 session_search 工具查询相关会话。"我又问它部署偏好,它说:"未找到相关记忆。"
不是它不想记。是 MEMORY.md 满了 96%,那条端口映射刚被新内容顶掉。USER.md 也已经 98%。再聊几个项目,Hermes 就要在"记这条新经验"和"删那条旧配置"之间做选择。
我试过把上限改大。三个月下来发现,容量只是表层问题。真正的麻烦是:你不知道什么该记、什么时候召回、旧信息怎么处理,以及它记住的东西到底能不能相信。
这篇不是安装教程。我按程序员视角拆开看:
- Hermes 自带的记忆到底怎么跑
- 第三方记忆值不值得接
- 实测之后我自己的选择和配置
- 给一个推荐起步配置
Hermes 还是装不下
刚开始用 Hermes 时我没觉得"记忆"是个问题。后来才知道 MEMORY.md 有 2200 字符限制。
用了几个月,几件事接连发生:
- 它开始忘端口映射,因为我把它顶掉了
- 它每次都把无关的旧偏好塞进 system prompt
- 长会话里它的 system prompt 比对话本身还长
问题不在容量。问题是没有分层。什么该常驻、什么该按需查、什么该忘记、什么该记下来——这些没人管,全靠 Agent 自己判断。
这就引出两个现实问题:
- Hermes 自己的记忆机制到底是怎么工作的?能不能撑住真实使用?
- 第三方记忆(Mem0、Hindsight 等)能不能补上能力短板,代价是什么?
Hermes 自带记忆:源码视角
~/.hermes/ 下和记忆相关的核心只有 3 个文件:
~/.hermes/
├── config.yaml
├── memories/MEMORY.md
├── memories/USER.md
├── state.db
└── hermes-agent/
├── agent/agent_init.py
├── tools/memory_tool.py
└── tools/session_search_tool.py
第一层:Markdown 笔记
agent_init.py 启动时创建 MemoryStore,调用 load_from_disk() 把 MEMORY.md 和 USER.md 读进内存,生成 _system_prompt_snapshot 注入 system prompt。全会话期间不变。
写入靠单一的 memory 工具,区分三种 action:
memory(action="add", target="memory", content="...")
memory(action="replace", target="memory", old_text="...", new_content="...")
memory(action="remove", target="user", old_text="...")
写入链路:
模型决定要不要记
↓
校验 action / target
↓
威胁模式扫描
↓
解析 § entries、检查字符上限
↓
文件锁
↓
临时文件 + atomic replace
↓
MEMORY.md / USER.md
几个不容易看到的细节:
- 限制按字符算,不按 token 算。换模型不会让容量突然变化。
replace用短字符串匹配,不用 entry ID。不够具体会被打回。- 每轮最多三次记忆整理失败,超过就让 Agent 先回答用户。这是为了防止它为了存一条偏好把整轮预算烧光。
- drift protection:用 shell 或 patch 直接改坏文件,工具会拒绝并保留
.bak快照。
第二层:SQLite 历史会话
session_search 工具直接查 state.db:
state.db → SQLite message store → FTS5/BM25 → 原始历史消息
整个过程零 LLM 调用,返回的是数据库里的真实消息,不是重新生成的摘要。
看起来所有会话都被记住了,但实际 session_search 的调用率极低,一般要你主动叫它调,另外能搜到的信息总是不符合预期。
三个设计限制
- 2200 字符硬上限,虽然可调但会消耗 token,Hermes 的记忆文件容量有限
- 每次会话都全文注入。不管你问 Docker 还是公众号,所有核心记忆都挤进 system prompt。
- 会话中写入不更新当前 prompt。调
memory写入的内容,下一次/new才生效。这是为了保护 prefix cache,但用户体感就是"它写了但没用上"。
所以严格点说:
Hermes 自带两层持久化记忆:Markdown 是整理好的笔记,SQLite 是完整的历史档案。
挂上去的第三方记忆
config.yaml 里的 memory.provider 字段可以挂载一个外部 Provider。官方内置 8 个可选:
| Provider | 类型 | 关键差异 |
|---|---|---|
holographic | 本地 SQLite + FTS5 | 零凭证、信任评分、HRR 检索 |
hindsight | Daemon + PostgreSQL | 知识图谱、实体消解、反思 |
mem0 | 云 API | 生态最大、自动去重 |
honcho | 云 API | 跨会话用户建模、辩证推理 |
openviking | 云 | 文件系统风格浏览 |
retaindb | 云 API | 7 类记忆类型 |
supermemory | 云 API | Profile 召回 |
byterover | CLI + tree | 分层检索 |
同时只能启用一个外部 Provider。不是做不到,是多个 Provider 会带来工具 schema 膨胀、重复召回和冲突写入。
挂载后,Provider 通过 MemoryProvider 接口接入:
memory:
provider: hindsight
走这条链路:
agent_init.py → MemoryManager.add_provider() → provider.initialize()
它不是替换。MEMORY.md 仍然在跑,第三方 Provider 只是 additive。
源码之外,我把当前主流的 Agent memory 方案看了一遍。最终选了本地 docker 一键部署的 Hindsight 首先体验了下。docker-compose 配置如下,端口可以自定义:
services:
hindsight:
image: ghcr.io/vectorize-io/hindsight:latest
container_name: hindsight
restart: unless-stopped
ports:
- "9999:9999"
- "8089:8888"
volumes:
- ./data:/home/hindsight/.pg0
environment:
- HINDSIGHT_API_LLM_PROVIDER=openai
- HINDSIGHT_API_LLM_API_KEY= # 你自己的key
- HINDSIGHT_API_LLM_MODEL=deepseek-v4-flash
- HINDSIGHT_API_LLM_BASE_URL=https://api.01story.com/v1
- HINDSIGHT_API_HOST=0.0.0.0
- HINDSIGHT_API_PORT=8888
- HINDSIGHT_API_LOG_LEVEL=info
- HF_ENDPOINT=https://hf-mirror.com
Hindsight 怎么工作
Hindsight 把过程拆成三个动作。
Retain:输入对话后,独立 LLM 抽取事实、实体、时间和关系,写入 memory bank。它不是原样保存聊天记录,写入本身就是一次知识加工。
Recall:TEMPR 同时跑语义、关键词、图关系和时间检索,再用 RRF 融合、cross-encoder 重排。
Reflect:先查 mental models,再查 observations,必要时回到 raw facts,循环检索后生成带引用的答案。
Hindsight 论文在 LongMemEval 上报告 91.4%,但这个数字依赖数据集、模型和配置。装上不会自动达到。
Hindsight 会自动记录实体和关系并提供了可视化,效果还不错,如下:

一个常被忽略的时序限制
每轮的外部 Provider 块注入到 system prompt,但它是上一轮 prefetch 的结果,不是当前轮的:
第 N 轮:
用户消息
↓
system prompt(MEMORY.md 块 + 外部 Provider 块 [来自上轮])
↓
Agent 回复
↓
sync_turn 写入库
↓
prefetch 用本轮 query 检索
↓
缓存给下一轮
第 N+1 轮:
用户消息
↓
system prompt(MEMORY.md 块不变 + 外部 Provider 块 [新内容])
↓
Agent 回复
第一轮永远召不回任何历史记忆。短句、问候语也经常被忽略。这是 Hermes 的通用机制,不是 Hindsight 专属。因为 system prompt 会不断变化,缓存命中会变得很糟糕。
Token 消耗
| 项目 | 谁花 | 多少 |
|---|---|---|
MEMORY.md 全文注入 | 每轮必带 | 约 2K tokens |
| Hindsight 自动 prefetch | 每轮注入 | 默认 budget=mid,约 80 条事实,2.5K—2.8K tokens |
| Hindsight retain | 异步,每轮一次 | fact extraction 一次 LLM 调用 |
| Hindsight reflect | 按需 | 800—3000ms 内 1 次 LLM 调用 |
session_search | 必要时 | 零 LLM,纯 SQLite FTS5 |
几个绕不开的现实问题
- 自动写入不等于高质量写入。Retain 依赖 LLM,漏抽、错抽都会污染 observation。
- 两套记忆不会自动保持一致。删
MEMORY.md不会同步删 Hindsight。 - 中文不是装完即最佳。默认 embedding 偏英文,中文效果还要看 embedding、reranker 和全文分词器。
- 隐私和安全要自己管。Hindsight 的 Memory Defense 默认关闭且不回扫历史;MCP 默认无认证。
3 个省 token 的习惯
- 控召回量。
recall_budget从mid调到low,召回条数从约 80 条降到 15—20 条;再配recall_max_tokens=2048兜底。 - 一个领域一个会话。写公众号时让 Hindsight 召回 Docker 经验,反而干扰判断。聊完就
/new。 MEMORY.md只放高频稳定的事实。临时状态留在 session history。
装之前想清楚的 2 件事
- 你的场景真的需要跨 30+ 个会话保持上下文吗?5—10 个会话的工作流,Hermes 内置 +
session_search已经够用。 - 你能接受高额的 token 消耗吗?不写清楚这个流程,过几个月两边就开始打架。
小结
回到开头那两个问题:
- Hermes 自带的记忆够不够? 简单场景够,复杂场景不够。容量硬上限、每次全文注入、会话中写入不立刻生效是三个核心限制。
- 第三方记忆值不值得接? 看场景。5—10 个会话的工作流没必要接;长期跨项目偏好才值得。Hindsight 是有真本事的方案,但 token 消耗会上一个台阶,建议第三方记忆使用低成本模型。
真正好用的 Agent 记忆,不是把所有事情永久记住,而是把重要的内容放在正确的层级,并在真正需要时准确找回来。
你的 MEMORY.md 用了多少?评论区报个使用率。
现在就能做的一件事:打开 ~/.hermes/memories/MEMORY.md,把"临时项目状态"那类条目删掉,给真正需要常驻的信息留空间。
本篇主要分析了下 Hermes 的记忆实现,下一期再一起看下当前主流的 AGENT 记忆工具的思路与方案。
觉得这篇有用的话,求一个点赞~3q,关注我了解 AI 最新动态。
