写给 agent 看的任何文档的参考——一个 skill、一份 AGENTS.md / CLAUDE.md、一份被指针指向的 doc。打包方式不同,写法一致:同一组杠杆让每份文档可预测——agent 每次跑的是同一套过程,而不是产出相同的输出。
当你写的文档本身是一个 skill 时,frontmatter、调用方式选择、路由类 skill 这些 skill 专属的细节见 SKILL-MECHANICS.md;本 skill 只讲通用的写作杠杆。
上下文指针(context pointer)
上下文指针(context pointer) 是留在 agent 上下文里的一句引用,它指名某个上下文之外的材料,并编码了「何时去读它」的条件。一个 skill 的 description 就是一个指针;AGENTS.md 里指名某份文档的一行,也是同一个东西。决定 agent 何时触达材料的,是指针的措辞,不是它的目标——以及它有多可靠。一个必须触达的目标躲在一句弱措辞后面,就是一个 variance bug(不稳定触达缺陷):先把措辞磨尖(sharpen),只有当 sharpen 仍不够时才把材料 inline 进主上下文。
一个指针做两件事——说明材料是什么,并列出应当触发去读它的分支(branch,文档要处理的不同情况,所以不同运行会走不同路径)。常驻指针的每一个词在每一轮都在花成本,所以它比正文更该被狠删:
- 把引导词前置——指针正是在这里完成触发工作的。
- 一个分支一个 trigger。 把同一个分支换几个同义词写,那是一个分支写了两遍;合并它们,只保留真正不同的分支。
- 砍掉正文已经携带的身份信息。
两种负担(the two loads)
你加的每一份文档和每一个指针,都在花两种预算之一:
- 上下文负担(context load)——常驻材料压在 agent 上下文窗口上的成本:一行
AGENTS.md、一段 skill description、任何每轮都坐在上下文里、不论是否触发都在消耗 token 和注意力的东西。 - 认知负担(cognitive load)——压在人身上的成本:哪些文档存在、何时该去翻哪一个。人就是那个索引。这不是一个要最小化的成本——它是人类自主权的代价;把成本花在人类判断真正重要的地方,在判断不重要处去掉它。
只通过指针才能触达的材料,代价是省下了上下文负担、但付出了指针自身那一行的成本;完全没有指针的材料,则完全骑在认知负担上。
信息层级(information hierarchy)
一份文档由两类内容构成——步骤(steps,agent 按顺序执行的有序动作)和参考(reference,按需查阅的定义、规则、事实)——两者可以自由混合:全步骤(一份菜谱)、全参考(一次 review 的规则,也就是本 skill)、或两者皆有。核心决策是每一块放在**信息层级(information hierarchy)**的哪一级,这是一个按 agent 需要材料的紧迫程度排序的梯子:
- 文件内步骤(in-file step)——主层级:agent 要做什么,按顺序。
- 文件内参考(in-file reference)——按需查阅。常常是一组合理的平级并列(一次 review 的每条规则在同一级)——这是好的安排,不是坏味道。
- 外置参考(disclosed reference)——推到独立文件里,靠上下文指针触达,只在指针触发时才加载。范围从一个同目录下兄弟文件,到完全外部、可放在任何地方、任何文档都能指向的参考。
推得太少,顶部会膨胀;推得太多,你会把 agent 真正需要的材料藏起来。这种张力就是整个决策。
渐进披露(progressive disclosure) 是沿梯子向下的动作——移出主文件、藏到指针后面——好让顶部保持清晰可读。它主要不是 token 优化:它是保护层级的方式。分支是最好用的披露测试:把每个分支都需要的 inline,把只有某些分支才触达的推到指针后面。当一份文档有步骤时,本该披露的在文件内参考会埋住它们,让「去注意它们」变成抛硬币——这是一个 variance 杠杆,不只是可读性问题。
co-location 是文件内的配套:层级决定一块坐在多靠下,co-location 决定它一旦到位,谁坐在它旁边。把一个概念的定义、规则、注意事项放在同一个标题下,而不是散开,这样读其中一部分就会把它邻居一起带出来。检验标准:文档读起来应该像写给 agent 的文档——成组的内容就是这种读法;散开的内容不是。(这和重复不同:重复是把同一个意思在两处重写;散开是把一个意思碎在很多地方。)
sprawl 是这里典型的失败模式:一份文档就是太长,哪怕每一行都活着的、唯一的。注意力被多余的长度摊薄,每一行额外内容都是要多保持相关的一行。解药是梯子:把参考披露到指针后面,并按分支或顺序拆分,让每条路径只带它需要的。
步骤与完成标准(steps and completion criteria)
每一步都要以一个**完成标准(completion criterion)**收尾——告诉 agent 工作做完了的条件。两个属性让它成为杠杆:
- 清晰(clarity)——agent 能分清做完和没做完吗?模糊的边界(「理解到位了」)会诱发 premature completion(过早完成):在还没真做完时就结束这一步,注意力滑向「做完了」。前方还看得见的步骤——完成后的步骤(post-completion steps)——提供拉力;标准的清晰度是阻力。按序防守:先磨尖边界(局部、便宜);只有当它本质模糊且你确实观察到抢跑时,才通过拆分顺序把后面的步骤藏起来——而且隐藏只有跨过真实的上下文边界才有效(一次交接或一次子 agent 派发;一次 inline 调用会把后面的步骤留在上下文里,什么都没清掉)。
- 要求度(demand)——它要求多少。「每个被改的模型都交代清楚」在「列个改动清单」不要求的地方,逼出更彻底的工作。要求度驱动 legwork——agent 在工作里挖深的部分,藏在意而不是写成独立步骤——而且它不绑定步骤:「每条规则都应用了」绑定一整组平级参考,正如「每步都做完了」绑定一个序列,这就是为什么一份全参考文档仍然带着穷尽性门槛。
最强的标准既可检查又穷尽。
何时拆分(when to split)
把一份文档拆成两份,要花两种负担之一,所以只在切得值得时才拆:
- 按序列(by sequence)——拆一串步骤,其中完成后的步骤诱使 agent 抢跑它前面的那步。把它们移出视野,逼出当前任务上更多的 legwork。反过来也要当心:合并序列会把每步的后续步骤暴露给后面的内容,诱发 premature completion。
- 按调用(by invocation)——skill 专属,见
SKILL-MECHANICS.md。
引导词(leading words)
引导词(leading word) 是已经活在模型预训练里的一个紧凑概念,agent 跑这份文档时会用它思考(lesson、fog of war、tracer bullets)。作为 token 重复,绝不作为句子,它积累出一个分布式定义,用最少的 token 锚定一整片行为,靠调动模型已有的先验。自己造词也行,只要你定义清楚;但一个生造词调动不了任何先验——你用定义 token 付出的,一个预训练词是免费给的;先去够一个已有的词。
它在两处锚定。在正文里,执行(execution):这个词每次出现,agent 都去够同一套行为;在一组平级参考里,它把注意力聚焦到一类要找的东西上。在指针里,调用(invocation):当同一个词活在你的 prompt、你的文档、你的代码库里,agent 就把这共享语言连到材料上,更可靠地触达它。
找机会用引导词重构。一个在三处展开的三元组、一个花一整句去指一个想法的指针——每一段都在乞求坍缩成一个 token:
- 「fast, deterministic, low-overhead」→ tight(一个 tight loop)。
- 「一个你信得过的 loop」→ red——一个模糊的闸门变成一个二值的可观测状态(loop 在 bug 上变 red,或者不变)。
你赢两次:更少 token,以及给 agent 挂思考的一个更尖的钩子。假定每份文档都带着引导词能退休的重述——去把它们找出来。
否定(negation) 是这杠杆旁边的失败模式:用禁令来引导,会把被禁的行为拖进上下文,让它更可用,而不是更不可用。别去想大象,结果大象就是一切;否定是一个弱修饰符,被强激活的概念冲过去,所以禁令半读作「去做那件事」的指令。提示正面(positive)——陈述目标行为(「写单行注释」),这样被禁的那个从不被说出。一个禁令只有在你无法用正面表述、且作为硬护栏时才值得存在;即便如此,也要配上一个正面目标,好让注意力落在该做的事上。
删减(pruning)
- 让每个意思只有单一事实源(single source of truth):一个权威位置,这样改行为就是一处编辑。重复(duplication)——同一个意思出现在多于一个地方——既费维护又费 token,还把一个意思在层级上的分量吹过它真实的排名。(这是引导词的反面意外:引导词是故意重复 token,绝不重复意思。)
- 环境(environment) 也是一个事实源——
package.json的 scripts、配置文件、目录布局、--help输出——一份重述它的文档是一份缓存(cache):一份查找的副本,只有当查找很贵时才值得它的负载。缓存 agent 靠看找不到的东西:没写下来的约定、一个选择背后的理由、任何配置都不坦白的坑。把那种「一个文件、一条命令就能查到」的查找留给环境,那里它们不会过时。 - 逐行检查相关性(relevance):它还与文档做的事相关吗?一行会因为这任务从不相关(纯铺陈,或本该披露的一个分支)而失去相关性,也会因为行为或它描述的世界变了而变陈旧。更短的文档更容易保持相关。没有删减纪律,默认命运就是 sediment(沉积):因为「加」显得安全、「删」显得冒险而沉淀下来的陈旧层,直到你必须挖穿它们才能找到还活着的。
- 逐句找 no-ops(空操作):一条模型默认就已经遵守的指令,说了等于没说,白费负载。检验——相比默认,它改变了行为吗?——是模型相对的,不是读者相对的:两个人就一个 no-op 吵架,吵的是默认是什么,该靠跑这份文档来解决,不是靠辩论。当一句话没过时,删掉整句,而不是从里面抠字。这个检验也给引导词打分:一个弱到打不过默认的词(agent 已经挺 thorough 了,你还写 be thorough)就是个 no-op,解药是一个更强的词(relentless),不是另一种技巧。