Hermes 的 Skill 怎么「自我进化」:从 skill_manage 到渐进式加载
古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。更完整的更新写在微信公众号「字与码」:工作经历、对新技术的想法,以及这些年走弯路的记录,会不定期发在那里。若觉得博客对你有用,欢迎顺手关注。
Hermes 文档里把 skills 叫作 procedural memory。落到实处,就是 ~/.hermes/skills/ 下面的 SKILL.md,以及用来改这些文件的 skill_manage 工具。另外还有一层「渐进披露」:不是每个会话都把整本技能手册塞进模型上下文。
这篇先把技能和内置记忆区分开,再说明分层加载在干什么。然后写 skill_manage 什么时候会动磁盘、一般会改 SKILL 里的哪几块。最后有几段小故事。它们是我按官方文档里写的触发条件编出来的,不是某次真实会话的日志,用来帮助想象「进化」长什么样。你若自己跑 Hermes,可以在 ~/.hermes/skills/ 里对照有没有类似的改动痕迹。
技能和 MEMORY 不是一类东西
Hermes 有两块东西经常被混在一起说,其实用途不同。
内置记忆是 MEMORY.md 和 USER.md,放在 ~/.hermes/memories/。内容有严格的长度限制。每次会话开始的时候,这些内容会作为固定的一块写进系统提示,会话中间一般不再改这一块(改了磁盘也要等下次会话才反映到系统提示里)。适合放偏好、环境信息、短小的备忘。细节见持久记忆。
技能在 ~/.hermes/skills/,核心是 SKILL.md,结构和 agentskills.io 那套开放格式兼容。这里存的是可照着做的步骤:什么时候用、怎么做、坑在哪、怎么验收。所谓「进化」,主要是指这些内容被改写了,而不是把一整段聊天记录缩进 MEMORY。
所以一个是「记点事实和口味」,一个是「留一份可重复的操作说明」。混着说容易以为 agent 只是在「越聊越懂你」,其实磁盘上可能是完全不同的两类写入。
渐进披露在解决什么问题
技能多了以后,如果每个会话都把每个 SKILL.md 全文塞进上下文,token 很快会爆。文档里把加载拆成几级。第一级只拉一个列表,大致是名称、描述之类,体量相对可控。第二级才按名字拉某个 skill 的全文。第三级可以再按路径拉附属文件。
官方文档里对应的是 skills_list()、skill_view(name)、skill_view(name, path) 这一套。先看见目录,真要用再展开。技能系统要能用,离不开这一层设计。后面说的「自我进化」如果每次都把全文反复灌进上下文,产品上也撑不住,所以这两件事是搭在一起的。
skill_manage 动的是哪块盘
技能系统文档里有一节 Agent-Managed Skills。代理通过 skill_manage 这个工具来创建、打补丁、整段替换或删除技能,也可以给某个 skill 增加或删掉附属文件。
文档里写了几种典型情况,大意是下面这样,不必和某一次你自己的任务一一对应。
有时候任务本身步骤就多,工具来回调了很多次,最后跑通了。这种事后很适合把套路沉淀成 skill。
也有走弯路的:先试了一种做法失败了,再换路径才成功。文档里把这种也算在会动技能的场景里。成功之后把「能走通的那条路」写进 SKILL,下次少踩坑。
用户中途纠正也算。比如你明确说「别用这条命令,用那条」。这类纠正如果对应的是可重复流程,更适合写进 Procedure 或 Pitfalls,而不是只在 MEMORY 里记一句「用户不喜欢某某」。
还有一种,是 agent 发现某条工作流会反复出现,值得单独成篇。文档里用「非平凡」之类的说法,你可以理解成:不是回一句话就结束的那种事。
更新已有内容时,文档建议优先用 patch,只改一段,而不是整份 edit 重写。对模型来说 patch 更省 token,对人类来说 diff 也更好看。
落到工程上,就是模型发起了 skill_manage 调用,你在磁盘上看到 ~/.hermes/skills/ 下面文件变了。想验证的话,可以看工具调用记录,或者给目录做个版本管理,比猜「它有没有悟到」直接得多。
SKILL.md 里常见会动到的部分
创建技能的写法里,一般会分「什么时候用」「步骤」「坑」「怎么确认做对了」几块。进化的时候,动的多半是这些块里的文字。
Procedure 里可能多一步,或者把某条命令换成更贴合你环境的写法。Pitfalls 里可能加一条「在什么条件下会失败」。Verification 可能跟着改,因为验收方式变了。
这和 USER 里那种「回复写短一点」不是同一类信息。前者改的是怎么做,后者改的是怎么跟你说话。
几段小故事:进化可能长什么样
下面这些是我编出来的示意,用来对应文档里说的触发条件。不是真实 log。你若在本地看到类似的文件变化,说明 skill_manage 这类路径在工作。
第一个故事:改一条命令。
某次用自带的部署类 skill,Procedure 里写的是 docker-compose up。你这台机器只装了 Compose V2,实际该用 docker compose。任务折腾几轮之后跑通了。跑通之后 agent 用 patch 把 Procedure 里那一行换掉。下次再加载这个 skill,不会重复踩旧命令。这是文档里「纠正之后写回步骤」那一类。
第二个故事:在 Pitfalls 里补环境。
某次执行 npm ci,在国内网络一直超时。后来你改成指定 registry,或者走了代理,才装成功。这类信息如果写进 Pitfalls,后来的人一眼能看到「超时先查网络」,而不必把整段调试对话塞进 MEMORY。这和「记一句用户家网络不好」不一样,前者是可执行提示。
第三个故事:从零写一个 skill。
假设你让 agent 帮你完成「打 tag、推远端、写 release 说明」一整套,中间 terminal 和 git 来回用了好多次。文档里说的「复杂任务」在这种场景里就对上了。结束后可能会 create 一个新的目录,里面有一份 SKILL.md,以后可以用斜杠命令或自然语言再调起来。
第四个故事:你开口改默认值。
你说我们团队默认分支是 develop,别按 main 合并。agent 对已有 skill 做 patch,把文档里写死的分支名改掉。这比只在 USER 里写「用户喜欢 develop」有用,因为下次执行的是对的 git 命令,而不只是「记得用户偏好」。
session_search、外部记忆、Hub 安装,和本地改 SKILL 的关系
如果你要问「三周前那次聊天里具体说了哪句」,那是另一条机制。Hermes 有 session_search,在 SQLite 里搜历史会话,还可以配合摘要。这和「把步骤写进 SKILL」是两种用途。前者是翻旧账找话,后者是留下可复用的做法。
文档里还提到可选的外部记忆 Provider,例如 Honcho、Mem0 等。那是更深一层的建模或检索能力,不替代内置的 MEMORY 和 USER 小块。和 skill 文件也不是同一个目录下的同一类东西。
从 Hub、GitHub、skills.sh 等 hermes skills install 装下来的,是别人打包好的技能,走安全扫描和版本管理那一套。agent 在运行过程中自己写进 ~/.hermes/skills/ 的,是本地沉淀出来的那份。两条路径可以并存:你可能既装了社区 skill,又在自己目录里长出了几份私货。
把这几件事分开想,就不容易把「装了一个市场技能」和「跑任务跑出一篇自己的 SKILL」混成一件事。