技能系统:Agent 如何把经验变成可复用的程序化记忆

从声明式 SKILL.md 到自动化经验积累,Hermes 如何让 Agent 越用越聪明

通过 Hermes 探秘 Agent 工程 | 第 9 篇 · 查看全部

上一篇:记忆系统:跨会话持久化的工程实现


[系列文章导航]

#文章定位
1Agent Loop:Agent 的核心执行循环入口
2System Prompt:身份、上下文与策略的三层架构认知层
3工具系统:从注册到调度工具层
4工具调度系统:从注册到执行的完整生命周期调度层
5安全防护体系:当 Agent 拥有终端时如何防止「做出格」的事安全层
6沙箱与代码执行:让 Agent 安全跑代码的 RPC 架构执行层
7上下文压缩:让 Agent 在有限窗口里「记得住」记忆层
8记忆系统:跨会话持久化的工程实现记忆层
9技能系统:Agent 如何把经验变成可复用的程序化记忆记忆层
10Provider 抽象层:让 Hermes 同时驾驭 30+ 个 LLM 提供商模型层
11Gateway 网关:连接 20+ 平台的统一消息路由接入层
12多 Agent 协作:委托、调度与看板协作层

问题:记住了"是什么",但忘了"怎么做"

第 8 篇聊过 Hermes 的记忆系统——MEMORY.md 记事实,USER.md 记偏好。它们是陈述性记忆——你知道什么。

但 Agent 完成一个复杂任务后,最有价值的不是"我知道什么",而是"我怎么做成的"。这是程序化记忆——关于"怎么做"的知识。

Hermes 的技能系统就是为此设计的:把成功的做法编码成可复用的程序化记忆。

技能是什么

一个技能就是一个目录,核心是一个 SKILL.md 文件:

~/.hermes/skills/
├── docker-deploy/
│   ├── SKILL.md              # 主指令(必须)
│   ├── references/
│   │   └── troubleshooting.md
│   └── templates/
│       └── Dockerfile.tpl

frontmatter 有严格的长度限制:description ≤ 1024 字符,name ≤ 64 字符——它们对应 LLM 上下文窗口里每个技能的 token 预算

三个工具:skills_list、skill_view、skill_manage

skills_list — 列出所有可用技能

返回 JSON:只包含 name + description 的元数据——几十个技能加起来可能只有 1000 字符

skill_view — 加载完整的技能内容

调用链:

  1. 路径安全检查 — 拒绝 .. 遍历
  2. 插件分发 — plugin:skill 格式
  3. 三策略查找 — ① 直接路径匹配 → ② 递归目录名匹配 → ③ frontmatter name 字段匹配
  4. 碰撞检测 — 多个目录匹配同一个 name → 拒绝
  5. 平台过滤 — frontmatter.platforms 不匹配当前 OS → 跳过
  6. 环境过滤 — frontmatter.requires 不满足 → 跳过

每次成功的 skill_view 还会触发遥测:更新 view_countuse_count

skill_manage — 创建、更新、删除技能

支持 createpatch(模糊匹配替换)、delete(三层路径验证防误删)。

渐进式披露:token 预算的艺术

第 1 篇提到过,system prompt 是"有价商品"。技能系统的渐进式披露在两个层面解决这个问题:

层面一:System Prompt 里的 Skill Index

build_skills_system_prompt() 在 system prompt 里注入一份紧凑的技能索引

## Skills (mandatory)
Before replying, scan the skills below. If a skill matches or is even partially
relevant to your task, you MUST load it with skill_view(name) and follow its
instructions.

<available_skills>
  devops: DevOps and infrastructure skills
    - docker-deploy: 用 Docker 部署 Python web 应用的最佳实践...
    - kubernetes: 在 Kubernetes 上部署和管理容器化应用...
  writing: Documentation and writing skills
    - api-docs: 编写 REST API 文档的最佳实践...
</available_skills>

关键设计决策:索引不是过滤,只是提示。LLM 自己判断该调不调 skill_view。没有任何代码逻辑禁止加载索引之外的 skills。

层面二:两层缓存避免重复计算

L1 — 进程内 LRU cache:cache key 包含 skills_dir、available_tools、platform hint 等——Gateway 多 session 共用同一个进程时保证技能索引独立。

L2 — 磁盘快照~/.hermes/skills/.skills_prompt_snapshot.json,冷启动时直接读 JSON 解析即可,不需要遍历所有 SKILL.md 文件。

层面三:按需展开

层级调用返回内容典型 token 消耗
L1System promptname + description 索引~100/token × SKILL
L2skill_view(name)完整 SKILL.md + linked_files 目录~2K-10K
L3skill_view(name, file_path)单个文件的内容~500-5K

工程启示

1. 程序化记忆 vs 陈述性记忆

MEMORY.md 记事实,SKILL.md 记流程。把"世界知识"和"操作知识"分开存储,能显著提升检索效率。

2. 渐进式披露是 Agent 的标准技能

所有需要把"大量信息"暴露给 LLM 的场景(工具定义、文档检索、推荐系统),都应该采用书脊 → 目录 → 正文的渐进模式。

3. 声明式技能比代码插件更安全

SKILL.md 是 Markdown 文档,不是 Python 代码。它只能"告诉" LLM 怎么做,不能自己执行。安全风险从"任意代码执行"降级为"prompt injection"。

4. 缓存维度设计

cache key 包含了 platform hint + compact_categories + available_toolsets——不只是"内容变了才 cache 失效",而是"消费上下文变了才 cache 失效"。


下一篇:Provider 抽象层:让 Hermes 同时驾驭 30+ 个 LLM 提供商 — 声明式 Profile、插件化注册、三种传输协议、Fallback 链