点击上方 前端Q,关注公众号
回复加群,加入前端Q技术交流群
我研究 Hermes Agent 的时候,最让我"哦~原来是这样"的不是 Memory,而是 Skill 系统。
Memory 解决的是"我记得这件事是这样"。
Skill 解决的是"我知道这件事该怎么做"。
听起来差不多,工程上完全是两个东西。前者偏知识查询,后者偏过程复用。Hermes Agent 之所以能"越用越快",靠的不是 Memory 越来越多,而是 Skill 越攒越准。
这一篇就专门讲 Skill 系统。
先把概念分清楚
聊 Skill 之前,先把它和 Memory 拉开距离。我看过太多人混着用,最后越聊越糊。
Memory 是陈述性记忆:你知道什么。
它回答的是事实型问题:
▸用户喜欢用 TypeScript
▸数据库是 PostgreSQL
▸项目用 monorepo 结构
Memory 写出来更像便签,是离散的事实。
Skill 是过程性记忆:你怎么做。
它回答的是流程型问题:
▸怎么发布到 npm
▸怎么排查内存泄漏
▸怎么写 changelog
Skill 写出来更像菜谱,是带顺序的步骤。
我自己学认知心理学时,老师讲过一句话挺贴切:"会做事比知道事更值钱。"
人能写出一份菜谱,跟人真的会炒菜,是两回事。Skill 做的就是后者。
为什么不能只用 Memory
可能你会想:那我把"发布 npm 包的 5 个步骤"也塞进 Memory,不就行了?
短期看是行的,但跑长了一定爆。我自己实验过,主要踩三个坑。
坑 1:Memory 是给"理解"用的,不是给"执行"用的
Memory 的查询路径默认是:先把所有相关 Memory 注入 Prompt,让模型"看完再说话"。
但执行型任务不是说话,是动手。Agent 真正需要的是"打开手册第 3 步、做完打勾、出错回到第 2 步"。
把流程塞 Memory 里,模型很容易跳步、合并步、漏一步。我的经验是,任何超过 3 步的事情都会出问题。
坑 2:Memory 没办法版本化
发布流程会变。今天用 npm,明天换 pnpm,后天加上 changesets。
Memory 是离散事实的合集,没人知道"上次的发布步骤"和"今天的发布步骤"有什么差。一改要么全删要么全留,没有中间态。
Skill 是文件,天然可以打版本号、做 patch、回滚到上一版。
坑 3:Memory 之间没有依赖关系
复杂任务往往是多个流程互相调用。"发布 npm 包"里要先"跑测试"、"写 changelog"、"打 tag"。
Memory 是平的,没办法表达"做 A 之前先做 B"。
Skill 不一样,它本身就是带步骤的文档,自然可以引用其他 Skill。Hermes 里很多 Skill 顶部都有depends_on: [run-tests, write-changelog]这种声明。
这三个坑加起来就是一句话:陈述性知识和过程性知识,必须分开存。
一个 SKILL.md 长什么样
讲清楚边界,再来看 Skill 的物理形态。
Hermes 里 Skill 就是一个普通的 markdown 文件,存在.hermes/skills/目录下。一个项目一个 Skill 库,结构清爽:
.hermes/skills/
publish-to-npm.md
debug-memory-leak.md
write-changelog.md
rollback-deploy.md
每个文件里大致 5 个区块。
我把每一块的设计意图说一下,因为这个结构不是随便定的,每条都有讲究。
第 1 块:元信息
name: 发布 npm 包
trigger: 用户说 "发布" 或 "上线"
version: 1.2
trigger是关键字段。Hermes 在用户提需求时,会先扫所有 Skill 的 trigger,看哪个匹配。
为什么不用纯语义匹配?因为太贵也太慢。先用 trigger 关键字粗筛 → 再用语义补一刀,这是工程上的折中。
第 2 块:适用场景
写明哪些场景能用、哪些场景不能用。
很多人省略这块,结果踩坑:一个"monorepo 发布脚本"被用到了"单仓库项目"上,命令全错。
适用场景写清楚,能省掉至少一半的误用。
第 3 块:步骤清单
带数字编号的真正流程:
1. 跑 lint + 测试
2. bump 版本号
3. 写 changelog
4. npm publish
这部分越具体越好。能贴命令就贴命令,能写参数就写参数。模糊的"做相关检查"基本等于没写。
第 4 块:容易踩的坑
这是 Hermes 设计里最妙的一块。
不是写"正确做法",而是写"上次错在哪"。比如"忘记 build""发到了错误的 tag"。
为什么这个有用?因为模型在执行时会专门看这一段,相当于一个反向的 checklist。它会主动避开你之前掉进去的坑。
第 5 块:校验方式
每一步做完怎么验证?或者整个流程跑完怎么知道成了?
npm view <pkg> version 是否更新
没有校验,就没办法判断这次跑得对不对。后面 Review Agent 给 Skill 打分时也要靠这个。
Skill 是怎么被找到、用起来的
写好了 Skill,接下来才是有意思的:Agent 怎么知道现在该用哪个 Skill?
这是检索问题。Hermes 的做法没那么玄,4 步搞定。
第 1 步:用户提需求
"帮我把项目发布到 npm"。这是自然语言,模型还没开始动。
第 2 步:Skill 索引匹配
Hermes 会读.hermes/skills/下所有文件的元信息(不是全文,省 token)。
匹配逻辑分两层:
▸关键字匹配:用户说了"发布",命中所有带这个 trigger 的 Skill
▸语义补充:再用模型对剩下的做一轮语义打分
我看过这块的实现,trigger 关键字命中的会被加权,语义打分只是 tie-breaker。这样既快又准。
第 3 步:命中候选 Skill
通常会拿到 1~3 个候选。如果只有一个就直接用,多个会让模型看一眼标题和适用场景做选择。
我做实验时发现,这一步偶尔会出错 ——比如同时有"发布到 npm"和"发布到 GitHub Release",模型会卡一下。这种时候就靠 trigger 写得够区分。
第 4 步:注入到 Prompt
选定的 Skill 会被作为"执行手册"注入到当前任务的 system prompt。
注意,是注入"完整的 Skill 文件",不是摘要。因为执行时漏一步就崩,必须给完整步骤。
这一步也是为什么 Skill 文件要控制长度。一个 Skill 太长(超过 2000 token)就会挤掉其他上下文。Hermes 里有个隐形规则:单个 Skill 控制在 800~1500 token,太长就拆。
金句:找不到才创建,找到就复用。
这是整个 Skill 系统最朴素的哲学。Agent 不会一上来就生成新 Skill,永远是先找现成的。
Skill 不是只创建,更重要的是修补
很多人理解 Skill 系统时,停留在"AI 自己写 markdown"。
但 Hermes 真正聪明的地方是:它不是只写一次,而是会反复修补。
举个例子。你第一次让 Hermes 发布 npm 包,它跑出来的步骤可能是:
1. 跑测试
2. bump 版本
3. npm publish
跑成了,写进 SKILL.md。
第二次跑的时候,发现包发了但 changelog 没更新。Review Agent 复盘后会做一件事:修补这个 Skill。
Skill 文件会变成:
1. 跑测试
2. bump 版本
3. 写 changelog ← 新增步骤
4. npm publish
注意,不是"重新生成一个新 Skill",是"在原文件上 patch"。这是关键区别。
为什么是 patch 不是重写?
▸重写会丢历史经验(之前的"容易踩的坑"段落)
▸重写没办法增量评估(新版本相比老版本到底好了多少)
▸重写让版本号失去意义
Hermes 里 Skill 的修改是带 diff 的。每次 patch 都会留下"改了什么、为什么改"的记录。这个机制在第四章 Skill Hub 里会变成更复杂的"评估、灰度、回滚",先记住这个原型。
一个 Skill 的一生:5 个阶段
Skill 不是写完就完事,它有完整生命周期。Hermes 里大致分 5 个阶段。
Created(新建)
第一次任务跑通后,Review Agent 复盘出来的初版 Skill。这个时候它还很"嫩",没经过多次验证。
Used(被复用)
被检索到、被注入 prompt、被 Agent 执行。每一次复用都是一次实战检验。
Patched(修补)
执行中发现遗漏或错误,复盘后增补步骤、修正坑位说明。版本号 +1。
Aged(沉淀)
多次成功复用后,这个 Skill 就成了"成熟资产"。Hermes 内部对成熟 Skill 会提升信任度,比如允许跳过部分人工确认。
Retired(退役)
工具栈过时了(比如从 npm 切到 jsr)、流程不再适用了,Skill 会被归档而不是删除。归档的 Skill 不参与匹配,但还能查历史。
为什么不是直接删除?因为 Skill 携带了大量"经验",哪怕过时了,里面"上次踩的坑"依然有参考价值。
整个生命周期就一句话:越用越准,过期就退。
我自己用下来的几个建议
写完 Skill 系统的源码导读后,我总结了 5 条实操经验。
建议 1:Skill 写得越具体越好
模糊的 Skill 等于没写。"做相关检查"模型自己脑补,每次脑补都不一样。
我现在写 Skill 的标准是:步骤里能贴命令就贴命令,能写参数就写参数,能附校验就附校验。
建议 2:trigger 关键字要选区分度高的
别用"发布"这种太通用的词。"发布 npm 包""发布 GitHub Release""发布到生产环境",每一个都该有自己专属的 trigger。
不然检索阶段就会撞,撞了模型就纠结。
建议 3:定期清理 .hermes/skills/
我每个月会扫一次,把那些半年没用过、明显过时的 Skill 归档。
Skill 库膨胀的成本不是磁盘,是检索时的噪音。10 个 Skill 模型能选对,100 个就开始飘。
建议 4:Skill 写人能看懂的话
很多人喜欢让 Skill 看起来"机器味",全是 yaml 和 schema。
我的经验恰好相反:Skill 是给人也是给 AI 看的。哪天你需要手动调,写得越像菜谱越容易上手。
建议 5:别一上来追求"自动 Skill"
很多人接 Hermes 第一天就想让它自动生成所有 Skill。
我建议反过来,前 5 个 Skill 自己手写。这样你能感受到一个好 Skill 长什么样,后面让 Review Agent 写的时候也知道怎么挑、怎么改。
我的看法
我研究完 Skill 系统,最大的感受是 ——Skill 才是"自进化 Agent"真正的资产层。
Memory 解决的是"懂背景",但背景知识每个项目都要从头积累。
Skill 解决的是"会做事",而做事的方式可以跨项目、跨团队、跨人复用。一个写好的"发布流程 Skill",新人入职那天就能用,根本不用问老员工。
这才是 Agent 真正"能放进组织里"的关键能力。它不再是某个开发者的私人助手,而是能沉淀团队 know-how 的载体。
这也解释了为什么后面第四章会重点讲"企业级 Skill Hub"。当 Skill 从"个人 markdown"升级成"组织资产"时,就需要版本管理、质量评估、灰度发布、回滚机制 —— 这些都是工程系统该解决的事,不能靠人手 git。
Hermes 在单机版本里已经把骨架搭好了:版本号、patch、生命周期。剩下的是把它放大到组织层面,那是后面 16~25 篇要解决的事。
下一篇我们聊 Nudge Engine ——Hermes 是怎么主动触发"学习时刻"的,因为 Skill 不会自己冒出来,得有人按下"该复盘了"那个按钮。
往期推荐
Multi-Agent Teams:让多个专家 Agent 像团队一样协作
AI Agent 是怎么"想一步做一步"的?拆解 ReAct 模式
从零开始:用 LangChain.js 构建你的第一个 Tool-Calling Agent
最后
点个在看支持我吧