给 Hermes Agent 装上「外挂系统」:记忆系统与 Skill 系统的深度改造
一套完整的 AI Agent 记忆管理 + Skill 自进化 + 自动化维护的实践记录。不改 Hermes 核心代码,通过外挂插件让 Agent 越用越聪明。
给 Hermes Agent 装上「外挂系统」:记忆系统与 Skill 系统的深度改造
一套完整的 AI Agent 记忆管理 + Skill 自进化 + 自动化维护的实践记录。不改 Hermes 核心代码,通过外挂插件让 Agent 越用越聪明。
TL;DR
| 维度 | 改造前 | 改造后 |
|---|---|---|
| 跨会话记忆 | 每次新会话从零开始 | 5 层记忆 + 自动维护 |
| 知识积累 | 经验随会话消亡 | 反思 → solutions/ → 自动晋升 |
| Skill 管理 | 60 个 skill 平铺,无质量控制 | Hub 分层 + 质量门 + 防膨胀 |
| Token 消耗 | 大 skill 全量注入 | 按需加载,87→56 enabled |
| 自动化 | 手动维护 | 会话级/日/周 cron 全覆盖 |
Part 1: 记忆系统
1.1 问题:Agent 的「金鱼记忆」
Hermes Agent 原生有三层记忆:MEMORY.md(系统提示词注入)、memory tool(memories/MEMORY.md)、session_search(SQLite 对话历史)。看起来够用,实际跑起来有三个致命问题:
| 问题 | 表现 |
|---|---|
| 跨会话失忆 | 新会话启动,Agent 不记得昨天调过的 bug、做过的决策 |
| 知识不积累 | 踩过的坑下次还会踩,解决方案随会话结束消失 |
| 维护靠人工 | MEMORY.md 满了要手动清理,过时信息不会自动淘汰 |
1.2 我们的改造:5 层记忆体系
┌─────────────────────────────────────────────────────────────┐
│ Layer 1: 系统提示词 MEMORY/USER │
│ 永远加载,2200 字符上限,存最关键的事实 │
│ 文件:~/.hermes/MEMORY.md + ~/.hermes/memories/MEMORY.md │
├─────────────────────────────────────────────────────────────┤
│ Layer 2: fact_store(全息结构化记忆) │
│ 向量嵌入 + 实体关系 + 信任评分 │
│ 支持语义搜索、实体探查、组合推理 │
├─────────────────────────────────────────────────────────────┤
│ Layer 3: session_search(FTS5 对话历史) │
│ 全文搜索过去的对话,支持 discovery/scroll/read/browse 四种模式│
├─────────────────────────────────────────────────────────────┤
│ Layer 4: compound-system(反思 + 知识库) │
│ 任务后自动反思,写入 solutions/,带 track/level 三级管理 │
├─────────────────────────────────────────────────────────────┤
│ Layer 5: Skill 系统(可复用技能) │
│ 从成功模式自动提炼,按需加载,防膨胀 │
└─────────────────────────────────────────────────────────────┘
1.3 compound-system:让 Agent 学会反思
这是整个记忆系统的核心。每次完成一个非平凡任务,Agent 会自动执行反思流程:
任务完成
↓
compound.sh reflect → 判断是否需要反思
↓ 需要反思
reflect.sh → 调用 LLM 分析,输出结构化 JSON
↓
write-solution.sh → 写入 solutions/ 目录
↓
下次遇到类似问题 → compound.sh search → 命中历史方案
关键设计决策:
| 决策 | 选择 | 原因 |
|---|---|---|
| 反思触发 | 自动判断 | 不是每个任务都值得反思,避免噪声 |
| 存储格式 | Markdown 文件 | 人可读、git 友好、搜索方便 |
| 知识分级 | working → session → longterm | 三级晋升,避免信息爆炸 |
| 衰减机制 | 30 天自动归档 | 不用的知识自动降温 |
| 搜索方式 | FTS5 全文搜索 | 本地运行,无外部依赖 |
实际效果:
$ bash compound.sh search "ruff format"
[INFO] Found 3 solution(s) for: ruff format
[1] "ruff format 欠账导致 CI 失败"
File: solutions/bug/ticketpilot-ruff-format-debt-2026-06-21.md
Track: bug, Level: session
[2] "子代理拆分模块后必须检查 ruff"
File: solutions/session/ruff-subagent-lesson.md
Track: session, Level: session
1.4 reflect.sh:LLM 驱动的结构化反思
最初 reflect.sh 只返回裸 JSON,LLM 经常只回显输入而不做分析。经过多轮迭代:
| 迭代 | 问题 | 修复 |
|---|---|---|
| v1 | "Return JSON only" prompt 太简单 | 改用结构化 prompt,明确要求 root_cause/solution/lessons/patterns |
| v2 | curl bash 引号嵌套爆炸 | 改用 Python urllib |
| v3 | log_info 污染 stdout | 重定向到 stderr |
| v4 | write-solution.sh 丢字段 | 扩展模板支持 lessons/patterns |
| v5 | compound.sh reflect vs reflect.sh 混淆 | 文档明确区分:前者判断是否反思,后者实际调 LLM |
最终 pipeline:
# 一键反思+存档
bash ~/.hermes/skills/compound-system/scripts/reflect.sh \
"修复了 QQ Bot 心跳回环" "success" "low" "" \
| bash ~/.hermes/skills/compound-system/scripts/write-solution.sh1.5 记忆维护自动化
手动维护不可持续。我们建了一套自动化维护链:
| 触发时机 | 脚本 | 动作 |
|---|---|---|
| 会话结束 | session-end.sh | 压缩 MEMORY.md + 归档旧方案 + 反思 |
| 每天凌晨 2 点 | daily-maintenance.sh | 衰减检查 + 去重检查 + 同步检查 |
| 每周日凌晨 3 点 | weekly-maintenance.sh | 淘汰检查 + 合并检查 + 大小检查 |
衰减机制原理:
# memory-decay.py 核心逻辑
# 信任评分按指数衰减,30 天半衰期
new_trust = old_trust * (0.5 ** (days_elapsed / 30))
# 低于阈值 → 自动归档到 .archive/去重机制:
# memory-dedup.py 核心逻辑
# FTS5 全文搜索 + SequenceMatcher 相似度
# 相似度 > 0.85 → 合并,保留更新的版本1.6 MEMORY.md 的三层文件陷阱
这是调试中最坑的一个发现——系统里有三个不同的 MEMORY.md:
| 文件 | 用途 | 格式 | 字符上限 |
|---|---|---|---|
~/.hermes/MEMORY.md | 注入系统提示词 | 结构化 markdown | 无硬限制 |
~/.hermes/memories/MEMORY.md | memory tool 操作 | § 分隔符格式 | 2,200 |
~/.hermes/memory/MEMORY.md | 遗留,已废弃 | — | — |
memory tool 的 add/replace/remove 操作的是 memories/MEMORY.md,不是注入到系统提示词的那个。当 tool 报告 "at X/2200 chars" 时,需要手动编辑 memories/MEMORY.md 来清理。
1.7 实战数据
| 指标 | 改造前 | 改造后 |
|---|---|---|
| 跨会话知识保留 | 0% | ~90%(compound-system) |
| 重复踩坑率 | 高 | 低(search 命中历史方案) |
| MEMORY.md 维护 | 手动 | 自动(cron + 衰减) |
| 新会话冷启动时间 | 5-10 分钟 | 1-2 分钟 |
Part 2: Skill 系统
2.1 问题:Skill 膨胀
Hermes Agent 的 Skill 机制本质上是把 SKILL.md 内容注入到 system prompt。一个 300 行的 skill 每次对话都全量注入,不管你用不用。
| 问题 | 影响 |
|---|---|
| Skill 数量多 | 60+ 个 skill,每个都有描述和指令 |
| Lark 系列占大头 | 24 个 Lark skill,QQ 聊天永远用不到 |
| 无质量控制 | 有些 skill 超 500 行,塞了所有细节 |
| 无淘汰机制 | 过时 skill 一直占 token |
2.2 改造 1:Hub + 专注 Skill 分层
核心原则:一个大 skill 不如多个小 skill。
| 维度 | 一个大 skill | 多个小 skill |
|---|---|---|
| Token 消耗 | 高(每次加载全部) | 低(按需加载) |
| 注意力 | "中间丢失"效应 | 每个都精简 |
| 维护 | 改一处影响全局 | 独立更新 |
| 复用 | 难以复用 | 可组合 |
改造后的架构:
Hub Skill(索引层,<100 行)
context-engineering-hub
快速参考 + 按需加载子 skill
↓ 按需加载
专注 Skill(功能层,每个 <200 行)
project-context 文件结构、模板
skill-evolver 从成功模式生成 skill
context-validation 验证改进效果
self-evolution-system 完整闭环架构
↓
工具 Skill(支撑层)
memory-orchestrator 统一记忆编排
resilient-web-search 搜索 API fallback
实际案例:context-engineering 的拆分
| 拆分前 | 拆分后 |
|---|---|
| 1 个 skill,683 行 | 4 个 skill:hub(95行) + project-context(148行) + token-compression(120行) + session-handoff(89行) |
| 每次全量加载 | 按需加载对应子 skill |
| 信息过载 | 每个精简聚焦 |
2.3 改造 2:质量门
每个 skill 创建/更新时必须过质量门:
| 检查项 | 阈值 | 不通过时动作 |
|---|---|---|
| 行数 | ≤200 行 | 压缩或拆分 |
| 三段式陷阱 | 至少 1 个 | 补充 |
| 边界三段式 | 必须有 | 补充 |
| 代码示例 | 至少 1 个 | 补充 |
| 指针引用 | 不嵌入详细文档 | 改为指针 |
三段式陷阱示例:
- **psycopg_pool 事务回滚**:`with` 块退出时自动回滚 → 写操作用 `autocommit=True`
- **ruff format 欠账**:CI 会跑 `ruff format --check` → 提交前先 `ruff format .`2.4 改造 3:防膨胀机制
| 机制 | 规则 | 动作 |
|---|---|---|
| 衰减 | 30 天未使用 | 归档到 .archive/ |
| 合并 | 2+ 相似 skill | 合并成一个 |
| 上限 | 超过 200 行 | 压缩 |
| 淘汰 | 6 个月未引用 | 删除 |
2.5 改造 4:Smart Skill 注入
Hermes 原生每次对话加载所有 enabled skill 的描述。我们的优化:
# config.yaml
skills:
disabled:
# Lark 系列(25 个)— QQ 聊天用不到
- lark-approval
- lark-apps
- lark-attendance
# ... 共 25 个
# 其他不需要的
- yuanbao
- honcho
- hermes-memory-setup
# ... 共 6 个| 指标 | 优化前 | 优化后 |
|---|---|---|
| Enabled skills | 87 | 56(-31) |
| System prompt 注入 | ~4600 行 skill 描述 | ~2800 行 |
| 预估 token/请求 | — | -2000~3000 |
2.6 resilient-web-search:搜索容错
Tavily API 经常 432(配额耗尽)。我们建了一条 fallback 链:
web_search(Tavily)
↓ 失败
web_search_plus(auto 路由)
↓ 失败
web_search_plus(指定 provider 轮询)
↓ 失败
返回错误 + 已尝试列表
这个 skill 被所有搜索相关的 cron job 引用,确保即使一个 API 挂了也不会空手回来。
2.7 Skill 优化实战数据
| 指标 | 优化前 | 优化后 |
|---|---|---|
| Skill 总数 | 60(4629 行) | 56(约 2200 行有效注入) |
| 最大单 skill | 648 行(lark-mail) | ≤200 行 |
| 按需加载 | 无 | hub + focused |
| 防膨胀 | 无 | 衰减 + 合并 + 淘汰 |
Part 3: 自动化系统
3.1 Cron Job 时间表(UTC+8)
| Job | Schedule | 说明 |
|---|---|---|
| GitHub 热门日报 | 每天 09:00 | 搜索 trending,中文整理 |
| compound-system-refresh | 每天 03:00 | 刷新 solutions 索引 |
| 统一 Memory 维护 | 每天 04:00 | MEMORY.md + fact_store 检查 |
| AgentMemory 维护 | 每天 19:00 | MCP server 健康检查 |
| Hermes 配置备份 | 每天 06:00 | config.yaml 备份 |
| skill-index-rebuild | 周日 09:00 | 重建 skill 索引 |
3.2 会话级自动化
会话启动
↓
fact_store(action='search') → 查已有知识
↓
开始任务
↓
任务完成
↓
compound.sh reflect → 反思
↓
session-end.sh → 压缩 + 归档 + 更新统计
3.3 解耦原则
所有改造都不修改 Hermes 核心代码。 这是最重要的设计决策:
| 组件 | 位置 | 与 Hermes 的关系 |
|---|---|---|
| compound-system | ~/.hermes/skills/compound-system/ | 独立 skill,不改 core |
| memory-orchestrator | ~/.hermes/skills/memory-orchestrator/ | 独立 skill |
| context-engineering-hub | ~/.hermes/skills/context-engineering-hub/ | 独立 skill |
| resilient-web-search | ~/.hermes/skills/resilient-web-search/ | 独立 skill |
| 维护脚本 | ~/.hermes/scripts/ | 独立脚本 |
| Cron jobs | Hermes cron 系统 | 用原生调度能力 |
为什么解耦?
- Hermes 更新时不会冲突
- 可以独立测试和迭代
- 可以分享给其他用户
- 维护成本低——不需要跟踪上游变更
Part 4: 设计哲学
4.1 从研究到实践
我们的所有决策都有研究支撑:
| 研究 | 发现 | 我们的应用 |
|---|---|---|
| ETH Zurich "Evaluating AGENTS.md" | 自动生成降低成功率 3% | 人工编写 skill,不自动生成 |
| GitHub 2500+ 仓库分析 | 边界三段式最有效 | skill 必须有 always/ask/never |
| "Lost in the Middle" | 长上下文中间信息被忽略 | 小 skill,按需加载 |
| Longbench | 中度压缩提升输出质量 | 结构化格式替代段落 |
| Mem0 2026 Agent Memory | 多层记忆架构最佳 | 5 层记忆体系 |
4.2 核心洞察
- 减少 token ≠ 减少理解:结构化压缩可以同时实现两者
- 渐进披露 > 全量加载:只在需要时加载详细内容
- 闭环验证是关键:每次改进都要验证效果,不盲目优化
- 自动化是必须的:手动维护不可持续
- 解耦是原则:不依赖特定工具的内部实现
4.3 仍在迭代的方向
| 方向 | 状态 | 优先级 |
|---|---|---|
| SkillOpt 集成(自动训练 skill) | POC 完成,0.825→0.85 目标 | 高 |
| ONNX 语义嵌入(fact_store 向量搜索) | 计划中 | 中 |
| 跨项目 skill 复用 | 概念验证 | 中 |
| LLM 驱动的 reflect.sh 接入 | 已实现 | ✅ |
总结
给 Hermes Agent 加外挂系统的核心思路:不改核心,用插件机制扩展能力。
- 记忆系统让 Agent 不再失忆——踩过的坑会记住,做过的决策会保留
- Skill 系统让知识有组织——按需加载、质量控制、自动淘汰
- 自动化让系统自运转——会话级/日/周三层维护,无需人工干预
所有代码都在 ~/.hermes/skills/ 下,纯外挂,不碰 Hermes 核心。
写于 2026-06-21,基于 Hermes Agent + compound-system + memory-orchestrator 的实践