Skip to main content

Agent Skills 三层加载

在技能标准出现之前,想让同一套工作流在三个编码助手里都能用,得维护三份文件:一份 CLAUDE.md、一份 AGENTS.md、一份 .cursorrules。三份格式、三套路径,改动一次要同步三次,然后它们就开始各自漂移。

现在这个成本可以省掉。一份 SKILL.md 能在几十个 Agent 产品里用——写一次,到处加载。

1 发现name + description2 激活SKILL.md 正文3 按需取资源scripts/ references/启动时 · 每个约 100 token命中时 · 建议 < 5000 token需要时才读成本结构不激活的技能几乎不占上下文正文一次性全部载入引用文件一层深description 是唯一的触发器:它写不清"什么时候用",技能就不会被选中
图:技能按三层渐进加载,未激活时不占上下文

1. 一个技能就是一个文件夹​

最小形态只有一个文件:

release-notes/
└── SKILL.md # 必须叫这个名字,大小写敏感

完整形态可以带三类可选目录:

release-notes/
├── SKILL.md
├── scripts/ # 可执行代码,Agent 能直接跑
│ └── collect-commits.sh
├── references/ # 需要时才读的文档
│ └── FORMAT.md
└── assets/ # 模板、示例、静态资源
└── template.md

只有 SKILL.md 是必需的,其余都是可选的、按需加载的。

1.1 frontmatter 只有两个必填字段​

---
name: release-notes
description: 从 git 提交记录生成发布说明,按类型分组并标注破坏性变更。用于发版、写 changelog 或整理本周改动时。
---

就这两个。其余字段(license、compatibility、metadata、allowed-tools)全是可选的,而且规范要求合规实现忽略不认识的前端字段——这正是它能跨产品移植的原因:核心足够小,扩展不破坏兼容。

2. name 字段的约束​

约束不多但都很硬:

  • 1–64 字符
  • 只能包含小写字母、数字和连字符
  • 不能以连字符开头或结尾,不能有连续连字符
  • 必须与父目录名完全一致

最后一条是最常见的加载失败原因。目录叫 Release-Notes 而 name 写 release-notes,或者改名目录忘了改 name,技能直接不加载,而且通常不会给明确报错。

不合格的例子:PDF-Processing(大写)、-pdf(开头连字符)、pdf--processing(连续连字符)。

3. description 是唯一的触发器​

这是整个格式里最需要花心思的一行,它是设计的核心:name 和 description 是启动时唯一会被读入上下文的东西,Agent 靠它判断"这个任务要不要用这个技能"。

它要同时说清两件事——做什么,以及什么时候用。

# 差:太泛,Agent 不知道何时该用
description: 处理 PDF。

# 好:说清能力 + 触发场景 + 关键词
description: 从 PDF 提取文本和表格、填写表单、合并多个文件。当用户提到 PDF、表单、文档提取,或需要处理上传的 PDF 时使用。

上限 1024 字符,一般写 1–3 句就够。写的时候想一个问题:用户会用哪些词描述这个任务? 把这些词放进去。Agent 匹配的是语义,但具体的关键词能显著提高命中率。

描述写得含糊,技能就等于不存在——它会被静静地跳过,没有任何提示。

3.1 描述之间要能区分​

技能库大了之后会出现"该选哪个"的问题。如果两个技能的 description 高度重叠,Agent 会选错或者都选。

写完一批技能之后,建议把它们的所有 description 列成一列读一遍,看能不能仅凭描述判断该用哪个。如果连人都分不清,Agent 更分不清。

4. 三层渐进加载​

规范把加载分成三级,这个设计决定了技能库的上下文成本。

4.1 发现(启动时)​

启动时扫描技能目录,只加载每个技能的 name 和 description,每个约 100 token。这时候 Agent 知道有哪些技能可用,但不知道具体内容。

所以挂几十个技能的成本是可接受的——未激活的技能几乎不占上下文。这是它相对于"把所有规则写进一个巨大的 CLAUDE.md"最大的优势:后者无论用不用,全文都在上下文里。

4.2 激活(命中时)​

当用户点名某个技能,或 Agent 判断某个技能与当前任务相关时,才把 SKILL.md 正文整体读进来。

规范建议正文控制在 500 行、约 5000 token 以内。超出部分应该拆到 references/ 里去。

这里有个容易忽略的点:正文是一次性全部载入的。一个 3000 行的 SKILL.md 每次激活都吃掉这么多上下文,而其中大部分内容这次可能用不上。

4.3 资源(按需)​

scripts/、references/、assets/ 里的文件只在明确需要时才读。规范还建议引用保持一层深度——从 SKILL.md 直接指向 references/FORMAT.md,而不要让 FORMAT.md 再引用更深一层的文件。链式引用在按需加载模型下很容易断。

# SKILL.md 里的引用写法(相对技能根目录)

详细的字段说明见 [格式参考](references/FORMAT.md)。
字段校验跑 scripts/validate.py。

5. 正文该写什么​

正文没有格式限制,但有几条从实践里来的经验。

5.1 写可执行的步骤,不写原则​

"要保持代码简洁"这类原则,模型本来就知道,写进去只是占上下文。有价值的是它不知道的东西:这个仓库的发布流程是什么、先跑哪个脚本、输出要落到哪个文件、遇到冲突怎么处理。

判断标准:这句话删掉之后,Agent 会不会做错? 不会,就删掉。

5.2 长内容拆到 references​

SKILL.md 保留主干流程,细节放 references/:

  • REFERENCE.md —— 详细技术参考
  • FORMS.md —— 表单模板、结构化格式
  • 按领域拆的文件 —— billing.md、auth.md

拆细一点更好:Agent 按需加载,小文件意味着每次只吃需要的那部分。

5.3 脚本要自带错误信息​

scripts/ 里的脚本是给 Agent 跑的,不是给人跑的。所以:

  • 依赖要写清楚,不能假设环境里有
  • 失败时给出可行动的错误信息("缺少环境变量 GITHUB_TOKEN" 而不是 "error: undefined")
  • 边界情况别崩,返回非零退出码和说明

Agent 会读错误信息并尝试修复。一句好的错误信息能省掉三次失败的尝试。

6. 各家放在不同的目录​

格式统一了,但发现路径没有统一。这是目前移植技能时唯一要处理的事:

产品项目级全局
Claude Code.claude/skills/~/.claude/skills/
GitHub Copilot.github/skills/~/.copilot/skills/
Cursor.cursor/skills/~/.cursor/skills/
Gemini CLI.gemini/skills/~/.gemini/skills/
Codex.agents/skills/用户级路径
OpenCode.opencode/skills/~/.config/opencode/skills/

项目级与全局级的优先级,规范客户端实现指南建议 project-over-user(同名冲突时项目级生效)——但注意各产品实际行为并不统一:Claude Code 的顺序是 enterprise > personal > project,恰好相反。写通用规则时留一句"以具体客户端为准",别把一种实现当成标准。

实践做法:保留一份权威副本,其余用符号链接或安装命令同步。不要把同一份 SKILL.md 复制六份——那又回到三份文件各自漂移的老问题了。有 CLI 工具支持把一份源安装到任意 Agent 的项目级或全局级,用 copy 或 symlink 模式。

链接之前先校验 frontmatter,避免一个格式错误的 name 被复制到六个目录里。

7. 和 MCP、和系统提示词怎么分工​

三者解决的不是同一件事,容易混:

  • MCP 给的是能力——能调什么工具、读什么资源(见《MCP 的工具、资源和提示模板》)。没有 MCP,Agent 没有手段。
  • Skill 给的是做法——拿到这些手段之后,按什么流程做。没有 Skill,Agent 有能力但每次都要重新摸索。
  • System Prompt 给的是约束——什么不能做、什么必须遵守(见《System Prompt 写的是约束》)。

一个粗略的分法:跨任务都要守的规矩放系统提示词;某个特定任务才需要的流程放技能;完成任务需要的外部能力放 MCP。

技能相对系统提示词的优势是按需加载——系统提示词里的每一句都在每一轮请求里付费,技能只有命中时才付费。这跟《上下文是有限预算》里说的是同一件事:把不总是需要的东西从常驻上下文里挪出去。

8. 几个会踩的坑​

  • 文件名必须是 SKILL.md,Linux 和 macOS 上大小写敏感,写成 skill.md 不生效
  • name 与目录名不一致导致静默跳过
  • description 写成"是什么"而不是"什么时候用",命中率极低
  • 正文过长,每次激活都吃掉大量上下文,且会挤掉真正相关的内容
  • 引用链超过一层,按需加载时断掉
  • 复制多份而不是链接一份,改动不同步

最后一条最隐蔽:它会安静地工作几个月,然后在某次改动之后,两个 Agent 表现出不一致的行为,而你查不出原因。

Skills 与规则沉淀到一定规模之后,会自然出现一个问题:这套东西到底有没有用。该看哪些数、哪些数会被自己骗到,见《AI 研发基建怎么度量》。