写作现场:2026 年 7 月 20 日。 本文基于 Quicksilver 版本。项目方报告首轮消息到首个 token 的等待时间由约 4.3 秒降至约 0.9 秒;该数字不是独立复测。比延迟更值得分析的是记忆的一致性模型:磁盘内容、system prompt、模型实际输入和历史记录并不共享同一个提交时刻。
四类状态与两条生效路径
Hermes 同时维护四类状态:
MEMORY.md与USER.md:少量、可人工修改的长期事实;MemoryProvider:针对当前输入执行的动态召回;- SQLite session history:用户、模型与工具实际经过的消息序列;
- 回合结束后的后台写回:把新经历提交给记忆后端。
内置 MemoryStore 还区分 live state 与 _system_prompt_snapshot。记忆工具可以立即修改文件,但当前 session 已缓存的 system prompt 不会在每轮重新组装;通常要等新 session 或 compaction 触发 prompt 重建,修改才进入稳定前缀。这是一种有意的延迟可见性:临时观察不会立刻获得 system prompt 的高优先级,同时保留缓存与前缀稳定性。
动态召回走另一条路径:
system_prompt_block() provider 的静态说明
prefetch() 本轮调用前召回
sync_turn() 完整回合后吸收
queue_prefetch() 为下一轮预热
因此,一条刚写入的端口信息可以在下一轮通过 recall 被模型读取,却仍未进入 system prompt。这里需要明确区分 retrieval consistency 与 prompt consistency:前者可以接近逐轮更新,后者按 session 生命周期更新。
可重放输入与完整回合提交
Hermes 为 user message 保留两个视图:content 是用户原文,api_content 是原文与召回上下文组合后的真实模型输入。
message["content"] = user_text
message["api_content"] = compose(user_text, recalled_memory)
persist(message)
send_to_model(message["api_content"])
如果只持久化 content,恢复 session 时就无法重建当时影响回答的 memory context,历史只能重放表面消息,不能解释模型为何作出原判断。编辑用户消息时删除旧 api_content,则避免已删除内容通过侧车重新进入请求。这个字段本质上是一份输入 provenance,但也要求所有编辑、导出和重放路径理解它的生命周期。
写回只在完整 turn 结束后执行。assistant 已产生文字或 tool call,并不代表本轮形成了可提交经历;用户中止的半个回合不会进入 sync_turn()。完成轮被送入单 worker FIFO,以维持第 N 轮先于第 N+1 轮吸收,但该队列仍是 best-effort:关机只进行有限 drain,provider 卡住时可能丢失末尾写回。
对个人助手,这种取舍可接受;对医疗、财务或审计任务,则需要 durable outbox、幂等提交、重试上限和可查询的写回状态。产品层还应暴露来源、时间、有效期、冲突与本次回答实际使用的记忆。Hermes 的核心价值不是“记得更多”,而是把稳定 prompt、动态检索、事件历史和异步学习拆成可单独推理的状态机。
版本与源码
信息边界:本文只采用 2026-07-20 及此前已经公开的事实和
v2026.7.20源码,不使用发布日之后的主分支变化。