Agent Skill 最会骗人的地方,是它长得太像文档了。
一份 Markdown,有 frontmatter、有触发说明、有步骤和示例。改完以后格式检查通过,引用路径也都存在,看上去和改好了一段配置没什么区别。
可 Skill 如果会影响 Agent 的决策,它就不只是一份给人看的说明。它更接近一份可执行规范。文件能被读取,只能证明语法成立;面对真实任务时有没有改变行为,是另一回事。
这两种「通过」之间的距离,有时比想象中大。
一条规则写进文件,不代表它真的压过了旧习惯
假设 Skill 新增了一条要求,大范围改写公开文档以前,要先确认语言策略。
从文字上看,这条规则很清楚。结构验证器也不会挑出问题。但把 Agent 放进一个已经有英文 README 的旧项目,它仍可能直接沿用英文,因为历史内容像一个很强的默认答案。
规则存在,行为没有变化。
这类问题靠继续润色那句话很难发现。更有效的办法,是把它放回会误判的场景。给出一个真实旧仓库的最小背景,不声明未来语言,让 Agent 处理新的公开内容,再观察它会先询问,还是顺着历史状态直接做决定。
Skill 的测试对象不是 Markdown 文件本身,而是「文件加上上下文以后,Agent 做了什么」。少了上下文,最容易失败的那部分刚好被拿掉了。
我会同时测试它该做什么,以及不该做什么
一个可靠 Skill 至少要覆盖几种不同问题。
触发测试确认该使用它的请求确实进入这套流程;行为测试观察关键步骤有没有发生;边界测试确保只读分析没有被扩大成修改、提交和发布;证据测试则检查最终结论是否由对应强度的验证支持。
正向场景还不够。机械修复一个链接时,不应该每次都停下来讨论整套内容战略;用户只要求本地提交,也不能因为 Skill 里写了发布流程就顺手推送;分析一个仓库时,更不能把「可以修改」当成默认授权。
好的 Skill 会让 Agent 多做一些必要动作,也会在不该行动时让它停下来。
如果测试只检查理想路径,Skill 很容易变成一份越来越长的愿望清单。每新增一条规则,最好都问一下它会不会误伤邻近任务,会不会把一个小请求升级成完整流程。
最有价值的回归,通常来自曾经做错的旧项目
新建一个专门配合规则的示例,很容易得到漂亮结果。真实项目不会这么体贴。它可能已经有另一种语言的文档,旧脚本使用过时命令,README 宣称的版本落后于包,工作区里还躺着用户自己的未提交修改。
Agent 的很多误判不是因为完全不懂规则,而是多个看起来合理的信号撞在一起以后,选错了优先级。
所以我更愿意把曾经发生过误判的条件提取成回归场景。测试不一定要修改真实仓库,可以保留最小上下文,但那个让 Agent 当初做错判断的关键条件不能被清理掉。
以后调整触发词、流程顺序或授权边界时,再拿同一场景跑一次。新版本如果只在为它量身定做的例子里成功,还不能说明旧漏洞已经补上。
结构检查很重要,只是它负责的是地基层
frontmatter、相对路径、必需章节和资源引用当然要检查。脚本很适合发现拼写、断链与格式漂移,这些问题确定、重复,而且没有必要每次靠人工阅读。
我会把验证大致分成四层。
结构检查 → 能否发现并读取
示例检查 → 命令、路径与工具是否真实
场景回归 → 是否做出目标决策
越权回归 → 是否在没有授权时继续行动
前两层主要检查 Skill 作为文件是否健康,后两层才检查它作为行为规范是否有效。它们不能互相替代。场景跑通不代表引用路径永远正确,格式合法也不代表 Agent 会照着做。
一个 pass 不够,失败过程也要能被看懂
评估结果如果只保存 pass 或 fail,失败以后仍然要重新猜整条链路。更有用的记录应该包含输入场景、预期关键动作、实际响应,以及偏差发生在哪条规则。
多阶段 Skill 还可以为关键节点设置断言。有没有先读取项目约定,有没有检查远端状态,有没有把本地构建和公开发布分开。这样能判断失败发生在触发、执行还是验证,而不是把所有问题都归成「模型没听话」。
这也让 Skill 的修改更像代码评审。一处措辞变化会影响哪些场景,新增了什么回归,旧边界是否仍然成立,都可以被明确讨论。
文档负责表达意图,测试证明意图进入了行为
Skill 会被多个项目反复使用时,一句看似很小的修改,可能改变很多任务的默认选择。它值得拥有版本意识、回归场景和可审查的失败输出。
我现在不会因为结构验证成功,就说一个 Skill 已经改好。至少还要找到一个过去容易出错的场景,让新版本在相同条件下做出不同而且正确的选择。
如果做不到,文件可能确实写得更漂亮了。
Agent 还是原来那个 Agent。