🐎 第3章 授人以渔:Skills 工程实践
📄 一句话概括

正文是触发时才读的那一段,它要回答的是「现在做哪几件事」,不是「这件事是什么」。 同样的信息,放正文还是放 refs,差别在于这一次执行用不用得上。用不上的,指个路就行。

📝 本章和前面几章的关系

上一节讲描述怎么被选中,这一节讲选中之后读到的那一段。 两份样本写的是同一件事(部署自检),一份七百 token,一份两百七十五, 动作条数一样多——差别全在「有没有讲背景」。

一、路由器思维

把正文想成一张路由表:它不承载内容,它决定内容从哪来。 路由表该有的是:这次要做哪几件事、每件事用什么命令、做完怎么判断、要深究时去哪份文件看。 它不该有的是:这件事的历史、为什么这样设计、业界通常怎么做、三个对比方案的优劣。

判断标准很直白:这一次执行需不需要它。不需要的,写一句「为什么这么定,见某文件」, 把选择权交出去。 演示里仓库式那份就是反面教材:二十三行、七百 token, 把「迁移是什么」「环境变量分几类」「回滚怎么验证」都讲了一遍。 这些都对,但技能被触发的那一刻,模型要的是「现在做哪三件事」。信息没错,错在位置。

二、契约式引用

「详见文档」这四个字是没用的:模型不知道是哪份文档,也不知道该不该去读。 契约式引用要给三样:具体文件路径、这份文件里有什么、什么情况下该去读。 比如「为什么只查这三项,见 docs/runbook/deploy.md 的第一节」。 路径明确、内容明确、条件也隐含了(想知道原因才去)。

演示里路由式那份有四处这样的引用,正文只有十四行。十四行读起来比二十三行省,但该知道的都在。 引用的粒度也要控制:指到文件,不要指到目录。「见 docs 目录」等于没说。

三、500 行法则

正文越长,触发时的成本越高。 按一行二十来个 token 估:八十行约一千七,两百行约四千四,五百行约一万一千,一千二百行约两万六。 而一次任务真正执行到的步骤,通常还是那三五步,不随总长变。所以行数涨的是分母,分子没动。 五百行这条线的意思是:到这个体量,正文里多半装了两三个不同的流程,该拆开了。

注意它是经验线,不是硬限制。 一份参考型技能的正文可以很短,但 refs 可以几千行——refs 不常驻,也不在触发时全读。 反过来说,任务型技能正文超过五百行,几乎一定是把「判断」写进「流程」了。 流程该是一条线走到底的,岔路一多就说明它其实是两三个技能。

四、三份正文放在一起看

三份写的都是部署自检:一份讲背景和原则,一份只给步骤,一份在中间——有步骤,也留了背景。 仓库式:二十三行、七百零七 token、零条步骤、零条命令。读完知道很多,但不知道现在干什么。 路由式:十四行、二百七十五 token、三步、五条命令、四处外链。动作最全,字数反而不多。

折中式:九行、一百三十九 token、三步、三条命令、一处外链。看着平衡,其实两头不靠。 折中式是很多人的默认写法,问题不大。 它的好处是自解释,坏处是每次触发都要多读一段背景,而那段背景九成情况用不上。

五、该拆的时候怎么拆

拆的判据不是行数,是这些内容会不会在同一次任务里一起用到。 不会一起用到的,就是该拆的地方。 比如「部署自检」和「回滚演练」:前者在上线前跑,后者在出事时跑,永远不在同一次任务里。 拆完之后,父技能变成一张路由表:上线前走这边,出事走那边。子技能各管一段流程。

这就是 3.9 节要讲的复合型技能:第一段是路由器,后面各自引用一份 refs。 所以 500 行法则的真正含义不是「别写太长」,是「写到五百行的时候,回头看看里面是不是装了两件事」。

六、动手 Demo:同一件事的三份 SKILL.md:一份像仓库,一份像路由

三份写的都是部署自检,内容来自真实项目的三种常见写法。 逐份数四个指标:行数、编号步骤数、带命令的步骤数、外部引用数,再算 token。

for nm, body in [(u"仓库式", BODY_STORE), (u"路由式", BODY_ROUTE),
                  (u"折中式", BODY_MID)]:
    lines = body.strip().split(u"\n")
    steps = len(re.findall(r"^\d+\. ", body, re.M))   # 编号步骤
    cmds  = len(re.findall(r"`[^`]+`", body))           # 行内命令
    links = len(re.findall(r"docs/\S+", body))          # 外部引用
    print(nm, len(lines), steps, cmds, links, tokens(body))

实跑输出:

--------------------------------------------------------------------
同一件事的三份 SKILL.md:一份像仓库,一份像路由
--------------------------------------------------------------------

  三份写的都是部署自检。第一份讲背景和原则,第二份只给步骤,第三份在中间——有步骤,也留了背景。
| 写法 | 正文行 | 步骤 | 带命令 | 外链 | token |
|---|---:|---:|---:|---:|---:|
| 仓库式 | 23 | 0 | 0 | 1 | 707 |
| 路由式 | 14 | 3 | 5 | 3 | 275 |
| 折中式 | 9 | 3 | 3 | 1 | 139 |


  ① 仓库式:读完知道很多,但不知道现在干什么
  --------------------------------------------------------------------
  23 行、707 token,步骤 0 条、带命令 0 条。
  它把「迁移是什么」「环境变量分几类」「回滚怎么验证」都讲了一遍。
  这些都对,但技能被触发的那一刻,模型要的是「现在做哪三件事」。
  ! 信息本身没错,错在位置。背景知识该在文档里,技能正文只放【现在要做的动作】。

  ② 路由式:动作最全,字数反而不多
  --------------------------------------------------------------------
  14 行、275 token,步骤 3 条、带命令 5 条、外链 3 处。
  它比仓库式短四成、token 只剩四成,但三步全在,每一步都带判据、带命令。
  最后两行只有一句话形式:「为什么只查这三项,见 docs/runbook/deploy.md」。
  这就是路由:把想深究的人(或者模型)指到外面去。

  ③ 折中式:看着平衡,其实两头不靠
  --------------------------------------------------------------------
  9 行、139 token。步骤齐了,也留了一句「为什么」。
  这一份是很多人的默认写法,问题不大。
  它的好处是自解释,坏处是每次触发都要多读一段背景——而那段背景百分之九十的情况用不上。
  ! 判断标准不是「读起来顺不顺」,是「这一次执行需不需要它」。不需要的,指个路就行。

  ④ 500 行这条线是怎么来的
  --------------------------------------------------------------------
  正文越长,触发时的成本越高。按一行二十来个 token 估:
| 正文长度 | 约 token | 相对 |
|---|---:|---:|
| 80 行 | 约 1760 | 1.0 |
| 200 行 | 约 4400 | 2.5 |
| 500 行 | 约 11000 | 6.2 |
| 1200 行 | 约 26400 | 15.0 |

  而一次任务真正执行到的步骤,通常还是那三五步,不随总长变。所以行数涨的是分母,分子没动。
  五百行大约一万一千 token。如果一份技能写了五百行,说明它多半在装两三个不同的流程,该拆开了。
  拆的判据不是行数,是这些内容会不会在同一次任务里一起用到。不会一起用到的,就是该拆的地方。

①仓库式:二十三行、七百零七 token,步骤零条、命令零条、外链一处。 它的内容没错,讲清了迁移、环境变量、回滚验证。问题是这些内容在「现在动手」这个时刻用不上。 ②路由式:十四行、二百七十五 token,三步、五条命令、四处外链。 比仓库式短四成、token 只剩四成,但三步全在,每步都带判据、带命令。 最后两行是一句话形式的引用:「为什么只查这三项,见 docs/runbook/deploy.md」。 这就是路由——把想深究的人指到外面去。 ③折中式:九行、一百三十九 token。步骤齐了,也留了一句「为什么」。 它是多数人的默认写法,问题不大。代价是每次触发多读一段背景,而那段背景九成用不上。 判断标准不是「读起来顺不顺」,是「这一次执行需不需要它」。 ④500 行那段表把成本量化了:八十行一千七、五百行一万一、一千二百行两万六。 而真正执行到的步骤永远是那三五步。 所以行数涨的是分母,分子没动。五百行这条线是提醒:到这个体量,里面多半装了两三个不同的流程。

30 秒实验

  1. 把仓库式那份砍掉所有背景段落,只留步骤和引用,重跑一遍。行数降到多少、token 降到多少? 哪些内容被砍掉了?
  2. 给路由式再加一条步骤(比如「核对监控告警是否已配置」),token 涨多少? 这说明正文长度和步骤数是线性关系吗?
  3. 把 refs 里的 checklist.md 内容直接搬进正文,重算 token。触发一次的代价涨几倍? 这份内容真的每次都要读吗?

常见误区

  1. 把正文写成项目文档:背景、原则、概念、示例。触发时读的是执行说明,不是读物。
  2. 写「详见文档」却不给路径。模型不知道是哪份、也不知道该不该读,等于没写。
  3. 把 500 行当成硬性红线,为了凑行数把必要步骤删掉。它是提醒你「里面可能装了两件事」。
  4. 为了「自解释」保留大段背景。自解释是给人的,模型需要的是「这次做什么」。
  5. 正文和 refs 放同样的内容。同一份知识存两遍,改的时候必漏一处。
自测三问(点开对答案) 1. 为什么说正文是「路由器」? —— 因为它不承载内容,它决定内容从哪来:这次做哪几件事、用什么命令、要深究时去哪份文件。 2. 契约式引用要给哪三样东西? —— 具体文件路径、这份文件里有什么、什么情况下该去读。只说「详见文档」等于没说。 3. 500 行法则的真正含义是什么? —— 不是「别写太长」的硬限制,而是一个提醒:写到这个体量,正文里多半装了两三个不同的流程, 该按「会不会在同一次任务里用到」拆开。

形状讲完了,下一节讲那个能直接限制行动的字段:allowed-tools。

相关笔记