name: writing-great-skills
description: 写作和编辑高质量 skill 的参考:提供让 skill 行为更可预测的词汇和原则。
disable-model-invocation: true

Skill 存在的目的,是从随机系统中争取确定性。可预测性 指 Agent 每次运行时采用同一种过程,而不是产出同样的文本。下面所有杠杆都服务于这个目标。

加粗术语 的完整定义应放在 GLOSSARY.md 中;当你不确定术语边界时,先查术语表再修改 skill。

Invocation

先决定这条 skill 由谁触发。两种选择花费不同成本:

  • Model-invoked skill 保留 description,这样 Agent 可以自动触发它,其他 skill 也可以触达它;用户仍然可以手动点名。代价是 context load:description 会在每轮对话里占用上下文窗口和注意力。机制上,不设置 disable-model-invocation,并写面向模型的 description,包含明确触发措辞,例如 “Use when the user wants…” 或 “Use when the user mentions…”。
  • User-invoked skill 对 Agent 隐形,只能由用户输入名称触发,其他 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 只列出其他 user-invoked skills 以及什么时候该用它们。

Writing the description

model-invoked 的 description 有两个职责:说明这条 skill 是什么,以及列出哪些 branches 应该触发它。description 中每个词都会增加 context load,所以它比正文更需要修剪:

  • 把 leading word 放在前面:description 是 leading word 发挥 invocation 作用的地方。
  • 每个 branch 只保留一个 trigger:同义词如果只是重命名同一个 branch,就是 duplication。例如 “build features using TDD” 和 “asks for test-first development” 通常是同一个 branch 写了两遍。合并它们,只保留真正不同的触发分支。
  • 删除正文里已经说明的身份信息:description 只保留触发条件,以及必要的 “when another skill needs…” 触达说明。

不要把 description 写成正文流程摘要。description 负责触发 skill,不负责替代 SKILL.md

Information hierarchy

Skill 由两类内容构成:stepsreference。它们可以自由组合:一条 skill 可以全是 steps、全是 reference,也可以两者都有。核心决策是:使用哪类内容,以及它们位于 information hierarchy 的哪一层。

信息层级按 Agent 多快需要这些材料排序:

  1. In-skill step:写在 SKILL.md 里的有序动作,是最高优先级。它告诉 Agent 按什么顺序做什么。每个 step 都应结束于 completion criterion,即判断该步骤完成的条件。completion criterion 要尽量可检查,必要时要穷尽。例如 “every modified model accounted for” 比 “produce a change list” 更强;模糊标准会诱发 premature completion
  2. In-skill reference:写在 SKILL.md 里的定义、规则或事实,供 Agent 按需查阅。它可以是平铺的同级规则集,例如 review skill 中每条规则都同等重要。平铺不一定是坏味道。writing-great-skills 本身就是全 reference 型 skill。
  3. External reference:从 SKILL.md 拆到单独文件里的参考内容,通过 context pointer 触达,只在 pointer 触发时加载。它可以是同目录下的 GLOSSARY.md,也可以是 skill 系统外的普通参考文件。

强 completion criterion 会驱动更充分的 legwork。这不只适用于步骤型 skill;即使是平铺 reference,只要要求“每条规则都应用”,也会驱动 Agent 做更多幕后工作。

放下去太少,SKILL.md 顶部会臃肿;放下去太多,又会隐藏 Agent 实际需要的材料。这个张力就是 information hierarchy 的核心决策。

Progressive disclosure 是把 reference 沿层级往下移动:从 SKILL.md 移到链接文件里,让顶部保持清晰。机制上,在 skill 目录里放一个命名明确的 .md 文件,例如把完整术语定义放到 GLOSSARY.md

一条 skill 可能有多种使用方式;每种不同使用方式就是一个 branch。branch 是最干净的 disclosure 判断标准:每条 branch 都需要的内容留在正文,只有某些 branch 需要的内容放到 pointer 后面。Context pointer 的措辞,而不是目标文件本身,决定 Agent 什么时候以及多可靠地读取该材料。

如果 information hierarchy 决定一块内容放多深,那么 co-location 决定它和谁放在一起:一个概念的定义、规则和 caveats 应放在同一个标题下,不要散落在文件各处。

When to split

Granularity 是 skill 拆多细的问题。每次拆分都会花掉两种负载之一,所以只有拆分收益明确时才拆。

有两种拆法:

  • 按 invocation 拆:当你有一个独立 leading word 应该触发某条 model-invoked skill,或另一个 skill 必须能触达它时,拆出一条 model-invoked skill。代价是新的 description 会常驻上下文,增加 context load;独立触达必须值得这个成本。
  • 按 sequence 拆:当一个步骤后面的 post-completion steps 会诱导 Agent 匆忙结束当前步骤,即发生 premature completion,就把步骤序列拆开。让后续步骤不在当前上下文里,可以促使 Agent 在当前任务上投入更多 legwork

拆分不是为了形式上的模块化,而是为了控制 context load、cognitive load 和 premature completion。

Pruning

每个含义都应该有一个 single source of truth:只有一个权威位置。这样修改行为时,只需要改一个地方。

逐行检查 relevance:这一行是否仍然服务于这条 skill 要做的事?

然后逐句猎杀 no-ops,不要只按行检查。把每个句子单独拿出来做 no-op 测试:它会改变模型相对于默认行为的表现吗?如果不会,删除整句,而不是试图修饰它。要激进一点;大多数 no-op prose 应该被删除,不是被改写。

Leading words

Leading word 是一个模型预训练中已经熟悉的紧凑概念,Agent 在运行 skill 时会用它来思考。例如 lessonfog of wartracer bullets。它可以在很少 token 内编码一个行为原则,因为它借用了模型已有先验。

leading word 通过重复出现积累分布式定义,锚定一整片行为区域。它不一定必须重复很多次;足够强的 leading word 可能出现一次就够。

它服务可预测性两次:

  • 在正文里,它锚定 execution:每次这个词出现,Agent 都会回到同一类行为。
  • 在 description 里,它锚定 invocation:当同一个词出现在用户提示、文档和代码库里,Agent 更容易把这个共享语言和 skill 连接起来,更可靠地触发 skill。

主动寻找能用 leading word 重构 skill 的地方。一个意思被三个句子反复解释,或者 description 花一整句模糊指向某个概念,通常都可以压缩成一个 token。

例子:

  • “fast, deterministic, low-overhead” 可以压成 tight,例如 a tight loop。
  • “a loop you believe in” 可以压成 red,把模糊门禁变成可观察的二值状态:这个循环有没有在 bug 上变红?

收益有两个:更少 token,以及更锋利的思考挂钩。假设每条 skill 都带着可以被 leading word 替代的重复说明,然后去找它们。

Failure modes

用这些失败模式诊断用户在使用 skill 时遇到的问题。

  • Premature completion:当前步骤还没真正完成,Agent 的注意力就滑向“已经完成”。防御顺序:先锐化 completion criterion,因为这是局部且便宜的修复;只有当标准无法再清晰、且你确实观察到 rushing 时,才通过拆分隐藏 post-completion steps。
  • Duplication:同一个含义出现在多个地方。它增加维护成本和 token 成本,还会把这个含义在信息层级中的权重抬得过高。
  • Sediment:旧内容因为“添加安全、删除危险”而沉积下来。没有修剪纪律的 skill 默认都会出现 sediment。
  • Sprawl:skill 单纯太长,即使每一行都还有效、也不重复。它损害可读性、可维护性并浪费 token。解决方法是使用 information hierarchy:把 reference 放到 pointer 后面,并按 branch 或 sequence 拆分,让每条路径只携带需要的内容。
  • No-op:模型默认就会遵守的句子。你付出了 load,却没有改变行为。测试方式是:这句话会改变模型相对于默认行为的表现吗?弱 leading word 也可能是 no-op,例如当模型本来就会稍微认真时,be thorough 并不会增加多少约束;修复方式是换成更强的词,例如 relentless,而不是换一种技术。

Glossary:好 Skill 的术语模型

什么样的 skill 才算好,这里给出它的领域模型。skill 的目的,是从随机系统中尽量拽出确定性;下面每个术语,都是作用在这个目标上的一个杠杆。这是 writing-great-skills 所披露出来的参考文件。

任意定义里的 加粗术语,也都在这个 glossary 中有自己的条目;按标题查找即可。

Language

Predictability(可预测性)

一条 skill 让 Agent 在每次运行时都以同一种 方式 行动的程度。这里的一致性指的是过程一致,而不是输出一致。比如 brainstorming skill 应该“可预测地发散”:每次 token 可以不同,但行为模式应该稳定。它是其他所有术语共同服务的根目标;成本和可维护性只是它的外在症状,不是与它并列的竞争目标。

Avoid: consistency, reliability, robustness, output-determinism

这里的 _Avoid_ 不是“这些词绝对不能出现”,而是“不要把它们当成 Predictability 的同义替代词”,因为它们会把“过程稳定”误带成“系统可靠”或“输出确定”。后文类似。

Model-Invoked(模型触发型)

保留 description 字段的 skill。这样 Agent 能看见它并自主触发,人也仍然可以手动输入它的名字,所以 model-invocation 总是包含用户可达。不存在“只有模型能用、用户反而不能用”的状态:description 只会增加 Agent 的发现能力,不会减少人的触达能力。它用永久性的 context load 换来可发现性。它也可以被其他 skill 触达,因为 description 让它对 Agent 可发现,也就对 skill 可调用。一个内容全是 reference 的 model-invoked skill,还可以作为共享参考的归宿:多个 skill 需要的参考,可以放在这一个可调用的地方。只有在 Agent 必须能自己想到这条 skill 时,才选择 model-invocation;如果它永远只会被手动调用,就删除 description,不支付 context load。

Avoid: ability, tool, capability

User-Invoked(用户触发型)

去掉 description 的 skill。它对 Agent 不可见,只能由人手动输入名称来触发。所以 user-invoked 是“只有用户能触达”,而 model-invoked 是“用户和模型都能触达”。它用放弃 Agent 可发现性来换取零 context load。因为没有 description,除了人之外没有东西能触达它:其他 skill 也无法自动触发它。

Avoid: procedure, workflow, command

Description

skill 的机器可读触发器,也是 model-invoked skill 被迫始终加载在上下文中的那个 context pointer。它的存在本身就是 invocation 轴:保留它,skill 就是 model-invoked;删掉它,skill 就是 user-invoked,只能由人触达。它也是 model-invoked skill context load 的来源。

Avoid: frontmatter, summary

Context Pointer

一种保留在 Agent 上下文里的指针:它指向上下文外的材料,并编码“什么时候该去读它”的条件。Description 是最上层的 context pointer(从上下文窗口指向 skill);指向披露文件的链接,是同一种对象在下一层的表现。真正决定 Agent 什么时候去读、以及读得是否可靠的,不是目标文件,而是 pointer 的措辞。一个必须读取的材料,如果被放在措辞很弱的 pointer 后面,就是方差 bug:先修 pointer 的写法,只有在写法强化仍然无效时,才把材料重新内联回正文。

Avoid: link, reference, import

Context Pointer 强调的是“指向 + 触发条件 + 读取可靠性”,而 link/reference/import 都只抓到其中一部分。

Context Load

Model-invoked skill 对 Agent 上下文窗口施加的成本。它的 description 会在每一轮都被加载,持续消耗 token 和注意力。User-invoked skill 正是通过没有 description 来逃避这种成本。它也是“是否继续拆成更多 model-invoked skills”的制动器。

Avoid: token cost, context bloat

  • token cost 说得太窄,只讲数量
  • context bloat 说得太偏结果,只讲臃肿
  • Context Load 讲的是 持续占用上下文窗口的整体负担:token + 注意力

Cognitive Load

User-invoked skill 加在人身上的成本:用户必须在脑中记住有哪些 skill、什么时候该用哪一个,也就是“人自己当索引”。这正是 model-invocation 帮用户拿掉的负担,也是“是否继续拆成更多 user-invoked skills”的制动器。它不是要被一味最小化的成本:它本身就是人类能动性的价格。有些地方必须保留人的判断,就应该花这笔 cognitive load;不需要人的地方,才应该尽量移除。

Avoid: human index, burden, overhead

Granularity(粒度)

skill 拆得有多细。拆得越细,就越会花掉两类负载中的一类:更多 model-invoked skills 会增加 context load,因为更多 description 会常驻上下文并争夺注意力;更多 user-invoked skills 会增加 cognitive load,因为用户要记住更多东西。拆分主要有两种依据。按 invocation 拆:当你有一个清晰的 leading word,并且你确实会在提示词里用它来触发 skill,就可以把它拆成独立的 model-invoked skill。按 sequence 拆:当一串 steps 里的某一步后续内容必须被隐藏时,就应该拆开,因为把它隔离进自己的上下文,能让后面的东西暂时消失。也要小心反过来:把多个 sequence 合并,会让每个步骤都暴露在后续 post-completion steps 面前,从而诱发 premature completion。

Avoid: chunking, modularity

Router Skill

一种 user-invoked skill,它的职责是指向其他 user-invoked skills:列出它们是什么、什么时候该用哪个。这样用户只需要记住一个 skill,而不是很多个。它只能提示,不能真正触发那些 skill,因为 user-invoked skills 没有 description,除了人之外没人能触达它们。当 user-invoked skills 多到难记时,router skill 就是解决 cognitive load 的办法。

Avoid: dispatcher, menu, registry, index, router procedure

Information Hierarchy(信息层级)

skill 内容按“Agent 多快需要它”排序后形成的层级。它由两次切分共同决定:内容是在文件内,还是放到 pointer 后面;内容是 step,还是 reference。层级从上到下是:

  • Steps:文件内,主层
  • 文件内的 Reference:次层
  • 被披露到 pointer 后面的 Reference

一条没有 steps 的 skill,只使用下面两层,而且这通常完全合理。例如 review skill 中的所有规则都可以平铺在同一层上,这不是坏味道。信息层级和 invocation 是独立的:一条 skill 无论是 model-invoked 还是 user-invoked,都可以是全 steps、全 reference,或两者兼有。真正有步骤的 skill,如果把本该披露下去的 reference 留在文件内,就会把 steps 埋住,让 Agent 是否注意到它们变成掷硬币,这不只是可读性问题,而是方差来源。顶部必须保持清晰,能往下推的内容就尽量推下去。

作用:首先是保护注意力,让Agent专注重要步骤;其次是token 优化。

Avoid: structure, organization, layout

Co-location(共置)

把 Agent 在同一时刻需要一起读的东西放在一起。比如一个概念的定义、规则和 caveats 放在同一个标题下,而不是散落在不同段落里。它是 Information Hierarchy 在文件内部的配套原则:hierarchy 决定一块内容放多深,co-location 决定它和什么放在一起。reference 没有固定的唯一格式,判断标准是:这份 skill 读起来是否像一份写给 Agent 的文档。该放在一起的内容放在一起时,它会更像;分散时就不像。它和 Duplication 不同:duplication 是同一个意思重复了两遍;scattering 是同一个意思被拆散到很多地方。

Avoid: grouping, clustering, cohesion

Branch

skill 被调用的一种不同方式,也就是它要处理的一个分支。不同 branch 会让 skill 在不同运行中走不同路径。一条带很多步骤的 skill 可能有很多 branch;完全线性的 skill 则可能没有。

Avoid: path, case, fork

Progressive Disclosure(渐进披露)

reference 沿着层级往下移动:从 SKILL.md 挪到 context pointer 后面,让顶部保持清晰。它首先不是一种 token 优化,而是保护 information hierarchy 的办法。它的许可条件来自 branching:只有部分 branch 需要的材料可以披露下去;每条路径都需要的材料要留在正文里。如果某个必须读取的材料放在 pointer 后面却总是触发不稳,先强化 pointer 的措辞,只有失败后才把材料重新拉回正文。

Avoid: lazy loading, chunking

Steps

Agent 需要按顺序执行的动作。如果一条 skill 有 steps,它们就是正文里的主层内容,也是它真正值得放进 SKILL.md 的部分。不是所有 skill 都必须有 steps:一条 skill 可以全是 steps(如 tdd),全是 reference(如一条 review skill),也可以两者兼有,而这与 invocation 无关。每个 step 都会结束在一个 completion criterion 上,无论这个 criterion 是清晰还是模糊。

Avoid: workflow, instructions, choreography

Completion Criterion

告诉 Agent 一段工作何时算完成的条件,也就是它判断 done 与 not-done 的依据。它有两个真正起作用的属性。第一是 清晰度:Agent 能不能判断什么时候完成?它用来抵抗 premature completion。模糊边界例如“理解到了”会让 Agent 很容易自认完成并滑到下一步;这条作用只在存在 steps 时才成立,因为 premature completion 是 steps 之间的失败。第二是 要求强度:它要求 Agent 做多少 legwork。例如“每个修改过的 model 都交代清楚”会迫使 Agent 做扎实工作,而“列出改动清单”就不会。这个维度不依赖 steps:它也可以约束一组平铺的 reference,因此一条没有 steps 的 skill 仍然可以有穷尽性要求,例如“每条规则都应用”。最强的 completion criterion 同时具备可检查性和穷尽性。

Avoid: done condition, exit condition, stopping rule

Post-Completion Steps

当前步骤之后还没开始的那些 steps。只要它们可见,就会把 Agent 的注意力往前拉,诱发 premature completion。看到的后续越多,拉力越强;防御方式是通过拆 sequence 把后续步骤藏起来。

Avoid: horizon, fog of war, lookahead

Legwork

Agent 在单个步骤内部做的幕后工作,例如读文件、探索代码库、实际改代码、自己挖出需要的信息,而不是把这些工作转嫁给用户。它存在于步骤结构之下:不应该被单独写成 step,而是隐含在措辞里,由 Agent 主导而不是由 skill 直接编排。它是 post-completion steps 那种“跨步骤拉力”在步骤内部的对应物。它会被更强的 leading word 拉高,也会被更强的 completion criterion 拉高,包括那种作用在平铺 reference 上的穷尽性要求。它会变薄,要么因为要求本来就弱,要么因为 premature completion 提前把步骤截断了。

Avoid: scope, effort, diligence, coverage

Reference

Agent 按需查阅的材料:定义、事实、参数、例子、条件指令等。如果 skill 有 steps,reference 是次层;如果没有 steps,reference 就是全部内容;或者它甚至可以完全在 skill 系统外,这就是 External Reference。reference 通过 context pointers 被触达,也是 progressive disclosure 最该处理的对象。

Avoid: supporting material, docs, background

External Reference

存在于 skill 系统之外的 reference:一个普通文件,没有 description,没有 steps,也不可被调用,但任何 skill 都可以指向它。它适合承载那些不需要自己独立触发、但可能被多条 skill 共享的参考内容。对于两条 user-invoked skills 来说,它也是唯一可共享的归宿,因为它们彼此都没有 description,不能互相调用。

Avoid: doc, resource, knowledge base

Leading Word

一个紧凑的概念,也可理解为 Leitwort。它最好已经存在于模型预训练中,因此 Agent 在运行 skill 时能直接“借用”它来思考。例如 lessonproximal zone of developmentfog of wartracer bullets。它用最少的 token 编码一个行为原则,因为它调用了模型已有的先验。leading word 应该重复为“词”,而不是重复为整句解释;这样它会在全文中逐渐积累起分布式定义,锚定一整片行为区域。你当然也可以自己造词,只要定义得足够清楚;但造词无法借用现成先验,会把原本可以白拿的语义改成你必须自己付 token 去解释的成本,所以优先选已有词。

leading word 会双重服务 predictability。在正文里,它锚定 execution:每次这个概念出现,Agent 都更容易回到同一类行为;即使在一堆平铺的 reference 里,它也能把注意力聚焦到同一类检查点上。在 description 里,它锚定 invocation:而且不只是 skill 内部。当同一个词同时出现在你的 prompt、文档和代码库里,Agent 更容易把这套共享语言和 skill 对上。description 最好也使用你平时真的会说出来的 leading words。

Avoid: keyword, term, motif

Single Source of Truth

理想状态是:每个含义都只有一个权威位置。这样你要修改 skill 行为时,只改一处即可。Duplication 就是对这个状态的破坏。

Avoid: home, canonical location

Relevance

一行内容是否仍然服务于这条 skill 要做的事。这是判断该保留什么的镜头。失去 relevance 有两种方式:要么一开始就没真正服务任务,只是多余解释,或者是本该披露下去的 branch;要么它曾经相关,但后来过期了。skill 越短,越容易保持 relevant,因为每一行都更便宜复查。它和 no-op 不同:relevance 判断的是“是否相关”,不是“是否真的改变了行为”。

Avoid: load-bearing, staleness, freshness

Failure Modes

Premature Completion

当前步骤还没真正完成,Agent 的注意力就已经滑向“尽快完成”。这是 steps 之间的失败:没有 steps 的 skill 如果提前停下,不叫 premature completion,而叫在要求不足时出现的薄 legwork。它是两股力量的拉扯结果:一边是可见的 post-completion steps 往前拉,另一边是 completion criterion 的清晰度在往后稳住。模糊边界是必要条件:一个锋利、可检查的边界可以抵抗后续拉力,无论后面还暴露了多少步骤。所以防御顺序必须是:先锐化 completion criterion,因为这便宜而且局部;只有当这个边界真的无法再清晰,而且你也确实观察到 rushing 时,才去 隐藏后续步骤。而隐藏只有跨越真实的上下文边界才有效,例如交给一个 user-invoked hand-off 或 subagent;内联的 model-invoked 调用不会让后续步骤真的消失。它是导致薄 legwork 的一种原因,但两者并不等价:就算一个步骤完整跑完,legwork 也可能仍然很薄。

Avoid: premature closure, the rush, rushing, shortcutting

Duplication

同一个含义有不止一个 single source of truth。它会增加维护成本,因为你改一处就得改所有重复处;也会增加 token 成本;还会错误抬高这个含义在信息层级中的权重。它正好和 leading word 相反:leading word 是为了有意提高一个概念的注意力,而 duplication 是无意间把同一个意思写了两次。

Avoid: repetition, redundancy

Sediment

旧内容像沉积层一样堆在 skill 里不再被清理。因为添加看起来安全,删除看起来危险,于是过时和不相关的内容一层层沉下来。没有修剪纪律的 skill,默认都会走向 sediment。它是 relevance 被长期侵蚀后的状态,而不是 duplication 那种简单的重复。

Avoid: accretion, bloat, cruft, rot

Sprawl

skill 单纯太长了。即使每一行都还活着、每一行都不重复,它依然可能 sprawl。它会损害可读性,因为 Agent 在行动前得先穿过更长的正文,注意力也会被拉薄;会损害可维护性,因为每多一行就多一行要保持 relevant;也会浪费 token。解决方法是用 information hierarchy:把 reference 放到 context pointers 后面,并按 branch 或 sequence 拆分,让每条路径只携带它真正需要的内容。它不同于 sediment(长度来自沉积)和 duplication(长度来自重复);sprawl 是“长度本身”。

Avoid: bloat, length, size, verbosity

No-Op

一条不会改变任何行为的指令,因为模型默认就会这么做。你为它支付了 load,却没有得到行为增量。判断方法是:相对于默认行为,这一行真的改变了什么吗?一条内容可以完全 relevant,却仍然是 no-op。让 leading word 能白嫖先验的同一套模型特性,也让 no-op 变得毫无价值。

leading word 是一种 技术,No-Op 是对一行内容的 判决;两者会交叉。一个太弱的 leading word 也可能是 no-op,例如当模型本来就已经“有点认真”时,be thorough 没有带来新的约束;修复方式不是换技术,而是换成更强、真正能通过 no-op 测试的词,例如 relentless。所以 no-op 测试同时也是在检验 leading word 是否值得它那几次重复。它是模型相对的,而不是读者相对的:两个人如果争论一行是不是 no-op,本质上是在争论“默认行为是什么”,这要通过运行 skill 来验证,而不是靠辩论。

Avoid: redundant instruction, restating the obvious, belaboring

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐