关于 writing-great-skills
writing-great-skills 是帮助作者设计可预测 Agent Skill 的参考 Skill,讲解调用方式、信息组织、拆分与精简,以管理执行行为和上下文占用。
主要功能
- 01设计模型调用与用户调用
- 02编写描述和触发条件
- 03组织步骤与参考信息层级
- 04采用渐进式披露
- 05拆分与精简 Skill
- 06诊断常见失效模式
适用场景
- 01选择 Skill 的调用方式
- 02组织指令和关联参考资料
- 03减少重复内容与上下文占用
- 04排查过早完成或 Skill 膨胀
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ leandrocfe/ skills --skill writing-great-skills安装后在 Claude Code 中输入/writing-great-skills确认已加载。
附带文件GLOSSARY.md
详细介绍
一种 skill 的作用,是从随机系统中提取确定性。可预测性——agent 每次执行都遵循相同的_流程_,而不是产出相同的结果——是首要美德;下面的所有机制都服务于它。
GLOSSARY.md 中定义了粗体术语;完整含义请参阅该文件。
调用方式
两种选择,各自权衡不同的成本:
- model-invoked skill 会保留一段 description,让 agent 可以自主触发它,_也_让其他 skills 能调用它(你仍然可以输入名称)。它会增加 context load——每一轮对话中,description 都会留在上下文窗口里。实现方式:省略
disable-model-invocation,并编写面向模型的 description,加入丰富的触发语句(例如“当用户想要……、提到……”)。 - user-invoked skill 会让 agent 无法访问 description:只有你亲自输入名称才能调用它,其他 skill 也无法调用。它不占用 context load,但会增加 cognitive load:_你_就是索引,必须记得它的存在。实现方式:设置
disable-model-invocation: true;此时description面向人类,写成一行摘要,并移除触发条件列表。
只有在 agent 需要自主调用某个 skill,或其他 skill 需要调用它时,才选择 model-invocation。如果它只通过手动方式触发,就设为 user-invoked,不占用 context load。
当 user-invoked skills 多到你记不住时,可以用一个 router skill 来管理累积的 cognitive load:这个 user-invoked skill 会列出其他 skills,并说明何时使用它们。
编写 description
model-invoked 的 description 有两项职责:说明这个 skill 的用途,并列出应该触发它的 branches。每个词都会增加 context load,因此 description 比正文更需要严格精简:
- 将 skill 的核心词前置——description 正是它发挥调用作用的地方。
- 每个 branch 只写一个触发条件。 只是换个说法来表达同一个 branch,就属于 duplication——“使用 TDD 构建功能……用户要求先写测试”其实把同一个 branch 写了两遍。合并这些表述;只保留真正不同的 branches。
- 删去正文中已有的身份介绍。 description 只保留触发条件,以及任何说明适用范围的条款,例如“当其他 skill 需要……时”。
信息层级
一项 skill 由两种内容构成——步骤和参考资料,两者可以自由组合:一项 skill 可以只有步骤、只有参考资料,也可以两者兼有。核心在于决定使用哪种内容,以及它们在信息层级中的位置。信息层级是一架按 Agent 对材料的需求紧迫程度排序的阶梯:
- Skill 内步骤——写在
SKILL.md中的有序操作,是主要层级:Agent 要做什么,以及按什么顺序做。每个步骤都以一个完成标准结束,说明工作何时算完成。让标准_可检查_(Agent 能区分已完成和未完成吗?);在重要之处,还要让标准_涵盖全面_(“所有已修改的模型都已列明”,而不是“生成一份变更列表”)——含糊的标准会导致过早完成。 - Skill 内参考资料——写在
SKILL.md中,按需查阅的定义、规则或事实。通常,所有规则平铺在同一层也是合理的安排(例如,一项审查中的所有规则都在同一层)——这只是细粒度的组织方式,并非坏味道。这项 skill 全部由参考资料构成。 - 外部参考资料——从
SKILL.md移至单独文件的参考资料,通过上下文指针访问,只有在指针触发时才加载。(范围从_已披露_的参考资料——例如GLOSSARY.md这样的同目录文件,仍属于该 skill——到外部参考资料,后者位于 skills 系统之外,任何 skill 都可以指向它。)
严格的完成标准会促使 Agent 深入开展调查工作——即 Agent 在任务中进行的挖掘——无论 skill 是否包含步骤,因为“应用每条规则”对平铺的参考资料的约束,就如同“完成每个步骤”对一系列步骤的约束一样。
下沉得不够,顶层就会臃肿;下沉得太多,又会把 Agent 真正需要的材料藏起来。所有权衡都在于此。
渐进式披露就是沿着阶梯向下移动——从 SKILL.md 移至链接文件——让顶层保持易读。具体做法是:在 skill 文件夹中放置一个链接的 .md 文件,并按其内容命名(这项 skill 将完整定义披露在 GLOSSARY.md 中)。有些 skills 有多种使用方式,每种不同的方式都是一个分支——不同的运行过程沿着该 skill 走不同的路径。分支是检验披露策略最直接的方式:将所有分支都需要的内容放在行内,把只有部分分支会用到的内容放在指针之后。上下文指针的措辞,而非其指向的目标,决定了 Agent 何时以及能否可靠地找到相关材料。
阶梯决定某项内容_放得多远_,而就近组织决定它到达该层级后_与什么并列_:将某个概念的定义、规则和注意事项放在同一标题下,而不是分散开来,这样阅读某一部分时也能一并看到相关内容。
何时拆分
粒度是指将 skills 拆分得多细;每次拆分都会消耗两次加载机会之一,因此只有在值得时才拆分。拆分有两种:
- 按调用方式拆分——当你有一个独特的首词,需要单独触发某项由模型调用的 skill,或另一项 skill 需要调用它时,将该 skill 拆分出来。你需要为新的、始终加载的描述付出上下文加载成本,因此这种独立调用能力必须物有所值。
- 按顺序拆分——如果后续的步骤(某个步骤的完成后步骤)会诱使 Agent 仓促完成眼前的工作(过早完成),就将这段步骤序列拆分出来。让后续步骤暂时不可见,可以鼓励 Agent 在当前任务上做更多调查工作。
精简
让每个含义都只有一个唯一事实来源:只保留一个权威位置,这样要改变行为时,只需修改一处。
逐行检查相关性:这一行是否仍会影响 skill 的行为?
然后逐句查找无效内容,而不只是逐行检查:单独对每个句子进行无效性测试;如果某个句子未通过,就删掉整个句子,而不是只删减其中的词语。要果断——大多数未通过测试的文字都应该删掉,而不是改写。
引导词
引导词是一种紧凑的概念,早已存在于模型的预训练中,Agent 在运行技能时会借助它思考(例如:lesson、fog of war、tracer bullets)。在文本中反复出现(但并非必须如此——一个有力的引导词只出现一次也可能足够),它会逐步形成分布式定义,并用尽可能少的 token 锚定一整片行为区域,调动模型已有的先验知识。
它从两个方面提升可预测性。在正文中,它锚定_执行_:引导词每次出现时,Agent 都会采取相同的行为。在描述中,它锚定_调用_:当同一个词也出现在你的提示词、文档和代码中时,Agent 就会把这种共享语言与技能联系起来,从而更可靠地触发它。
寻找将技能重构为使用引导词的机会。某个三元组在三个地方逐字出现(重复),描述中用一句话指向某个想法——每一处都是在呼唤你将其折叠为一个 token。示例:
- “快速、确定性、低开销” -> tight — 在某个阶段反复重申的一种特质 — 用一个预训练词表达(一个 tight 循环)。
- “一个你信得过的循环” -> red — 将模糊的门槛转化为可观察的二元状态(遇到 bug 时,循环会变成 red,否则就不会)。
你能获得双重收益:减少 token,_并且_为 Agent 提供更清晰的推理支点。假设每项技能都包含可以由引导词取代的重复表述——去把它们找出来。
失败模式
使用这些模式来诊断用户可能遇到的技能问题。
- 过早完成 — 在某个步骤确实完成之前就结束,注意力滑向_准备就绪_。按以下顺序防范:先明确完成标准(成本低、影响局部);只有当它无可避免地模糊,_并且_你观察到 Agent 急于结束时,才通过拆分序列隐藏完成后的步骤(按序列拆分)。
- 重复 — 同一个意思出现在多个地方。这会增加维护成本和 token 消耗,并使某个意思在上方阶梯中的显著程度膨胀,超出其实际等级。
- 沉积 — 添加内容看似安全,删除内容却似乎有风险,于是过时内容层层堆积。缺乏清理纪律的技能最终都会走向这一结果。
- 臃肿 — 某项技能就是太长,即使每一行都有用且独一无二。这会损害可读性和可维护性,并浪费 token。解决办法是使用阶梯:通过指针将参考资料隐藏起来,并按分支或序列拆分,让每条路径只承载所需内容。
- 无效项 — 模型默认就会遵循某一行指令,因此你付出了加载成本,却什么也没说。测试方法:它会改变模型相较默认状态的行为吗?一个较弱的引导词(例如,当 Agent 本来就有点 thorough 时说_要 thorough_)就是无效项;解决方法是换一个更有力的词(relentless),而不是改用其他技巧。
- 否定 — 用禁止来引导会适得其反:_不要想大象_会点出大象,让它更容易浮现,而不是更难。提示积极的目标——明确说出目标行为,这样就无需提及禁止的行为;只有当某项禁令是无法用积极方式表达的硬性护栏时,才保留它;即便如此,也要同时说明应该怎么做。