当前位置:首页 > 编程开发 > 正文

扫了 83 个 Skill,七成有问题:坏得最多的是引用,不是长度

约 4901 字 · 预计阅读 13 分钟
一句话总结:我给 Skill 写了个 lint,扫了本机 83 个,58 个有问题,占七成。反直觉的地方在于分布:引用断链 36 个(43%)、description 没写触发语 33 个(40%),而大家最担心的「正文写太长」只有 5 个(6%)。真正让 Skill 失效的不是臃肿,是断链和不触发。

一、Skill 写多了会烂,但烂在哪

单看一个 Skill,很难出问题。目录对、frontmatter 齐、正文写清楚,就能用。

问题出在数量和时间的乘积上。写到十几个之后,会出现三种情况:改了正文忘了改脚本、引用了后来被删掉的文件、description 当初随手写的一句话到现在也没动过。

这些问题的共同点是不会立刻报错。Skill 加载成功、格式合法、Agent 也读到了,只是在你需要它的时候不触发,或者触发后按着一条死路去走。

所以我做了个 lint。思路和代码检查一样:别靠人记,靠工具扫。

二、三个检查维度

格式层。 frontmatter 能不能解析、name 和 description 在不在、name 和目录名是否一致。这一层是硬性要求,错了加载就会出问题。

匹配层。 description 的长度是否合理、有没有写清楚"什么时候用"。这一层决定 Skill 会不会被触发,最容易被忽略。

内容层。 正文 token 估算是否超标、正文里引用的本地文件是否存在。这一层决定触发之后能不能跑通。

TRIGGER_HINTS = ("当", "时使用", "使用时", "when", "use ", "Use ",
                 "适用于", "用于", "务必", "确保")

def est_tokens(text):
    """粗估:中文按 1.5 字符/token,英文按 4 字符/token"""
    cjk = len(re.findall(r"[\u4e00-\u9fff]", text))
    other = len(re.sub(r"\s", "", text)) - cjk
    return int(cjk / 1.5 + other / 4)

token 估算用的是经验系数,不追求精确,只要能把"三千还是三万"分出来就够用。

三、真实数据

扫的是本机 skills 目录,83 个 Skill。

Skill 总数:83
存在问题:58 个(70%)

按问题类型(同一 Skill 可命中多类):
  引用断链         36 个(43%)
  description 缺触发语 33 个(40%)
  正文超 5k token  5 个(6%)
  格式问题         11 个(13%)

正文 token 中位数:1633
正文 token 最大:14187
只有 SKILL.md、没有任何附件的:41 个(49%)

扫了 83 个 Skill,七成有问题:坏得最多的是引用,不是长度

图 1:断链和触发语缺失占了绝大多数,长度反而是小问题

四、三个反直觉的结论

结论一:长度不是主要矛盾。

官方的建议是正文不超过 5,000 token,我原以为会有很多 Skill 超标。实际只有 5 个,占 6%。中位数 1,633 token,相当克制。

这说明写的人大多有分寸感。真正的问题是别的。

结论二:引用断链占 43%,是第二大类的两倍还多。

我抽查了几个:

有个 Skill 的正文写着「详细说明见 wiki/index.md」,但目录里只有 SKILL.md,那个 wiki 目录从来没建过。作者当时可能打算写,后来忘了。

还有个 Skill 有 references/ 目录,里面文件都在,但正文引用时写的是 reverse-engineering/tools-dynamic.md,实际文件名是 tools-dynamic.md,多了个前缀。文件明明在,就是找不到。

这两类加起来,构成了断链的大头。

结论三:一半的 Skill 只用了前两层。

41 个目录里除了 SKILL.md 什么都没有。这意味着第三层——脚本和参考资料——完全没被使用。

关于三层加载的机制,在前面那篇里讲过。只写正文的 Skill 依然能用,但它失去了这个格式最大的优势:把确定性操作交给代码。

五、断链为什么这么常见

我认为有三个原因,都是结构性的。

一是 Skill 是"写一次、改很多次"的东西。 你发现漏了什么就补一句,删了一个文件就顺手 rm,但不会回头去改正文里那句引用。文件系统和文档内容之间没有任何强制关联。

二是路径有两种写法,容易混。 相对 Skills 根目录,还是相对 SKILL.md 所在目录?两种都有人在用,混着写就出错。

三是没有加载时校验。 Skill 加载只看 frontmatter,不管正文里的引用。所以断链永远不会在加载阶段暴露,只会在真正执行到那一步时才发现。

第三条是根本原因。工具不检查,人就会忘。

六、description 缺触发语,问题更隐蔽

40% 的 Skill 在这一项不合格。

description 是 Agent 唯一用来决定"要不要打开这个 Skill"的依据。它启动时只读这两行元数据,别的一概不看。

所以这句话必须回答两个问题:

  • 这个 Skill 做什么
  • 什么情况下该用它

我扫到的失败案例,大多只答了第一个。比如写「用于处理 PDF 文件」,这句话说得没错,但 Agent 不知道什么时候该想起它。改成「用于处理 PDF 文件。当用户要求提取 PDF 文字、填写表单、合并文档时使用」,匹配率完全不同。

这个问题的隐蔽性在于:Skill 装上了,格式没问题,也不报错。它只是永远不被触发。你以为装了个工具,实际上是装了个没人用的摆设。

七、怎么修

断链。 先跑一遍 lint 拿到清单,然后两件事:文件该有的补上,路径该改的改对。改完再跑一次确认。

日常维护上,我建议加一条纪律:删文件、改文件名的时候,同一个动作里顺手 grep 一遍所有 SKILL.md。 一个 grep -rn "旧文件名" 就能扫完,十秒钟的事。

触发语。 按固定句式重写:做什么。当……时使用。 前半句说能力,后半句列触发场景,触发场景里尽量用用户真会说的词。

超长正文。 5 个案例里,最长的约 14,000 token。处理方式不是删内容,是拆:把"只有特定情况才需要"的部分挪进 references/,正文留一个指针。拆完正文短了,信息一点没少,而且真正需要时还能读到。

八、给团队的五条规矩

如果 Skill 是多人维护的,光靠自觉不管用。

一,description 用固定句式。 前半句能力,后半句触发场景。写不出来的,说明这个 Skill 定位不清。

二,引用只写相对 SKILL.md 的路径。 统一一种写法,别混。

三,正文超过 3,000 token 就拆。 别等到 5,000 才动,留点余量。

四,lint 进 CI。 退出码非 0 就不合并。和代码检查一样对待。

五,每季度扫一次。 Skill 是文档,文档会腐坏。定个体检周期比事后追查便宜。

九、坑清单

写这个 lint 的过程本身踩了两个坑,都挺典型。

1. 把 URL 里的路径当成本地文件。 第一版扫出来断链特别多,仔细看发现 github.com/morluto/rea/blob/main/docs/xxx.md 被当成了本地路径。修法是匹配前先把 https?://\S+ 剥掉。

2. 正则把 package.json 截成 package.js。 我用 \.(md|py|sh|js|json) 匹配,非贪婪地在 .js 就停了。后来干脆去掉 js/json,只匹配 md/py/sh,误报立刻降下来。

3. 备份目录混进统计。 有个 .backup-xxx 目录里也放了 SKILL.md,被算成了一个 Skill。跳过所有 . 开头的目录就好。

4. token 估算是粗估,别当计费依据。 我用的 1.5 字符/token,不同模型、不同分词器能差出一倍。这个数只用来看量级。

十、边界

这个 lint 只能查形式,查不了内容质量。

一个 description 写得句式完美但描述错了能力范围的 Skill,它照样给绿灯。正文里讲的方法是不是最好的做法,它也不知道。

引用的检查也只覆盖 .md、.py、.sh 三类。正文里提到一个 .json 配置或者一张图片找不到,它不报。

这些都得靠人。工具的作用是把机械的部分自动化,让人腾出手看真正难的部分。

结语

这组数据里最有价值的一条,是"七成有问题"这个数字背后的分布。

如果把维护精力按问题占比分配,你应该把一半时间花在修断链上,而不是反复打磨正文措辞。大多数人恰好相反,正文改了七八遍,引用一次没查过。

给个具体动作:现在就扫一遍你自己的 Skill 目录,看断链有几个。数字出来之后,你可能会有和我不一样的结论。

站里另两篇:Skill 是什么、从零写一个能用的 Skill。

参考资料

目录导航
  • 一、Skill 写多了会烂,但烂在哪
  • 二、三个检查维度
  • 三、真实数据
  • 四、三个反直觉的结论
  • 五、断链为什么这么常见
  • 六、description 缺触发语,问题更隐蔽
  • 七、怎么修
  • 八、给团队的五条规矩
  • 九、坑清单
  • 十、边界
  • 结语
    • 参考资料
  • 相关文章:

  • Command 按按钮、Skill 给经验、Subagent 借个脑子:三者到底怎么配合
  • 从零写一个真能用的 Skill:目录、脚本、验证,外加一次被自己工具打脸的迭代
  • Skill 到底是什么:一个文件夹三层加载,和 MCP 干的不是一回事
  • Anthropic 给四个旧模型回填水印:改一个采样参数就能绕过去
  • 给 Agent 加预算护栏:四道闸门、一个检查点和分级降级
  • Agent 上线之后:工具调用日志、token 账和失败归因怎么做
  • Anthropic 递交 S-1:营收 14 倍增长,和 807 亿净亏损怎么同时成立
  • OpenAI 的艰难一周:13 起诉讼、FTC 传票、欧盟问询,还有开发者流向 Claude
  • 发表评论

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。