学习目标:掌握 Agent Skills 的"发现—激活—执行"三层架构,学会把一个臃肿的 Skill 重构为按需加载的分层结构,让 17 个 Skill 的发现总成本压到 ~1700 tokens,激活成本控制在 5000 tokens 以内。 适用人群:已经写过第一个 Skill、想让 Skill 在大规模(10+ 技能)环境下稳定高效运行的开发者。
~/.claude/skills/ 或项目 .claude/skills/ 下跑通一个最简 Skillskills-ref 验证工具)很多开发者写第一个 Skill 时会犯同一个错误:把所有规则、所有示例、所有脚本说明,一股脑写进 SKILL.md,文件膨胀到 8000 tokens。表面上看"内容全在一处很方便",实际却带来两个严重问题:
问题 1:上下文不是免费的。 大语言模型存在"lost in the middle"现象——上下文越长,模型对中间位置信息的提取准确率越低。研究表明,agent 同时挂载的工具一旦超过 10 个,准确率就开始下降;超过 20 个则明显劣化。指令和工具定义遵循同样的规律。当你挂了几个 MCP 服务器,工具的 JSON Schema 很容易就堆到 50000 tokens,模型还没开始推理,注意力已经被稀释。
问题 2:激活成本暴涨。 Skill 一旦被判定为相关,整个 SKILL.md 会被加载进上下文。一个 8000 tokens 的 Skill 每次激活就吃掉这么多窗口;如果你有 20 个这样的 Skill,热点任务反复激活时,窗口被无效内容反复挤压。
Anthropic 官方仓库里 skill-creator 的 SKILL.md 确实达到约 8000 tokens,但那是少数——官方 17 个 Skill 的 SKILL.md body 中位数只有约 2000 tokens,最小的 internal-comms 仅 275 tokens。差距的全部秘密,就在于渐进式披露(Progressive Disclosure)。
渐进式披露是一个源自人机交互(Nielsen Norman Group)的经典设计原则:只展示当前任务需要的信息,把进阶选项藏到二级入口。Agent Skills 把这个原则应用到了上下文管理上,形成三层加载模型:
| 层级 | 触发时机 | 加载内容 | 典型成本 |
|---|---|---|---|
| Layer 1 发现 | 启动时,常驻 | 仅 name + description |
~80 tokens/skill |
| Layer 2 激活 | 判定任务相关 | 完整 SKILL.md body |
< 5000 tokens 推荐 |
| Layer 3 执行 | 执行中按需 | scripts/、references/、assets/ |
仅当前所需 |
对 Anthropic 官方 17 个 Skill 的实测显示:发现层成本从 55 tokens(webapp-testing)到 235 tokens(xlsx)不等,全部 17 个加起来约 1700 tokens——让 agent "意识到"几十个技能存在,成本比激活单个技能还低。这正是分层设计的威力。
flowchart TD
A[Agent 启动] -->|扫描所有 Skill| B["Layer 1 发现<br/>仅 name+description<br/>~80 tokens/skill"]
B --> C{description 与<br/>当前任务相关?}
C -->|否| D[保持休眠<br/>零额外开销]
C -->|是| E["Layer 2 激活<br/>加载完整 SKILL.md<br/>建议 < 5000 tokens"]
E --> F[按指令执行]
F --> G{遇到需要<br/>细节的步骤?}
G -->|否| I[直接完成]
G -->|是| H["Layer 3 执行<br/>按需读 references/scripts/assets"]
H --> I
I --> J[完成后缓存或卸载]
关键洞察:路由准确性几乎完全取决于 description 的质量。模型在 Layer 1 用纯推理判断"这个 Skill 该不该激活",写好 description 就等于写好路由表。这也是为什么 name 和 description 是 frontmatter 里仅有的两个必填字段。
下面我们以一个"API 文档生成器"为案例,演示完整的三层重构过程。先看反例——一个把所有东西塞进 SKILL.md 的臃肿版本:
---
name: api-doc-generator
description: Helps with API docs.
---
# API 文档生成器(臃肿版)
(此处省略 8000 tokens 的 OpenAPI 字段规范、
各框架解析规则、20 个示例、报错排查……全部堆在这一个文件里)
这个版本有三大病灶:description 模糊("Helps with API docs" 缺少触发关键词)、body 臃肿(每次激活浪费数千 token)、没有执行层(细节和脚本混在一起)。我们逐层修复。
description 必须同时回答两个问题——做什么和何时用,并埋入用户真实会说的关键词。规范要求 1–1024 字符。
---
name: api-doc-generator
description: 为 Express/FastAPI/Fastify/Spring Boot 项目自动生成 OpenAPI 3.x 接口文档。当用户说"生成API文档""导出OpenAPI/Swagger""列出所有端点""从路由代码提取接口"时使用;也可用于把现有路由转成可交互的 API 参考。
metadata:
author: bootcamp-demo
version: "1.0"
---
frontmatter 字段速查(基于 Agent Skills 开放规范):
| 字段 | 必填 | 约束 |
|---|---|---|
name |
是 | ≤64 字符;仅小写字母/数字/连字符;不得以连字符开头结尾、不得连续连字符;必须与父目录名一致 |
description |
是 | 1–1024 字符;同时说明做什么+何时用 |
license |
否 | 许可证名或指向 LICENSE 文件 |
compatibility |
否 | ≤500 字符;环境要求(系统包、网络等) |
metadata |
否 | 任意 string→string 映射 |
allowed-tools |
否 | 空格分隔的预批准工具(实验性) |
name 字段有几个易错点:PDF-Processing(大写不允许)、-pdf(连字符开头)、pdf--processing(连续连字符)都会验证失败。
常见问题:description 写了"帮助处理 API",结果 Skill 死活不触发。
解决:用 /help 或 skills-ref 观察实际加载的 metadata,把用户真实措辞("导出接口文档""Swagger")作为关键词写进 description。
激活层只放"决策骨架"——分支判断、高层流程、指针。目标是把 body 控制在 500 行以内、5000 tokens 以内:
# API 文档生成器
## 决策流程
1. 识别项目框架(检查 package.json / requirements.txt / pom.xml)
2. 按下表选择解析脚本
3. 解析后套用输出模板,产出 OpenAPI 结构
## 框架 → 脚本映射
| 框架 | 解析脚本 |
|------|---------|
| Express / Koa | `scripts/parse_js_routes.py` |
| FastAPI | `scripts/parse_fastapi.py` |
| Spring Boot | `scripts/parse_spring.py` |
## 何时需要深入细节
- OpenAPI 字段写法不确定 → 读 `references/openapi-spec.md`
- 输出格式与模板 → 读 `references/output-templates.md`
- 完整示例 → 读 `references/example-output.md`
> 除非当前任务明确需要,**不要预读** references/ 下的文件。
这个 body 约 250 tokens,相比 8000 tokens 的臃肿版,激活成本骤降 96%。骨架里最关键的一句是最后那行防预读指令——明确告诉模型"没需要就别加载",避免它好心把所有 reference 全读进来,前功尽弃。
执行层遵循一个铁律:单个文件聚焦一个主题,越小越好。因为模型按需加载,文件越小,单次加载越省。目录结构如下:
api-doc-generator/
├── SKILL.md # Layer 2 骨架(~250 tokens)
├── scripts/
│ ├── parse_js_routes.py # Express/Koa 路由解析
│ ├── parse_fastapi.py # FastAPI 装饰器解析
│ └── parse_spring.py # Spring 注解解析
├── references/
│ ├── openapi-spec.md # OpenAPI 3.x 字段规范
│ ├── output-templates.md # 输出模板
│ └── example-output.md # 完整示例
└── assets/
└── example-openapi.json # 静态示例文件
references/openapi-spec.md(节选)放的是字段级细节:
### paths 对象
每个路径以 `/` 开头,键为路径模板,值为 Path Item Object。
### parameters
- `name`:必填,参数名
- `in`:query | header | path | cookie
- `required`:path 参数必须为 true
- `schema`:类型定义,引用 `$ref: '#/components/schemas/...'`
### responses
- HTTP 状态码作键(如 `200`、`404`)
- 每个值含 `description`(必填)和可选 `content`
当任务是"审查这个 FastAPI 项目的接口安全"时,模型只会加载 scripts/parse_fastapi.py 和 references/openapi-spec.md,而 Express 的解析脚本、Spring 的注解规则——全部留在磁盘上零开销。这就是分层加载的本质收益:按任务裁剪上下文。
规范明确要求:文件引用用相对路径,且保持一层深度,避免深层嵌套引用链。
正确写法(在 SKILL.md 中):
见 [OpenAPI 字段规范](references/openapi-spec.md) 了解详细字段。
运行解析:`python scripts/parse_fastapi.py`
错误写法:
见 references/openapi-spec.md,它又指向 references/advanced/security.md,
后者再引用 references/advanced/oauth/flows.md ……
深层嵌套引用链会让模型陷入"读了 A 才知道要读 B,读了 B 才知道要读 C"的连环加载,既慢又费 token。每层 reference 应当自包含,直接被 SKILL.md 指向。
写完后用官方参考库 skills-ref 校验 frontmatter 合法性与命名规范:
npx skills-ref validate ./api-doc-generator
它会检查 name 是否匹配目录名、是否含非法字符、description 是否非空等。验证通过再发布。
把上面片段拼成可运行的项目。先创建目录与最小文件:
mkdir -p ~/.claude/skills/api-doc-generator/{scripts,references,assets}
scripts/parse_fastapi.py(一个真实可跑的最小解析器):
"""从 FastAPI 项目提取路由定义,输出端点列表。
用法: python parse_fastapi.py <app_dir>
"""
import ast, sys, json
from pathlib import Path
VERBS = {"get", "post", "put", "delete", "patch"}
def extract(file_path: Path):
tree = ast.parse(file_path.read_text(encoding="utf-8"))
endpoints = []
for node in ast.walk(tree):
if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute):
if node.func.attr in VERBS:
path = ast.literal_eval(node.args[0]) if node.args else ""
endpoints.append({"method": node.func.attr.upper(), "path": path,
"file": str(file_path)})
return endpoints
if __name__ == "__main__":
if len(sys.argv) < 2:
print("用法: python parse_fastapi.py <app_dir>", file=sys.stderr); sys.exit(1)
root = Path(sys.argv[1])
all_eps = []
for py in root.rglob("*.py"):
try: all_eps += extract(py)
except SyntaxError: continue
print(json.dumps({"openapi": "3.0.3", "paths_count": len(all_eps),
"endpoints": all_eps}, indent=2, ensure_ascii=False))
预期结果:对一个含 @app.get("/users") 的 FastAPI 文件运行,输出:
{
"openapi": "3.0.3",
"paths_count": 1,
"endpoints": [{"method": "GET", "path": "/users", "file": "app.py"}]
}
触发演示:在项目里对 Claude 说"帮我导出这个 FastAPI 服务的 OpenAPI 文档",Claude 会:①Layer 1 匹配 description 命中 → ②Layer 2 加载 ~250 token 骨架,识别出是 FastAPI 分支 → ③Layer 3 仅加载 parse_fastapi.py + openapi-spec.md → ④产出文档。全程上下文干净,Express/Spring 那几个文件从不被加载。
假设一个 agent 同时挂载 20 个 Skill,其中 5 个是本案例这样的"知识密集型"技能:
| 指标 | 单文件臃肿版 | 三层分层版 |
|---|---|---|
| 单个 Skill 激活成本 | ~8000 tokens | ~250 tokens(骨架) |
| 20 个 Skill 发现总成本 | ~1600 tokens | ~1600 tokens(发现层不变) |
| 一次任务无关文件加载 | 0(全在一起) | 仅命中分支的文件 |
| "lost in the middle"风险 | 高 | 低 |
发现层成本两种结构相同(都只读 name+description),差异全在激活层和执行层。分层结构的全部收益,体现在"只加载被命中的那一支"。
flowchart LR
subgraph 单文件臃肿版
A1[激活即加载 8000 tokens<br/>所有规则/示例/脚本说明]
end
subgraph 三层分层版
B1["骨架 250 tokens"] --> B2{命中分支?}
B2 -->|FastAPI| B3["parse_fastapi.py<br/>+openapi-spec.md<br/>≈1200 tokens"]
B2 -->|Express| B4["parse_js_routes.py<br/>≈900 tokens"]
B2 -->|其余| B5[不加载]
end
Q1:我的 Skill 描述很详细,为什么还是不触发? A:description 里缺"用户真实措辞"。你写的是"处理文档",但用户说的是"导出 Swagger"。把后者作为关键词写进去。路由纯靠 Layer 1 的推理,关键词就是路由表。
Q2:模型激活后总是把 references 全读一遍,怎么办? A:在 SKILL.md 骨架末尾加一句显式指令:"除非当前任务明确需要,不要预读 references/ 下的文件。" 这句指令的省 token 效果立竿见影。
Q3:reference 文件该切多细? A:按"一次任务只会同时需要其中几个"来切分。OpenAPI 字段规范、输出模板、示例天然是独立主题,就拆成三个文件;如果两个文件几乎总是一起被读,就合并。
Q4:跨平台(Claude Code / Codex / Gemini)格式一样吗?
A:SKILL.md 格式是 2025-12-18 发布的开放标准,OpenAI、Google、GitHub、Cursor 均已采纳,格式一致;只是存放路径不同(Claude Code 用 ~/.claude/skills/,Codex 用 .agents/skills/,Gemini 用 .gemini/skills/)。
Q5:激活后卸载,下次又重载,会不会反复浪费? A:会。成熟的实现会缓存最近用过的 Skill、保持高频激活的 Skill"warm",在上下文效率与重复加载成本间取平衡。设计上让骨架小,正是为了降低这个反复成本。
skills-ref validate 通过截图与激活前后 token 对比报告。[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
