Hermes Agent 的持续学习系统:Memory、Review、Skill 与 Curator

前言:Agent 能保存一段偏好并不稀奇,真正难的是决定记什么、怎样召回、何时把一次经验升级成可复用流程,以及长期运行后如何整理这些内容。本文把 Hermes 的内置 Memory、外部 Provider、Background Review、Skill 和 Curator 放回同一条学习闭环。


系列导航:这组文章按“总览 → 入口 → 运行时 → 扩展 → 状态 → 协作 → 安全”的顺序展开;第一次阅读可以从总览开始,带着具体问题也可以直接跳到专题。

  1. 01|Hermes Agent 架构总览:从 Agent Loop 到智能体平台
  2. 02|Hermes Desktop 架构:Electron 如何连接本地 Python Agent
  3. 03|Hermes Agent 运行时:AIAgent、模型协议与工具执行
  4. 04|Hermes Agent 扩展体系:Skill、Plugin 与 MCP
  5. 05|实战:同一个 Markdown 检查器的 Skill、Plugin 与 MCP 三种实现
  6. 06|Hermes Agent 的持续学习系统:Memory、Review、Skill 与 Curator
  7. 07|Hermes Agent 的长会话架构:Prompt Cache、压缩与 SessionDB
  8. 08|Hermes Agent 的多 Agent 与自动化:从 Goal 到 Kanban
  9. 09|Hermes Agent 安全架构:审批、沙箱、回滚与凭据隔离

先分清历史、记忆和请求上下文

刚接触 Agent 记忆时,我很容易把“聊天历史、长期记忆、上下文压缩”混成一层。Hermes 的实现恰好说明了为什么必须拆开:SessionDB 保存证据,Memory 保存精选事实,Context Engine 决定某次请求实际携带多少历史。

状态层回答的问题主要存储取用方式
SessionDB过去具体发生了什么?state.db 中的原始消息、Prompt、用量与关系恢复会话、FTS5 session_search
Persistent Memory以后每次都值得知道什么?MEMORY.mdUSER.md,可叠加一个外部 Provider会话快照、按轮语义召回、Provider 工具
Context Engine本次模型请求应该带什么?会话内状态或插件自己的索引select_context()compress()
flowchart LR
    Turn[完成一个 Turn] --> DB[SessionDB 原始历史]
    DB --> Search[session_search 精确回看]
    Turn -->|可选精选写入| Builtin[内置精选记忆]
    Turn -->|异步同步| External[外部 Memory Provider]
    Builtin --> Snapshot[下次 Prompt 快照]
    External --> Recall[下轮语义召回]
    DB --> Engine[上下文引擎
Context Engine] Engine --> Request[本次请求消息] Snapshot --> Request Recall --> Request

SessionDB 是事实底账,不是“模型脑内记忆”

SQLite 保存会话、消息、完整 System Prompt、模型用量、父子关系和压缩归档。session_search 直接在 FTS5 中查询真实消息,不需要再调用一个 LLM 做摘要;它适合回答“上周我们在哪个会话讨论过这个错误”,而不是把所有历史都塞进每轮 Prompt。

因此压缩也不等于删除历史。默认 in-place compaction 只替换当前会话的活跃消息视图,原始行会软归档并继续接受全文检索。Memory 写错了也不需要从 SessionDB 反推真相:可以回到原消息核对,再修正精选记忆。

记忆系统:文件快照、语义召回和后台学习

Hermes 的记忆不是一个单独向量库,而是两层可叠加机制:内置 MemoryStore 负责小而稳定的常驻事实,可选 MemoryProvider 负责更深的语义召回、用户建模与后端工具。两者可以同时工作,但外部 Provider 一次只允许激活一个。

内置 MemoryStore:有界、可读、由 Agent 自己维护

文件保存什么默认上限在 Prompt 中的位置
MEMORY.md环境事实、项目约定、工具坑点、完成事项2,200 字符Volatile tier 的冻结快照
USER.md用户身份、表达偏好、工作习惯和期望1,375 字符Volatile tier 的冻结快照

文件位于当前 Profile 的 $HERMES_HOME/memories/MemoryStore.load_from_disk() 在 Agent 初始化时读取、解析并安全扫描条目,然后生成本会话的 System Prompt 快照。memory 工具提供 addreplaceremove;replace/remove 使用唯一子串定位,底层通过锁、临时文件和原子 rename 更新。

它刻意不做“满了自动丢旧内容”。写入超过上限时,工具返回当前 entries 和容量错误,让 Agent 在同一 Turn 里先合并或移除,再重试。精确重复会被拒绝,隐形 Unicode、提示注入和凭据外传模式也会在进入未来 System Prompt 前被阻止。

flowchart TD
    Start[新会话或 Prompt 重建] --> Load[读取 MEMORY.md 与 USER.md]
    Load --> Scan[解析与安全扫描]
    Scan --> Freeze[生成冻结 Prompt 快照]
    Freeze --> Turn[对话循环
Conversation Loop] Turn --> Tool[记忆增改删
memory add / replace / remove] Tool --> Gate{写入审批开启?} Gate -->|是| Pending[进入待审批队列] Gate -->|否或批准| Atomic[原子更新磁盘文件] Atomic --> Next[新会话或压缩重建后可见]

冻结快照解释了一个常见疑问:当前 Turn 的 memory Tool Result 会告诉模型写入成功,但旧 Prompt 不会随即改字节;正常情况下,新内容到下个会话才成为常驻上下文。如果本会话发生上下文压缩,Prompt 重建路径会重新加载磁盘记忆,此时新条目也会进入更新后的快照。

外部 Memory Provider:每轮召回,但不污染干净历史

MemoryProvider 是另一份契约。它可以提供静态 system_prompt_block()、按问题召回的 prefetch()、Turn 完成后的 sync_turn()、Provider 专属工具,以及 session switch、compression、delegation 等生命周期 Hook。MemoryManager 负责选择、超时、工具路由和错误隔离。

sequenceDiagram
    participant U as 用户消息
    participant T as 回合前置阶段
Turn Prologue participant M as 记忆管理器
MemoryManager participant P as 外部记忆提供方
External Provider participant L as 对话循环
Conversation Loop U->>T: 非琐碎问题 T->>M: 回合开始与预取
on_turn_start + prefetch_all M->>P: 有超时边界的 prefetch P-->>M: 相关记忆 M-->>T: 记忆上下文边界
memory-context fence T->>L: 写入 user api_content sidecar L-->>U: 先交付最终回答 L->>M: 同步与排队预取
sync_all + queue_prefetch_all M->>P: 单线程 FIFO 后台同步

源码细节比“后台召回”四个字更精确:外部 prefetch 在独立线程执行,但 Turn 会在一个很短的超时边界内等待;超时或 Provider 异常就 fail-open,本轮不注入。召回内容被包进 <memory-context> fence,并和 Plugin context 一起写入当前 user message 的 api_content sidecar;数据库里仍保留干净的用户原话,同时以后重放能复现当时真正发给 Provider 的字节。

Turn 结束后的写入走另一条路:sync_all() 与 next-turn prefetch 进入单 worker 队列,保证 Turn N 先于 Turn N+1 落到外部后端,也避免一个慢网络调用让界面一直显示“运行中”。内置 memory 写入只有在真正提交成功、没有处于 staged 状态时,才通过 notify_memory_tool_write() 镜像给外部 Provider。

后台 Review:Hermes 的“自我学习”发生在哪里

项目首页强调 closed learning loop,源码对应的是 agent/background_review.py 和 Turn Finalizer 中的 nudge 计数。达到记忆或 Skill 的 review cadence 后,主回答先交付给用户,随后才启动一个后台 AIAgent fork,回看本轮是否出现值得保存的偏好、稳定事实、可复用步骤或对既有 Skill 的纠正。

flowchart LR
    Turn[主 Turn 完成] --> Nudge{达到 Review cadence?}
    Nudge -->|否| End[结束]
    Nudge -->|是| Fork[后台 Review Agent]
    Fork --> Whitelist[只允许 memory / skill 工具]
    Whitelist --> Decide{值得长期保存?}
    Decide -->|事实与偏好| Mem[写 MEMORY / USER]
    Decide -->|可复用流程| Skill[创建或修补 Agent-owned Skill]
    Mem --> Approval[可选写入审批]
    Skill --> Approval
    Approval --> Future[未来会话与任务复用]

这个 fork 不重新连接外部 Memory Provider,避免一次 Review 自己又被召回、同步和二次学习;它共享父 Agent 的内置 MemoryStore,工具白名单限制为 memory/skills,自己的 nudge 计数也被关闭。操作者可以给 Memory 与 Skill 分别开启 write approval,也可以把 Review 路由到更便宜的 auxiliary model。之后的 Curator 主要维护 Agent-created Skills,并可按配置归档长期未使用的 bundled Skill;Hub Skill 始终不碰,自动流程从不硬删除,显式 purge 也会先留下 ledger 与可恢复 blob。

四种“记住”应该怎么选

机制适合内容何时进入模型上下文主要代价
MEMORY / USER少量关键事实与偏好会话快照常驻每轮固定 token;容量严格
External Provider语义检索、用户建模、知识图谱按轮召回或显式工具调用网络延迟、外部数据治理
session_search过去对话的原始证据模型主动搜索时需要形成检索查询
Skill“如何完成一类任务”的程序性知识索引匹配后按需加载需要维护与验证流程

从“记住事实”到“学会方法”

单独看文件记忆、向量召回或反思学习都不算新概念。Hermes 更有意思的地方,是把它们放进同一条可观察、可审批的生命周期:事实和偏好进入 Memory,可复用的方法进入 Skill,后台 Review 负责提炼,Curator 再整理 Agent 创建的 Skill。

flowchart TD
    Turn[正常对话完成] --> Review[后台复盘
Background Review] Review --> Decide{学到了什么?} Decide -->|事实与偏好| Memory[记忆与用户文件
MEMORY.md / USER.md] Decide -->|可复用方法| Skill[智能体创建的技能
Agent-created Skill] Skill --> Curator[Curator 整理与归档] Memory --> Recall[后续 Turn 召回] Curator --> Recall Recall --> Turn

这条闭环仍然有边界:后台 Review 在主回答交付之后运行,使用受限工具集;Memory 和 Skill 写入可以要求审批;外部 Memory Provider 的召回以本轮 sidecar 进入请求,不会把数据库中的用户原话改写成召回文本。

Background Review 和 Curator 不是同一个后台任务

组件运行时机主要输入主要输出
Background Review主回答交付后的后台学习刚完成的 Turn、现有 Memory 与 Skill新增或修改 Memory;创建、改进 Skill
Curator按周期审查 Skill LibraryAgent-created Skill、使用记录与配置允许的候选保留、整理或软归档低价值 Skill

Review 关心的是“这一轮学到了什么”,Curator 关心的是“长期积累的 Skill 还值不值得继续占据发现面”。当前实现不会在后台静默硬删除 Skill;归档保留恢复路径,真正清理需要显式 purge。配置也可以允许 Curator 归档长期未使用的 Bundled Skill,但它的主要治理对象仍是 Agent 创建的内容。

参考资料与源码入口

题图来源:《湖、森林与公园》,创作者 IlonaBurschl,来自 Pixabay;依据 Pixabay Content License(Pixabay 内容许可)使用。

下一篇:Hermes Agent 的长会话架构:Prompt Cache、压缩与 SessionDB

ZFS Mirror vs mdadm RAID1:Linux 双盘镜像搭建、故障演练与性能实测 Hermes Agent 的长会话架构:Prompt Cache、压缩与 SessionDB Prometheus + Grafana 构建监控平台
View Comments
There are currently no comments.