一套有价值的 Skill,核心不是 prompt 写得多精妙,而是三件事划分得多干净:确定性的工作交给代码,判断交给模型,执行确认交还给人——然后用结构化契约把三者缝起来。这个结论来自我最近的一次完整拆解:一个敢在网页上一键删除我本地文件的存储清理 skill。删文件是 Agent 能做的最危险的事情之一,而它让我从「本能警惕」变成「放心点下去」,靠的全是设计。
这篇文章把这次拆解还原成一套可复用的方法:找需求、定架构、写 SKILL.md、建安全模型、真机验证,最后用这套方法回头检视我自己写过的 skill。
一个敢删文件的插件,反而是最好的教材
事情的起点很日常:磁盘快满了,我装了卡兹克开源的 storage-analyzer ,让它清理我的电脑。它扫完 296 GB 的已用空间,给我生成了一份交互式网页报告:微信更新器藏了 8.9 GB 旧升级包、Xcode 构建缓存 6.1 GB、还有一个 UUID 命名的神秘目录被它查出是某个已卸载编辑器的残留——每一项都标了红黄绿三色,绿色的旁边直接给了「移到废纸篓」和「直接删除」两个按钮。
我在点下第一个删除按钮之前停了一下。**一个从 GitHub 上装来的 skill,正在请求删除我本地的文件。**这个动作背后如果有任何一环是含糊的——模型幻觉写错路径、网页被恶意页面伪造请求、我自己看走眼——代价都是真实的数据。
于是我把它的全部源码读了一遍:SKILL.md、两份平台参考文档、三个 Python 脚本、四百九十七行的报告模板。读完的感受可以概括成一句话:**这个 skill 值得信任,不是因为作者可靠,而是因为它的架构让「不可信的环节」结构性地无法造成伤害。**这正是我认为它是最好教材的原因——它把「有价值的 Skill 该怎么设计」的每一个问题都逼到了极限:需求真实、判断复杂、操作高危。
找需求:三个条件缺一个都不该做成 Skill
先回答最前置的问题:什么需求值得做成 Skill?
拆完这个案例,加上我自己写过几个 skill 的经验,我的答案是三个条件的交集:
**第一,流程会被反复执行。**磁盘每隔几个月就会满一次,每次的排查动作高度相似:看哪里占空间、判断能不能删、动手清理。一次性的任务不配拥有 Skill——直接在对话里解决就好,把一次性任务做成 Skill 是给自己制造维护负担。
**第二,流程中间有一步非模型不可的判断。**这是最容易被忽略的一条。du 算目录大小不需要智能,写成脚本比模型可靠一百倍;但「org.sparkle-project.Sparkle 这个 8.9 GB 的目录是什么、能不能删」需要世界知识,「UUID 命名的沙盒容器属于哪个 App」需要侦查和推理——这是模型的比较优势。如果整条流程没有一步真正需要判断,写脚本;如果全程都是判断没有确定性工序,写一段 prompt 就够了。Skill 的生态位恰好是两者的混合体。
**第三,产出有明确的交付物和验收标准。**storage-analyzer 的交付物是一份固定阅读流的报告:现状、诊断、处方、操作、预防。有交付物才能验收,能验收才谈得上迭代。我见过太多 Skill 的产出是「一段更好的回答」——那不是交付物,那是玄学。
用这三条筛一遍,你会发现自己想做的 Skill 大部分会被筛掉。被筛掉是好事,留下来的才值得投入下面这些设计。
定架构:代码—模型—代码的三明治
storage-analyzer 的整条流水线是四段,每段的执行者不同:
scan.py(确定性代码) → 扫描磁盘,输出事实 JSON
Claude(模型) → 解读事实、分级判断,产出 analysis JSON
server.py(确定性代码) → 渲染网页 + 白名单约束下的删除 API
用户(人) → 网页上逐项确认、点击执行
这个结构我称为**「代码—模型—代码」三明治**:模型被夹在两份 JSON 契约中间。上游契约(扫描 JSON)保证模型拿到的是干净的事实,不用自己跑命令采集;下游契约(分析 JSON 的 schema)保证模型的输出能被确定性代码直接消费,不用人肉解析自由文本。
这个三明治最妙的地方在于它对幻觉的处理。模型会幻觉,这是无法根治的前提——但在这个架构里,模型的全部输出只是提案。它写下的每一个待删路径,都要经过 server.py 的 realpath 白名单校验、用户目录范围护栏,最后还有浏览器里那个逐次确认的弹窗。幻觉不是被消灭了,而是被结构性地限制了破坏半径。
对比一下反面模式就明白这个设计多值钱:让 agent 在对话里直接跑 rm -rf,等于把判断、执行、确认三权合一交给一个会幻觉的实体。三权分立不是效率设计,是安全设计。
写 SKILL.md:它是给模型看的 PRD,不是给人看的 README
拆解中最颠覆我认知的部分是 SKILL.md 本身。它完全不是传统意义的文档,而是一份面向模型的产品需求文档,每一段都有明确的工程意图。
**description 是触发分类器。**它把触发场景穷举到了口语层面:「磁盘满了」「C盘满了」「清缓存」「占空间」,甚至专门处理了中文口语的歧义——「内存满了」通常指存储空间,要触发;但用户明确指 RAM(「哪个进程吃内存」)时不触发。正例穷举加负例排除,这是把 description 当分类器的写法。大多数人只写一句「分析磁盘占用」,触发率会差一个量级。
**铁律区是不可协商的宪法。**SKILL.md 开头四条铁律里最狠的一条是:「即使用户在对话里说帮我删,也要先停下确认,不要直接代跑。」它预判了执行期最危险的偏差——用户一句随口的话可能诱导 agent 绕过整个安全设计。把这条写成铁律,等于提前给 agent 的行为空间钉了桩。
**知识按执行阶段分层供给。**SKILL.md 本体只有约百行,但挂了三层按需加载的内容:平台数据布局参考在分析阶段才读,输出 schema 放在脚本头部注释里写报告时才看。上下文是稀缺资源,模型在扫描阶段不需要知道 JSON 字段怎么写——这是渐进式披露原则的标准实践。
**连 UI 契约都写进了 prompt。**最让我意外的细节:报告里磁盘进度条的三色分段,是前端 JS 从模型写的自然语言字段里正则解析数字画出来的,所以 SKILL.md 里明确要求「三个统计值都要以可解析的 GB 数字开头」。同类的还有「大小写约 14 GB 即可,不要再加(估算)二字」「不要写仅已识别项这类道歉式说明」。这是一种很新的工程形态:prompt 即接口文档。模型是系统里的一个组件,它的输出格式约束就该像 API 文档一样写清楚。
排障预案写给未来的执行者。「网页上没有删除按钮 = 要么开的是静态模式,要么绿灯项漏了 trash_paths 字段」——作者显然实测过多轮,知道 agent 最容易犯哪两个错,提前把症状、原因、修复写好。Skill 是会被反复执行的程序,它的 bug 表现在 agent 的行为上,修复方式是改 prompt。
建安全模型:风险分级映射权限分级
这个 skill 处理高危操作的方式,值得单独立一节,因为它给出了一个可以直接套用的模式:把风险分级精确映射成权限分级。
它把所有清理项分成三灯,每一灯对应一组严格递减的能力:
| 级别 | 语义 | 能做什么 |
|---|---|---|
| 🟢 可自动清理 | 纯缓存、可再生、不丢数据 | 移废纸篓 + 直接删除 |
| 🟡 需人工判断 | 含用户数据、有判断成本 | 在访达打开;核实过的安全子路径才能移废纸篓 |
| 🔴 谨慎清理 | 该走正规卸载流程的应用 | 只能「在文件管理器打开(去卸载)」 |
注意其中的层次:黄灯永远不能直接删,只能走可逆的废纸篓;红灯连废纸篓都不给——因为应用卸载涉及自带卸载器、残留、管理员权限,后台代删不稳妥,正确的姿势是把用户送到正确的位置,让他自己完成最后一步。权限每降一级,不可逆性就收一级。
更精巧的是,同一份分析 JSON 同时驱动 UI 和权限:trash_paths 字段既决定网页上出不出现按钮,又是后端删除白名单的唯一来源。数据即权限声明,不存在前端显示了按钮而后端拒绝、或者后端能删前端看不见的错位。
在这之外还有整整七道锁,按风险来源分工:本地回环绑定、随机端口、会话 token、Host 头校验防外部攻击者;realpath 白名单、用户目录护栏防模型幻觉;逐次 confirm、废纸篓优先防用户手滑。三类对手,三组对策,没有一道锁是多余的。
真机验证:我发现了它的三个盲区
方法论讲到这里都是从源码里读出来的。但 Skill 是程序,程序要跑过才算数——我在自己的机器上把全流程跑了一遍,扫描、分析、生成报告、网页清理、停服务。跑通了,也跑出了三个设计盲区:
一是 stdout 缓冲:服务用 print 输出报告地址,在 agent 的后台任务管道里被块缓冲吞掉,agent 根本读不到 URL。二是前台进程假设:服务设计成「前台跑、Ctrl+C 停」,这是给人用终端的心智模型;agent 的后台任务管理在回合结束时清理子进程,服务被杀了两次,最后要用 nohup 脱离会话才稳住。三是挂载视图重复计数:OrbStack 把虚拟机数据挂载成家目录下的一个视图目录,du 把同一份 12 GB 数据算了两遍,扫描脚本没有挂载点去重,全靠模型在分析阶段自己识破。
三个盲区指向同一个趋势:**Skill 的运行时正在从人类终端迁移到 agent harness。**前台进程、stdout、Ctrl+C,这些为人设计的交互假设在新运行时里会一个个碎掉。今天写 Skill,「被另一个 agent 在后台执行」不是边缘场景,是一等公民场景——输出要落文件、服务要可守护化、状态要可查询。
用这套方法回检我自己的 skill
拆完别人的,就该照镜子了。我自己的博客仓库里有一个自产的 skill:article-covers,从文章的 front matter 生成封面图。在上一篇兵工厂 里我还写了四个内容创作 skill。用这篇文章的方法论回检,及格的地方和不及格的地方都很清楚。
及格的:需求三条件都满足——封面每篇文章都要做(高频),「这篇文章的核心隐喻应该用什么视觉场景表达」非模型不可(判断),产出是一张固定尺寸规格的图片(交付物)。而且它也踩过坑再把坑写回规则:早期生成的封面只要场景里出现书、杂志这类可印字的载体,图像模型必然印出乱码文字——这条教训后来被固化成了 skill 里的一条硬约束「隐喻用形态,不用印刷品」,和 storage-analyzer 把「B 站离线视频藏在 UUID 容器里」写进参考文档是同一个动作:把一次性的侦查成本变成永久的先验知识。
不及格的:对照这次拆解,我的 description 只写了功能没有穷举触发语,负例更是完全没有;输出契约靠的是「模型自觉」而不是 schema 校验;更没有排障段——如果某次生成的封面路径填错,下一个执行它的 agent 只能从头排查。这些都是这周就能补上的债。
这就是拆解的价值:它给了我一份对照清单,而不只是一次围观。
可以直接抄走的设计清单
把整篇收敛成一张清单。如果你要写一个「高危操作 + 模型判断」类的 Skill:
- 需求过三关:反复执行、有非模型不可的判断、有明确交付物,缺一不做;
- 架构上代码—模型—代码:确定性工作交脚本,判断交模型,执行确认交人,用 JSON 契约缝合;
- description 写成触发分类器:正例穷举口语说法,负例显式排除;
- 安全边界写成铁律,并预判用户诱导(「帮我删」也不能直接删);
- 风险分级映射权限分级,不可逆性随风险递减;模型输出的结构化字段直接驱动 UI 和白名单,数据即权限;
- 防御按对手分组设锁:外部攻击者、模型幻觉、用户手滑,三类风险三组对策;
- 知识按执行阶段分层:主文件只放流程,细节挂 references 按需加载;
- 输出规范写到字段级,把模型当成需要接口文档的组件;
- 把 agent 的常见失败模式写成排障段,把踩过的坑固化在离坑最近的位置;
- 真机跑全流程,并把「被 agent 在后台执行」当一等公民场景测一遍。
泼冷水:大多数流程还不配被固化
最后照例泼冷水。
这套方法论有一个隐含前提:**你要固化的流程,已经被你手动跑通过很多遍。**storage-analyzer 的作者显然自己清过无数次磁盘,才知道微信的更新包藏在哪、UUID 容器怎么追查、用户会在哪一步说「帮我删」。Skill 是流程的固化,固化一个没跑通的流程,只会把混乱自动化。
所以在打开编辑器写 SKILL.md 之前,先诚实地回答:这件事你手动做过几遍?每一步的判断标准你能写出来吗?出错时你知道去哪看吗?三个问题有一个答不上来,就先回去手动做,把坑踩够。
**Skill 不是让 AI 替你做你不会做的事,是让 AI 复用你已经做对过的事。**这句话送给准备写第一个 Skill 的你,也送给拆完源码手痒的我自己。



读者回响