文章目录
- 前言
-
- [一、第一层:安装 Skill 后,先暴露的是 YAML frontmatter](#一、第一层:安装 Skill 后,先暴露的是 YAML frontmatter)
- [二、第二层:命中 Skill 后,才读取对应的 `SKILL.md`](#二、第二层:命中 Skill 后,才读取对应的
SKILL.md) - [三、第三层:执行过程中,再按需读取 `references`、`scripts`、`assets`](#三、第三层:执行过程中,再按需读取
references、scripts、assets)
- 写在文后
🔥 个人主页:铁皮哥(欢迎关注)
📌 作者简介:28届校招生,后端开发/Agent 方向在学
📚 学习内容:Java、Python、计算机视觉、大语言模型、Agent开发
📝 专栏内容:从零开始的Claude Code零代码生活(持续更新中)
✨不只背八股,更想搞懂为什么这样设计
前言
第一次接触 Skill 时,很多人会自然地把它理解成一种"增强版 Prompt"。
既然是 Prompt,那是不是写得越详细越好?
是不是应该把使用场景、执行步骤、项目规范、代码模板、风格要求、历史案例全部塞进 SKILL.md 里面?
于是,一个原本应该轻量清晰的 SKILL.md,很容易被写成一份越来越长的"万能说明书"。
在小规模场景下,这样做很稳妥:模型似乎能一次性看到所有规则,后续执行任务时也就不容易漏掉细节。但问题恰恰出在这里。
Skill 的设计思路,并不是把所有能力说明一次性塞进上下文。
它真正依赖的是一种更克制的加载方式:Progressive Disclosure,也就是"渐进式披露"。
简单说,一个 Skill 从安装到真正被使用,并不是一步到位完成加载,而是分成三个阶段逐步展开。
安装之后,系统首先暴露的是最轻量的元信息,也就是 YAML frontmatter 里的 name 和 description。这部分信息的作用不是执行任务,而是让模型知道:当前环境里有哪些 Skill 可以被调用,以及它们分别适合处理什么类型的请求。
当用户的请求命中某个 Skill 后,模型才会进入第二层,读取对应的 SKILL.md。这时,SKILL.md 才真正进入上下文,向模型说明这个 Skill 的适用场景、执行流程和资源索引。
再往后,模型并不会把 Skill 里提供的所有资料文件、模板文件、脚本文件一次性读完。它会根据 SKILL.md 里的指引,在执行到具体步骤时,按需读取 references、scripts、assets 等资源。
也就是说,Skill 的加载过程更像这样:
text
安装 Skill
↓
暴露 name / description
↓
用户请求命中对应 Skill
↓
读取 SKILL.md
↓
根据执行过程按需读取 references / scripts / assets
Skill 不应该是一份大而全的资料库,也不应该是一个不断加长的超级 Prompt。写好一个 Skill 的关键,不是把 SKILL.md 写得足够长,而是设计清楚一条上下文加载路径。
哪些信息应该一开始暴露?
哪些信息应该命中后再加载?
哪些细节应该等真正执行到那一步时再读取?
一、第一层:安装 Skill 后,先暴露的是 YAML frontmatter
一个 Skill 被安装后,最先暴露给模型的,是 SKILL.md 顶部的 YAML frontmatter。它通常长这样:
yaml
---
name: csdn-blog-writer
description: 用于生成、改写和审查 CSDN 技术博客文章
---
name 用来标识这个 Skill 是什么。比如上面的 csdn-blog-writer,模型可以通过这个名字知道:这是一个和 CSDN 博客写作有关的能力。
description 则更重要。它决定了模型在面对用户请求时,能不能判断出这个 Skill 该不该被使用。
比如用户说:
帮我写一篇适合发布到 CSDN 的技术博客。
这时,模型并不是先读取所有 Skill 的完整内容,再从里面慢慢找答案。它会先根据已经暴露出来的轻量级元信息进行匹配:当前请求是否符合某个 Skill 的 description?
如果某个 Skill 的 description 里明确写着"用于生成、改写和审查 CSDN 技术博客文章",那么这个请求就很容易命中它。
但如果 description 写得太宽泛,比如:
yaml
description: 用于处理各种文本任务
模型确实可能更容易命中它,但问题是命中过于模糊。写文章、改简历、生成日报、润色邮件都可以叫"文本任务",最后反而会让模型不知道这个 Skill 的边界在哪里。
如果 description 写得太窄,比如:
yaml
description: 用于生成 Java 后端项目中关于 Spring Boot Controller 层代码讲解的 CSDN 博客
它又可能只在极少数场景下被命中。用户稍微换一种说法,比如"帮我写一篇 Spring Boot 接口开发经验总结",模型就可能判断这个请求和当前 Skill 不够匹配。
更合理的写法,应该在"明确边界"和"保留覆盖面"之间取得平衡:
yaml
description: 用于生成、改写和审查 CSDN 技术博客文章,适合技术教程、项目复盘、源码分析和工程实践类内容
这段描述没有把范围写得过死,但也没有泛化成"处理所有文本"。它清楚地告诉模型:这个 Skill 面向的是 CSDN 技术博客,适合教程、复盘、源码分析、工程实践这类内容。
二、第二层:命中 Skill 后,才读取对应的 SKILL.md
第一层的 name 和 description 解决的是"能不能找到这个 Skill"的问题。
但找到并不等于已经开始执行。
当用户请求命中某个 Skill 后,模型才会进入第二层:读取这个 Skill 对应的 SKILL.md 主体内容。
模型读取 SKILL.md 之后,最需要立刻知道的不是所有细节,而是三件事:
当前这个
Skill适合处理什么任务;如果要处理这个任务,应该按照什么主流程推进;
如果某一步需要更详细的规则、模板或脚本,应该去哪里读取。
SKILL.md 的核心价值不是"信息量大",而是"路线清楚"。
比如一个用于 CSDN 写作的 Skill,它的 SKILL.md 不需要一开始就塞进完整的文风规范、所有标题模板、所有历史文章案例。它只需要先把主流程讲清楚:
markdown
# 使用场景
当用户需要撰写、改写、审查 CSDN 技术博客时,使用本 Skill。
# 工作流
1. 判断文章主题和目标读者
2. 生成标题和文章大纲
3. 按照 CSDN 技术博客风格生成正文
4. 检查文章结构、代码块、标题层级和结尾总结
5. 输出适合发布的 Markdown 内容
# 资源索引
- 文风规范见 `references/style-guide.md`
- CSDN 排版规范见 `references/csdn-format.md`
- 文章模板见 `templates/article-template.md`
- 审稿清单见 `references/review-checklist.md`
SKILL.md 负责告诉模型:现在进入了哪个工作流,应该先做什么、后做什么,哪些地方有外部资源可以继续读取。
至于文风规范到底有多少条、文章模板具体长什么样、审稿清单包含哪些检查项,这些内容暂时不用全部进入上下文。
只有当任务真的推进到对应步骤时,模型才需要继续打开那些文件。
这样设计之后,SKILL.md 就不会变成一个不断膨胀的"规则垃圾桶"。
它的内容会更像一张任务地图:地图上标出主路、岔路和关键入口,但不会把每个房间里的所有物品都画进去。
一个好的引用,不应该只是简单甩出一个文件名:
markdown
详见 `references/style-guide.md`
这种写法的问题在于,模型只知道有这个文件,却不知道什么时候该读,也不知道读它是为了解决什么问题。
更好的写法应该带上触发条件和读取目的:
markdown
当用户要求生成完整正文,或需要统一文章表达风格时,读取 `references/style-guide.md`,用于约束文章语气、段落节奏和技术表达方式。
这样,模型在执行任务时就能判断:当前是否真的需要打开这个文件。
如果用户只是让它"想几个标题",那可能不需要读取完整文风规范;
如果用户要求"写一篇完整文章并统一成我的博客风格",那就应该继续读取这个引用文件。
三、第三层:执行过程中,再按需读取 references、scripts、assets
第三层资源并不是 SKILL.md 的附属正文,也不是自动展开的补充说明。它们更像是被主文件索引起来的一组工具和资料,只有当任务真的走到对应步骤时,模型才会按需读取。
比如一个用于 CSDN 写作的 Skill,目录可能长这样:
text
csdn-blog-writer/
├── SKILL.md
├── references/
│ ├── style-guide.md
│ ├── csdn-format.md
│ └── review-checklist.md
├── templates/
│ ├── article-template.md
│ └── title-template.md
├── scripts/
│ └── check_article.py
└── assets/
└── cover-example.png
这里的每一类资源,都应该承担不同职责。
references 适合放稳定的规则和说明,比如文风规范、排版要求、审稿清单、项目约束。它们通常比较长,也不一定每次都会用到。
templates 适合放可复用结构,比如文章模板、标题模板、摘要模板。它们在生成完整内容时很有用,但如果用户只是让模型判断一个标题是否合适,就没必要提前读取完整模板。
scripts 适合放可执行逻辑,比如格式检查、文件转换、批量处理、自动上传。脚本本身不需要变成上下文里的自然语言说明,模型只需要在合适的时候知道它可以被调用。
assets 则适合放图片、示例文件、静态素材等资源。它们通常只在特定任务中才有价值,比如生成封面图、参考某个视觉样式、处理某个已有文件。
第三层真正解决的,就是细节太多但又不能丢的问题。它把长规则、模板和脚本从主文件里移出去,同时仍然通过 SKILL.md 保持可访问。
SKILL.md 负责建立索引,第三层资源负责提供细节。两者之间不是重复关系,而是分工关系。
举个例子,如果用户只是说:
帮我想 5 个关于 Claude Code 的 CSDN 文章标题。
这时模型大概率只需要读取 SKILL.md。因为它只需要知道这个 Skill 的写作方向、标题生成流程和基本约束,并不需要打开完整文章模板,也不需要运行审稿脚本。
但如果用户说:
帮我写一篇完整的 CSDN 技术博客,要求符合我的文章风格,并在最后检查一遍排版和结构。
这时任务已经明显推进到了更深的执行阶段。模型就应该根据 SKILL.md 里的资源索引,继续读取文风规范、文章模板和审稿清单:
text
references/style-guide.md
templates/article-template.md
references/review-checklist.md
如果文章生成后还需要做格式校验,它才可能进一步调用:
text
scripts/check_article.py
这才是 Progressive Disclosure 真正落到工程里的样子。
text
用户提出请求
↓
通过 name / description 判断是否命中 Skill
↓
命中后读取 SKILL.md,获得主流程和资源索引
↓
执行到具体步骤时,按需读取 references / templates / scripts / assets
↓
完成当前任务
这样拆完之后,效果会很直观。
因为大模型的注意力是稀缺资源,塞进上下文的每一个 token 都在和当前任务争抢模型的注意力。如果你启动时就把所有可能用到的工作流、模板、示例全塞进上下文,模型在处理实际请求时反而抓不到重点。
分出三层后,模型一开始只看到最必要的信息,不会被暂时用不到的细节干扰;任务变复杂时,又可以沿着 SKILL.md 提供的索引继续读取更细的规则、模板和脚本。上下文不是一次性铺满,而是随着任务需要逐层展开。
写在文后
期待您的一键三连!如果有什么问题或建议欢迎在评论区交流!