Anthropic Skills 如何渐进加载并评测能力

Anthropic Skills 如何渐进加载并评测能力
Asaakii核验范围:本文以 agentskills.io 规范页 和 anthropics/skills 仓库 的
main分支为主要来源,重点读了规范正文、skills/pdf目录(SKILL.md、forms.md、reference.md、scripts/)以及官方工程文章。文中给出的字段约束、token 量级和脚本文件名均来自这两处;blog-md-preflight是我按同一格式写的示例,不是仓库里的现成 Skill。我没有在本地跑完整的skill-creator评测,只讨论从规范和公开示例中读到的设计方式。
假设用户给了我一份 30 页的 PDF,要求提取其中的表格、识别表单字段,再填回一份新文件。模型当然能读 PDF,但要稳定地完成这件事,还需要知道该用哪些库、何时调用脚本、遇到扫描件怎么办,以及怎么校验填好的表单。这几个问题本文都会具体回答,而不是停在”模型可以处理 PDF”这句话上。
Anthropic 的 Agent Skills 想解决的就是这类问题。它把一套可复用的操作经验放进一个目录:先让 Agent 看到简短的任务说明,确定相关后再读取具体步骤,最后按需要读取参考资料或执行脚本。本文以 Anthropic 的 pdf skill 为例,记录我理解这套机制的过程,并且尽量把每个概念都落到一份能看到的文件或一段能读的代码上。
先说明三个边界,后文会反复用到。Anthropic 最初提出并开源了 Agent Skills;anthropics/skills 是 Claude 的实现和示例仓库;现在跨平台的格式规范以 agentskills.io 为准。仓库 README 也把”Claude 的实现”和”标准”分开说明。凡是涉及”skill 怎么被发现、怎么被加载”的部分,标准只规定组织方式,具体行为取决于宿主 Agent,我会在对应位置标出。
这篇能解决什么问题
| 如果你想知道 | 建议阅读 |
|---|---|
| Skill 和 prompt、工具、MCP、RAG 有什么区别 | 先厘清概念 |
| 一个 Skill 最少要写什么、正文长什么样 | 最小结构 |
| Agent 到底怎么”发现”并选中一个 Skill | description 与匹配机制 |
| 为什么几十个 Skill 不会一起塞满上下文 | 渐进式披露与一笔账 |
| 为什么有些操作应该写成脚本 | PDF 示例 |
| 怎么从零写出并验证自己的第一个 Skill | 动手写一个最小 Skill |
| Skill 是否真的带来提升 | 评测闭环 |
| skill 放在哪、怎么被 Claude Code 加载 | 安装与使用 |
| 强约束型 Skill 应该怎么写 | 我的分类框架 |
先厘清概念:Skill 是什么,不是什么
初学者最容易把 Skill 和它周围一堆相似的东西混在一起。先用一张表把边界划开,后面的内容才不会悬空。
| 概念 | 它是什么 | 和 Skill 的关系 |
|---|---|---|
| 一次性 prompt | 你在对话里临时写的指令 | Skill 是把这套指令沉淀成可复用、按需加载的文件 |
| CLAUDE.md / 全局指令 | 每次会话都常驻上下文的项目约定 | Skill 默认不常驻,只有相关时才载入,省上下文 |
| 工具 / MCP | 让模型能”做”某件事(调 API、读文件、查数据库) | Skill 是”怎么做”的知识,可以指挥模型去调用工具或脚本 |
| 斜杠命令 | 用户手动触发的固定入口 | Skill 既可由用户点名,也可由模型按任务自动选中 |
| RAG | 运行时按相似度检索文档片段喂给模型 | Skill 是作者预先组织好的操作手册,不依赖向量检索来命中 |
一句话概括:Skill 是一份可以被 Agent 按需翻开的操作手册。它不新增模型的能力上限,而是在合适的时刻,把”这件事该怎么做”的经验精确地送到模型面前,同时避免不相关的经验一直占着上下文。
理解这一点,就能明白为什么 Skill 的价值不在”内容多”,而在”组织得当”。同样一段 PDF 处理经验,塞进一份三千行的超长提示词里,每次对话都得付出全部上下文成本,而且模型要在无关内容里找相关内容;拆成一个 Skill,则平时只露出一行 description,真正处理 PDF 时才展开正文,需要填表单时才进一步读 forms.md。差别不在写了什么,而在什么时候让模型看到什么。
一个 Skill 的最小结构
按当前规范,一个 Skill 是包含 SKILL.md 的目录。scripts/、references/ 和 assets/ 都是可选的:
1 | pdf/ |
上面是 anthropics/skills 里 pdf skill 的真实布局(文件名照抄仓库)。可以先记住这个形状:一份必需的 SKILL.md、若干按需读取的 Markdown、一批可执行脚本。
SKILL.md 以 YAML frontmatter 开始。真正必填的只有 name 和 description,最小的一份长这样:
1 |
|
各字段的约束如下,数字都来自规范:
| 字段 | 是否必填 | 约束与要注意的点 |
|---|---|---|
name |
是 | 1–64 个字符,只能用小写字母、数字和连字符,不能以连字符开头或结尾、不能出现连续连字符,且必须和目录名一致 |
description |
是 | 1–1024 个字符,非空,要同时写清”做什么”和”什么时候用” |
license |
否 | 许可名称,或指向一份打包在目录里的许可文件 |
compatibility |
否 | ≤500 字符,有特殊依赖、系统包、网络要求或目标产品时再写 |
metadata |
否 | 任意字符串键值对,供实现方保存额外属性 |
allowed-tools |
否 | 空格分隔的预授权工具列表,仍是实验字段,不同 Agent 支持情况不同 |
其中 allowed-tools 值得举个具体例子,规范给的写法是空格分隔的工具签名:
1 | allowed-tools: Bash(git:*) Bash(jq:*) Read |
它的意思是”这个 Skill 运行时预先批准 git、jq 命令和读文件”,好处是执行时少几次授权打断。但因为是实验字段,跨平台时不要依赖它,把它当锦上添花即可。
正文该写什么
规范对正文没有格式限制,只给了建议:写清分步骤、给输入输出示例、列常见边界情况。有一句提醒很关键:一旦 Skill 被激活,整份 SKILL.md 正文会被完整读入上下文,所以正文要克制,长的东西拆到引用文件里去。
拿真实的 pdf/SKILL.md 来看,它的正文骨架大致是这样(我按仓库里的分节还原):
1 | # PDF processing |
这个骨架本身就是一堂课:它没有把所有 PDF 知识铺开,而是先给一条最短路径(Quick start),再按”库/命令行/常见任务”分类,最后用一张对照表收口,把两块重内容(表单、排错)明确指向别的文件。初学者写自己的 Skill 时,照这个”最短路径 + 分类 + 指针”的结构走,通常不会太差。
写完后可以用 skills-ref validate ./my-skill 检查 frontmatter 和命名是否符合规范。
description 是触发器:怎么写,以及匹配是怎么发生的
这里最容易被低估的是 description。它不只是给人看的简介,而是 Agent 判断要不要激活这个 Skill 的唯一线索。先看规范给的一组好坏对照:
1 | # 差:模型没法判断什么时候该用它 |
差的那句问题不在”短”,而在没有可供匹配的信号:既没说清能做哪些具体动作,也没说什么场景下该被选中。好的那句把”做什么(extract/fill/merge)”和”什么时候用(提到 PDF、表单、文档提取)”都写出来了,模型才有依据。
匹配到底是怎么发生的
初学者常把这一步想成某种玄学,或以为背后有向量检索。就 Claude 的实现而言,机制其实很朴素:启动时,所有已安装 Skill 的 name 和 description 会被放进模型的上下文,约每个 100 token 量级;当任务与某个 description 匹配时,模型自己决定去激活它,这才触发正文的加载。没有 embedding,没有相似度阈值,就是模型读着这份清单做选择。
这个心智模型一旦建立,两条写法上的推论就很自然:
- description 写得过于笼统(”帮你处理文档”),模型在清单里看不出它和当前任务的关系,Skill 很可能不被选中。
- 把无关场景全塞进 description 想”多覆盖一点”,又会让它在不该出现的时候被误选,白白展开正文占上下文。
所以 description 的目标不是”介绍得全面”,而是”让模型在一屏清单里一眼认出这是不是当前该用的那个”。真实的 pdf skill 就把 description 写得很直白:从”读取/提取文本表格、合并、拆分、旋转、加水印、创建、填表单、加解密、提取图片、扫描件 OCR”一路列到”只要用户提到 .pdf 文件或要求产出一个 PDF,就用这个 skill”。它宁可把触发条件写满,也不含糊,因为这一行就是它被发现的全部依据。
渐进式披露:按需付出上下文成本
Skills 的核心不是多放几份 Markdown,而是把信息拆到不同加载时机。规范把它分成三层:
flowchart TD A["第一层:name 与 description(约 100 token/个)<br/>启动时载入,供 Agent 发现所有 Skill"] --> B["第二层:SKILL.md 正文(建议 < 5000 token)<br/>激活某个 Skill 后才读取核心步骤"] B --> C["第三层:scripts、references、assets<br/>仅在任务需要时才读取或执行"]
规范把第一层约束在约 100 token 的量级,建议 SKILL.md 正文控制在 5000 token 和 500 行以内,更长的说明拆到引用文件里。对 Claude 这类具备文件系统和代码执行能力的 Agent,脚本还可以直接执行,不必先把脚本全文读进上下文。
把这笔账算出来
抽象的”省上下文”不如一笔具体的账清楚。假设你装了 50 个 Skill,每个正文平均 4000 token:
如果不做分层,这 50 × 4000 = 20 万 token 就得一直常驻。别说很多模型的窗口放不下,就算放得下,模型每次都要在一堆无关内容里找相关内容,命中率反而下降。
做了渐进式披露就不一样:平时常驻的只有 50 × 100 = 5000 token 的 description 清单;当前任务真正激活的可能就 1 个 Skill,展开 4000 token 正文;用到脚本时才把某个脚本读进来。常驻成本从 20 万降到 5000,降了约 40 倍。
这就是为什么 Skill 强调”正文要短、重资料要拆”:省下来的不是磁盘,而是每一次对话都要重复付出的上下文预算。也正因如此,第一层的 description 才要写得精准,因为它是这套机制里唯一一直在花钱的部分。
需要强调一句边界:这套三层加载不是每个 Agent 产品都必然实现的,而是标准和 Claude 实现所倡导的组织方式。写跨平台 Skill 时,我会把”按需加载”和”能否直接执行脚本”分别写清,不假设每个宿主都有相同的权限与工具。
用 PDF Skill 看一次完整分工
Anthropic 的 pdf skill 很适合初学者拆读。它把常见操作放在 SKILL.md 中,把填写表单等专项说明放到 forms.md,把更详细的资料放在 reference.md,再把字段提取、填表、渲染或校验等确定性工作交给 scripts/。
回到开头那份 30 页 PDF 的任务,整个流程可以理解为:
- Agent 从每个已安装 Skill 的
name和description中发现 PDF 相关能力,选中pdf。 - 它读取
pdf/SKILL.md,拿到常用操作、分类和分支条件。 - 任务涉及表单时,它再读取
forms.md,而不是预先加载所有高级说明。 - 对”提取表单字段””填字段””校验填写结果”这类可确定执行的操作,它调用现成脚本并检查产物。
第四步是很多人没意识到、却最能体现设计的地方。仓库的 scripts/ 里放的不是零散片段,而是一批各司其职的确定性脚本,比如:
1 | extract_form_field_info.py # 提取表单里有哪些字段 |
到这里,开头留下的两个问题就有了着落。先看”遇到扫描件怎么办”:SKILL.md 的 Common tasks 里专门有一条扫描件 OCR,把扫描 PDF 变成可搜索文本,这条分支模型读正文时就能看到。再看”怎么校验填好的表单”:不是让模型”自己看一眼觉得对”,而是跑 check_fillable_fields.py 做程序化检查,必要时再用 create_validation_image.py 渲染出图供人核对。填表单这种既要精确、又容易出错的操作,交给脚本比交给模型的自然语言推理稳得多。
这种分工有两个直接收益。第一,模型不用每次重新组织一套 PDF 库调用方式。第二,复杂规则不会挤占所有 PDF 任务的上下文。官方工程文章也用这个例子说明:代码既能作为 Agent 的工具,也能作为可复用的操作知识。(官方文章)
我从这里得到的写法是:如果某段工作可以被明确输入、稳定执行、方便验证,就优先把它做成脚本;如果它依赖任务判断和上下文取舍,留在 SKILL.md 里;只有少见的分支才放进引用文件。填字段、校验结果属于前者,”这份文档大概是什么类型、该走哪条路”属于后者。这条界线比”把所有经验写进一份超长提示词”更容易维护,也更容易解释每一部分为什么在那里。
动手写一个最小 Skill:博客发布前检查
只读官方仓库,很容易觉得概念都懂了,却不知道从哪下手。下面把前面讲的东西压到一个能跑的最小例子上:给我自己的 Hexo 博客写一个”发布前检查” Skill。它的目录只有两个文件:
1 | blog-md-preflight/ |
先写 SKILL.md。注意 description 怎么按前面的原则写足触发关键词,正文怎么只放”顺序和判断”、把机械检查甩给脚本:
1 | --- |
再写那个被指向的脚本。它只做能确定判断的事,把需要人拍板的留给正文:
1 | #!/usr/bin/env python3 |
这个例子小,但它把本文的几个点都串了起来:description 写足了触发关键词(Hexo、frontmatter、cover、发布前检查);正文只保留顺序和异常处理这类需要判断的内容;机械、可验证的检查(字段在不在、date 像不像、路径像不像)交给脚本,模型不必自己去数。
要验证它到底有没有用,就用三篇文章各跑一遍:一篇故意缺封面、一篇日期格式写错、一篇完全正确,比较有 Skill 和没 Skill 时模型漏检的情况。这个练习比照抄一个大型 Skill 更值,因为它逼你回答三个问题:Agent 为什么需要它、哪些内容必须进上下文、怎样证明它确实减少了错误。
用评测判断 Skill 是否值得保留
一个 Skill 看起来很完整,并不等于它真的有用。Anthropic 在公开建议中强调从评测开始:先拿代表性任务观察 Agent 在哪里失败,再把失败模式整理成 Skill,最后比较加 Skill 前后的效果。
我会用一个很小的闭环开始,而不是一上来搭复杂基准:
1 | 任务集:3 到 5 个真实任务 |
“失败模式 → 写成 Skill”这句话有点抽象,还是用上面的博客检查举个实的。假设我先不写 Skill,让 Agent 帮我发布五篇文章,观察到一个稳定的失败模式:它经常忘记检查 date 字段的格式,导致文章排序错乱。这就是一条值得沉淀的失败模式。我把”检查 date 格式”写进 Skill(既进 SKILL.md 的检查顺序,也进脚本的断言),然后用一条可判定的断言来验证它是否补上了这个洞:
1 | 断言:对一篇 date 写成 "2026/6/10" 的文章, |
关键不在于凑够某个固定的运行次数或比例,而在于两点:一是每条 Skill 内容都能追溯到一个真实的失败模式,别写”感觉有用”的条款;二是始终保留 baseline(对照组)。没有对照,就很难分清”模型本来就会做”和”Skill 真正补上了什么”。skill-creator 把这件事做得更系统:准备代表性提示词、保留 baseline、对两组输出做断言或人工审阅、再根据失败样本回头调正文和 description,但它的内核就是上面这个闭环。
我的分类框架:能力型与纪律型
下面的分类不是 Agent Skills 规范中的官方术语,而是我用来阅读这个系列文章的一把尺。
| 类型 | 要解决的问题 | 常见内容 | 更适合的验证方式 |
|---|---|---|---|
| 能力型 Skill | Agent 缺少某项程序、领域或工具知识 | PDF 处理、生成文档、调用特定 API | 输出正确性、脚本结果、边界案例 |
| 纪律型 Skill | Agent 知道方法,但容易在压力下跳过步骤 | TDD、调试流程、需求澄清、提交前检查 | 是否遵循流程、是否留下验证证据 |
Anthropic 仓库中的 PDF、文档编辑和工具使用示例,大多可以放进”能力型”。我之前拆过的 Superpowers、Matt Pocock Skills 中,则有不少内容偏”纪律型”。上面那个博客发布前检查其实两头沾:查字段是能力型,”不许跳过 date 检查”是纪律型。两者都用同一个 SKILL.md 格式,但写法不该完全照搬。
能力型 Skill 要先让模型知道怎样完成任务,脚本和可执行示例往往很重要。纪律型 Skill 则要把触发条件、验收证据和例外情况写清,避免模型用”这次很简单”跳过关键步骤。这个分类只是起点,实际 Skill 经常同时包含两类内容,所以仍然要回到具体失败样本来决定写法。
安装与使用:skill 放在哪、怎么被发现
写出来只是一半,还得让 Agent 真的能加载它。这一节是标准之外的实现细节,我只讲 Claude Code 的情况,别的宿主未必一样。
就 Claude Code 而言,Skill 通常来自三个位置:
| 来源 | 放在哪 | 作用范围 |
|---|---|---|
| 个人 Skill | ~/.claude/skills/<name>/ |
你所有项目都能用 |
| 项目 Skill | <项目>/.claude/skills/<name>/ |
只在这个项目里生效,可随仓库提交、团队共享 |
| 插件 Skill | 通过插件安装 | 由插件作者维护、随版本更新,通常只读 |
放对位置后,启动时它的 name 和 description 就进入前面说的第一层清单,剩下的就交给 description 去匹配。想让某个 Skill 只由人手动触发、不让模型自动选中,一些实现(比如 Matt Pocock 的仓库)用 disable-model-invocation: true 表示。这属于宿主的扩展约定,不在核心规范里,跨平台前要确认对方支不支持。
给初学者一个简单的定位:目录放在 .claude/skills/ 下,name 和目录名一致,description 写足触发词,一个 Skill 就算装好了,不需要额外注册步骤。
使用公开 Skill 前的安全检查
Skill 可以携带指令和脚本,也就可能改变 Agent 的行为边界。安装第三方 Skill 前,我会先读 SKILL.md、脚本依赖和网络请求,确认它不会把本地数据传往未知地址,也不会执行与任务无关的命令。前面那个 allowed-tools 字段在这里就有了双重意义:它一方面替你省授权打断,另一方面也意味着这些命令是被预先放行的,读别人的 Skill 时要特别看清它预授权了什么。官方同样建议只从可信来源安装,并在使用前审查代码与资源。(安全建议)
许可也要单独看。Anthropic 仓库中许多示例采用 Apache 2.0,但 docx、pdf、pptx、xlsx 等文档类 Skill 是 source-available,pdf/SKILL.md 的 frontmatter 里就明确写着 license: Proprietary. LICENSE.txt has complete terms,并不等同于开源软件。将它们用于项目之前,应以目录中实际的许可说明为准。(仓库说明)
几个初学者常踩的坑
把前面的内容反过来说一遍,就是几条容易犯的错:
- description 写成自我介绍(”这是一个很强大的 PDF 工具”),而不是触发线索。模型靠它做选择,写清动作和场景才有用。
- 把所有内容堆进
SKILL.md正文。正文一旦激活就整份进上下文,长说明和低频分支应该拆到引用文件。 - 让模型用自然语言”校验”确定性结果。能写成脚本断言的检查(字段填没填对、格式合不合规),别指望模型自己看一眼。
- 不留 baseline 就下结论。没有对照组,你分不清是 Skill 起了作用还是模型本来就会。
- 假设别的宿主行为和 Claude 一样。加载时机、脚本执行、
allowed-tools、disable-model-invocation这些都可能因平台而异。
我的结论
Anthropic Skills 让我看到的不是一种”万能提示词格式”,而是一种组织 Agent 经验的方式:用简短元数据做发现,用 SKILL.md 给出主路径,把重资料和确定性操作延后到需要时再使用。它省的不是你写字的功夫,而是每一次对话都要重复付出的上下文成本,以及模型在无关内容里找相关内容的精力。
如果要把这篇的结论落到实践上,我会按这个顺序做:先写一个只有 name、description 和核心步骤的最小 Skill;拿真实任务和 baseline 比较;确认某一步重复且可验证后再补脚本;确认某段说明只在少数分支用到,再把它拆进引用文件;最后才扩充参考资料。这样写出来的 Skill 更容易解释,也更容易证明它给项目带来了什么。











