写好 skill 描述,让 agent 在该用的时候想起它
agent 靠描述判断要不要调用 skill:写清适用场景、触发信号,以及什么时候不该用。
我有一个 skill,用途是把 HTML 页面发布成在线链接。7 月底改过一次它的描述,只改了开头那一段,正文的发布步骤一个字没动。
改之前,描述是这么写的:
把生成的 HTML 报告发布到在线存档站,返回可分享的固定链接。当用户要求「生成一个 HTML 报告 / 输出汇报页 / 给我个在线链接 / 发布报告 / 更新那份报告」时使用。
当时提交说明里记的问题是:数据看板、原型页、说明文档、演示 demo 这些 HTML,因为不叫「报告」,不会命中这个 skill,我拿到的还是一个本地文件路径。
发布步骤写得再细也没用,agent 压根没想起来要用它。
agent 只看描述
skill 是这么工作的:平时上下文里只放每个 skill 的名字和描述,agent 根据眼前的任务读这些描述,觉得对得上,才去加载正文。正文写得多好,它在做决定的那一刻都看不到。
所以描述不是给人看的简介,它是一条路由规则,决定这个 skill 什么时候会被想起来。
那次的问题出在整段描述都围着「报告」这个名词写。里面其实有一句「给我个在线链接」,可开头就说这是发布「HTML 报告」用的。「报告」是我自己脑子里的叫法,做出来的东西是看板、是原型的时候,agent 就觉得这事不归它管。
改完的描述是这样:
把任何 HTML 页面发布成可分享的在线链接(汇报、审计报告、数据看板、原型页、说明文档、演示 demo 等一律适用)。触发场景:用户要「一个在线链接 / 发出来看看 / 发布一下 / 部署这个页面 / 别给我本地文件 / 给个 URL / 更新那个页面」,或你刚做完一个 HTML 而用户需要在浏览器里看或转发给别人。
变化有两处。一是把判断标准写明白了,提交说明里的原话是「实际判断标准只有两条:产物是 HTML + 需要被访问或分享」。二是触发说法换成了真实会说出口的话,「别给我本地文件」这种,比「发布报告」好认得多。
写清什么时候不该用
那次改描述,末尾还加了一句:
不用于产品自身的导出功能,也不用于应用本身的部署(那是 deploy skill)。
同一个仓库里还有一个 deploy skill,管的是把应用部署到服务器。「部署这个页面」和「部署一下」只差几个字,不写边界,两个 skill 就会抢同一句话。写明「这个不归我,归 deploy」,agent 就知道该往哪边走。
不该用的场景,最好也指到一个具体的去处。只写「不用于 X」,agent 知道不该用这个,还是不知道该用哪个。
触发信号可以是 agent 自己的动作
我还有一个记录待办的 skill,描述的写法不太一样:
强制纪律,不是可选项:凡是你准备在回复里写「遗留问题/以后再做/本次不展开/可选 backlog」,或对话中冒出任何没被处理的待办、隐患、业务诉求——必须先写入本仓库 ledger 再继续。
它等的不是用户说了什么,是 agent 自己准备说什么。agent 要在回复里写「以后再做」的那一刻,正是这个 skill 该出场的时候。这种信号用户不会说,只有 agent 自己能感知到,写进描述里就多了一个抓手。
不过这个 skill 上线当天,我又把同样的纪律写进了规则文件,提交说明里写着「skill description 自动触发不够可靠,会漏」。描述写得再准,调不调用还是 agent 的判断,判断就会有失手的时候。必须每次都发生的事,别只靠 skill,放进规则文件(这一点在另一篇里展开讲了)。
还有一件事:描述是常驻上下文的。9 月中旬,我在那个仓库里关掉了 34 个用不上的 skill。每多一个 skill,agent 每次开工就多读一段描述,也多一个可能被认错的候选。
可以直接抄的写法
一段好的描述大概长这样,四件事:做什么、什么时候用、用户会怎么说、什么时候不用以及该用谁。
---
name: publish-page
description: >
把任何 HTML 页面发布成可分享的在线链接(汇报、看板、原型、说明文档都算)。
用户说「给个链接」「发出来看看」「别给我本地文件」,或你刚做完一个 HTML、
用户需要在浏览器里看或转给别人时使用。
不用于产品自身的导出功能,也不用于部署应用本身(用 deploy skill)。
---
写完以后,拿最近几次本该用上它的对话对一下:那几句话,描述里有没有对得上的说法。
那个发布 skill 后来又改过好几次,加了加密、改了口令流程,改的都是正文。描述从 7 月底那次以后,就没再动过。