3. 渐进式披露
这是什么:渐进式披露(progressive disclosure) = 技能分三次交付:启动时只给「名字 + 简介」,选中后给正文,引用到才给附件。
为什么用:一个 Agent 装几十个技能很常见,但每次对话都用得上几十个吗?全量塞进上下文,光技能目录就能吃掉几千 token,还挤掉了真正重要的任务信息。
如何用:本章把三层各自的成本摊开算,重点讲第一层——description 是一次检索,模型只靠它挑技能。
3.1 三层的账本
规范给的成本基线是这么写的:
| 层级 | 内容 | 成本基线 | 加载时机 |
|---|---|---|---|
| L1 元数据 | name + description |
约 100 token / 个 | 会话启动时,全部加载 |
| L2 说明书 | SKILL.md 正文 |
建议 < 5000 token | 技能被激活时 |
| L3 资源 | scripts/ references/ assets/ |
不定 | 正文引用到时 |
做个粗算:装 40 个技能,光 L1 就是 40 × 100 ≈ 4000 token,一个技能正文都还没读就已经花掉了。这就是为什么 L1 必须短。
3.2 L1:description 是一次「检索」,不是「介绍」
模型在会话启动时看到的是这样一坨东西(opencode 的真实格式):
<available_skills>
<skill>
<name>git-release</name>
<description>Create consistent releases and changelogs</description>
</skill>
</available_skills>
注意这里只有名字和简介,没有正文。模型拿着这段目录做判断:现在这个任务,要不要调 skill({ name: "git-release" }) 把正文拉下来?
所以 description 的读者是模型,不是人。它的任务不是「介绍这个技能」,而是「让模型在正确的时刻认出来」。写 description: 一个很好用的周报技能 等于没写。
不同工具的 L1 呈现方式略有差别:
| 工具 | L1 长什么样 |
|---|---|
| opencode | <available_skills> 列表,模型调 skill 工具加载正文 |
| Claude Code | 命令菜单 + 自动匹配;description(含 when_to_use)在列表里截断到 1536 字符 |
| Hermes | skills_list() 只返回名字和摘要(整体约 3k token) |
Hermes 那套更直白——它的三个层级就是:
Level 0: skills_list() → 只有名字和简介(约 3k token)
Level 1: skill_view(name) → 任务真匹配了,才读全文
Level 2: skill_view(name, path) → 连参考文件也按需读
同一套渐进式披露,换了个产品还是这个套路。
3.3 description 的写法公式
一个能用的 description 通常包含三块:
<动词短语:做什么>。<场景:什么时候用>。<关键词:用户会怎么问>
照着这个写:
description: 汇总本周 Git 提交与 Issue,生成周报(三段式:做了什么/风险/下周计划)。用户提到「周报」「本周总结」「这周干了啥」时使用。
四个要点:
| 要点 | 说明 |
|---|---|
| 动词开头 | 「提取」「汇总」「检查」,别用「用于……的辅助工具」 |
| 写清触发场景 | 「用户提到 X 时使用」——模型靠这句话对齐用户的说法 |
| 塞关键词 | 用户嘴里的词(周报、发布、回滚)比规范术语(changelog、deployment)管用 |
| 别写实现 | 「调用 GitHub API 拉取 PR」是实现细节,不影响选择,可以省 |
反例对照:
| ❌ 差 | 为什么差 |
|---|---|
description: 周报技能 |
没说什么时候用,模型无从判断 |
description: 本技能通过分析 git log 生成结构化周报报告文档 |
全是实现细节,用户说的是「出周报」不是「分析 git log」 |
description: A helpful skill for generating weekly reports |
英文泛泛而谈,中文提问命中不了 |
3.4 L2:正文是「激活后」的常驻成本
技能被加载后,正文会一直留在上下文里(Claude Code 的官方说明里明确写了这点),直到会话结束。
这意味着正文应该写成操作清单,而不是说明书:
# ✅ 这样写
1. 跑 `git log --since="7 days ago" --oneline`
2. 按「做了什么 / 风险 / 下周计划」三段输出
3. 写到 `reports/YYYY-WW.md`
# ❌ 别这样写
因为团队每周都需要一份清晰的总结来对齐进度,所以本技能会先去收集本周的
提交记录,这一步非常关键,能够保证周报内容完整、不遗漏任何重要改动……
后者的信息量是零,token 成本却按字数一直付到会话结束。理由写给 review 的人看,步骤写给 Agent 看。
正文该有的三块内容(规范推荐):
- 分步骤指令——怎么做
- 输入输出示例——做成什么样算对
- 常见边界情况——什么时候别这么干
3.5 L3:资源按需拉取
第三层是 scripts/、references/、assets/。它们不占常驻上下文,只在 Agent 真的去读的时候才进来。
这给了一个非常实用的策略:把「可能用不到但很长的内容」全部下沉到 references。比如一份 800 行的接口文档,塞进正文就是每轮都在付钱;放进 references/api.md,则是用的时候才付。
weekly-report/
├── SKILL.md # 简短:只有步骤和输出格式
└── references/
├── report-template.md # 周报模板:需要时才读
└── issue-classification.md # Issue 分类规则:需要时才读
注意 L3 的规矩:引用只做一层,路径相对于技能根目录。
3.6 上下文预算怎么估
给一个新技能估成本,可以这么算:
常驻成本 ≈ L1 总和(元数据 × 技能数)
激活成本 ≈ L2(这个技能正文的 token 数)× 该技能活跃的轮数
偶发成本 ≈ L3(被引用到的资源大小)
实践中的三条经验:
- 技能数量控制在几十个以内。上百个技能时,光 L1 目录就会让模型的注意力被稀释,命中率跟着掉
- 同类技能合并。十个「日报类」技能不如一个「日报类」技能带三段说明——描述写清楚适用范围,模型自己会分
- 正文控制在几百 token。真需要长的,把细节下沉到
references/
🤝 记忆口诀:描述是检索词,正文是操作单,附件是抽屉。
动手改
- 拿你写过的一个技能,把
description改成「动词 + 场景 + 用户关键词」三段式,然后故意用一个不含任何原关键词的说法去试它,看模型还能不能选中 - 把技能正文里所有「因为…所以…」的解释性段落删掉,只留步骤,对比删前删后正文长度
- 给技能加一个
references/notes.md(至少 50 行内容),在正文里引用它,观察它只在被需要时加载
小结
- 三层账本:L1 元数据 ≈100 token/个常驻,L2 正文 <5000 token 激活后加载,L3 资源按需
- L1 是唯一的检索依据,
description要写「做什么 + 何时用 + 用户关键词」 - 正文一旦加载就常驻到会话结束,写操作清单,不写解释性长文
- 细节下沉到
references/,按需拉取,引用只做一层 - 技能别装太多,同类合并;把 L1 当目录页来经营
下一章:编写实战,三个可选目录到底该放什么、怎么拆 🐸