Hermes Agent:记忆模块 & Skill 自动收集原理(完整版)

不用向量数据库,纯文本文件 + FTS5 全文检索。冻结注入保 Prefix Cache,fork 子 Agent 做后台 Skill Review。每个设计决策背后都是明确的工程取舍。


一、为什么不使用向量检索?

1.1 主流方案的痛点

大多数 AI Agent 的记忆系统会用向量数据库(如 Pinecone、Chroma、Milvus)做语义检索:

用户输入 → 文本向量化 → 向量数据库 → 相似度 TopK 检索 → 召回相关记忆 → 注入 context

这套方案的问题:

  • 系统复杂度:需要维护向量数据库,增加部署成本
  • 调试困难:为什么召回这一条而不是那一条?黑盒不好解释
  • 过度设计:个人使用的 Agent,记忆条目通常只有几十到几百条

1.2 Hermes 的选择

Hermes 使用纯文本文件 + FTS5 全文检索:

  • 简单透明:用户可以直接打开 MEMORY.md 编辑
  • 足够好用:个人规模下,关键词检索配合合理上限,体验不差
  • 无外部依赖:不需要向量数据库,开箱即用

二、记忆模块详解

2.1 两层架构

记忆调度中心 MemoryManager
├── 内置记忆 BuiltinMemoryProvider
│   ├── MEMORY.md — Agent 笔记,上限 2200 字符
│   └── USER.md  — 用户画像,上限 1375 字符
└── 外部插件 MemoryProvider(最多挂载一个)
    └── Honcho / Mem0 / Holographic / ...

为什么只能挂载一个外部 provider? 避免工具命名冲突、简化调度逻辑、减少 token 开销。

2.2 字符上限的设计逻辑

文件上限用途设计理由
MEMORY.md2200 字符Agent 的环境/项目笔记防止注意力稀释,强迫精炼
USER.md1375 字符用户画像、偏好精简的用户快照,快速加载

注意力稀释问题

正常情况下,2000 tokens 的记忆内容中,每条约占 0.26% 的注意力权重。膨胀到 5000 tokens 后,每条只剩 0.02%。上限就是一道硬约束,迫使 Agent 只保留最有价值的信息。

2.3 冻结注入 & Prefix Cache

这是 Hermes 记忆系统最核心的设计决策。

什么是 Prefix Cache?

LLM API(如 Claude、GPT)内部使用 KV Cache 加速:

第一次调用:
  Input: [system prompt] + [user message]
  → 遍历所有 token 计算 KV 矩阵(耗时)
  → 保存 KV Cache

后续调用(system prompt 不变):
  Input: [system prompt] + [新的 user message]
  → 直接命中 KV Cache ⚡
  → 省 80%+ 计算时间

关键:只要 system prompt 变化,整个 KV Cache 就失效,必须重新计算。

Hermes 的策略

  1. Session 开始:读取 MEMORY.md 完整内容,制作”快照”,存入 system prompt,首次 API 调用建立 KV Cache
  2. 对话进行中:system prompt 不变,每次 API 调用命中 KV Cache
  3. mid-session 写入:调用 memory 工具写入新内容,文件已更新,但 system prompt 里的快照不变
  4. 下个 Session:重新读取(包含上次写入的内容),制作新快照,重建 KV Cache

取舍

  • 好处:保住了 prefix cache,大幅降低 API 延迟和成本
  • 代价:mid-session 写入的记忆,本轮对话感知不到

2.4 mid-session 写入的两种场景

场景本轮能感知吗?原因
用户明确说出”记住我喜欢用 pnpm”这句话在 messages 历史里,LLM 能看到
Agent 自己推断并写入 MEMORY.md不能system prompt 快照没更新

示例

本轮 Session:
  用户: "帮我配置项目"
  Agent: (推断出用户喜欢 pnpm,写入文件)
  文件已更新 ✓
  但 system prompt 快照未变

  用户: "用什么包管理器?"
  Agent: "根据你的项目,推荐 npm"  ← ❌ 没记住!

下个 Session:
  Agent 重新读取(包含 pnpm 偏好),新快照注入 system prompt

  用户: "用什么包管理器?"
  Agent: "你喜欢用 pnpm"  ← ✅ 记住了!

这是一个明确的工程取舍:性能优先,延迟生效。


三、Skill 自动收集:闭环学习系统

3.1 设计目标

让 Agent 能从每次任务中自动提炼可复用的知识,形成正向循环:

完成任务 → 后台 Review → 提取 Skill → 下次复用 → 更高效完成任务 → ...

3.2 为什么 fork 子 Agent?

不直接让主 Agent 存 skill,有三个原因:

主 Agent 直接处理fork 子 Agent
响应速度❌ 慢,用户要等✅ 快,后台静默
上下文污染❌ review 思考污染主对话✅ 独立不污染
判断客观性❌ 带任务惯性✅ 冷启动旁观者

3.3 nudge 触发完整时序

  1. 复杂任务执行:每次工具调用计数器 +1
  2. 计数器达阈值(默认 10 次工具调用后),标记 _should_review = True,计数器归零
  3. 返回最终回答给用户(用户已看到结果)
  4. 后台 fork 子 Agent:传入对话快照,子 Agent 冷启动执行 Review Prompt
  5. Review 判断
    • 值得泛化 → skill_manage(action='create') → 通知用户 Skill created
    • 已有 skill 需更新 → skill_manage(action='patch') → 通知用户 Skill updated
    • 不值得 → 静默跳过

3.4 Review 的判断标准

子 Agent 会审视对话,问自己:

  1. 有试错过程吗? 不是一帆风顺,而是踩了坑、调整了方案
  2. 有思路转变吗? 实际做法和用户最初预期不一样
  3. 用户有特别偏好吗? 比如在多种方案中选了某一种
  4. 下次还用得上吗? 这个场景会重复出现

触发创建/更新的条件

  • 任一问的回答是”是”,且没有现成 skill 覆盖 → 创建新 skill
  • 有类似 skill,但内容需要补充 → patch 更新

3.5 Skill 文件结构

~/.hermes/skills/
├── my-skill/
│   ├── SKILL.md          ← 核心文件
│   ├── references/       ← 参考资料
│   ├── templates/        ← 模板文件
│   ├── scripts/          ← 辅助脚本
│   └── assets/           ← 图片等资源
└── category-name/
    └── another-skill/
        └── SKILL.md

SKILL.md 格式

---
name: k8s-persistent-storage
description: Configure persistent volumes in Kubernetes
platforms: [linux, macos]
metadata:
  hermes:
    requires_toolsets: [terminal, web]
    config:
      - key: k8s.namespace
        description: Default namespace
        default: "default"
---
 
# 触发条件
When setting up persistent storage in Kubernetes...
 
# 步骤
1. Check existing storage classes: `kubectl get sc`
2. ...
 
# 常见问题
- PVC stuck in Pending → check storage class

3.6 Skill 的安全机制

skill_manage 工具有多层防护:

  1. 命名校验:小写字母、数字、连字符、下划线,最长 64 字符
  2. 大小限制:SKILL.md 最大 100KB,附件最大 1MB
  3. 安全扫描:检查注入攻击、数据外泄等恶意模式
  4. 回滚机制:扫描失败时自动撤销更改
  5. 只读保护:外部目录(external_dirs)的 skill 不能被修改

四、记忆 vs Skill:本质区别

维度记忆(MEMORY.md)Skill(SKILL.md)
存储内容事实性信息过程性知识
回答的问题”世界是什么样的?""下次怎么干?“
典型内容用户偏好、环境配置、项目状态操作步骤、避坑指南、最佳实践
触发写入手动 memory 工具 / nudge手动 skill_manage / nudge
生效时机下个 session下个 session(重建索引后)
更新方式追加、替换、删除条目create / edit / patch 操作
组织形式两段式(Agent 笔记 + 用户画像)分类目录 + 独立 skill 包

区别

  • 记忆 = 是什么(事实)
  • Skill = 怎么做(过程)

五、关键设计决策总结

决策取舍原因
冻结注入性能优先,延迟生效保住 prefix cache,省成本
字符上限精炼优先,放弃完整防注意力稀释,强迫高质量记录
fork 子 Agent体验优先,增加复杂度后台 review 不卡用户
纯文本 vs 向量简单优先,放弃语义检索个人规模够用,可维护性好
单外部 provider简化优先,放弃灵活避免冲突,降低调度复杂度

每个设计决策都不是”最优解”,而是在特定约束下的合理取舍。理解这些取舍,比记住实现细节更重要。