06. Skills

Skills 是「说明书」,承载具体的最佳实践

上一篇我们给 Agent 立了底座(System Prompt),最后留了一个缺口没填:「某一类文章到底怎么写好」这种偏方法论的知识,塞进系统指令是不合适的,那它该放在哪?这一篇就来填这个坑,主角是 Skills

👆你在这里
👆你在这里

🪧 一个个按需召唤的知识库

上一篇提到,System Prompt 是「刻在基因里的宪法」,只放全 App 不变的人设与纪律。可是像「随笔怎么写才有味道」「技术文怎么讲才清楚」这类具体某一类文章的写作方法论,是会不断积累、也会变的经验,塞进系统指令里明显不合适。它得有个地方待着,平时不占地方,写到某类文章时又能被随时唤醒

在 Claude 的世界里,这个「地方」就是 Skill

刚开始接触的时候,我曾把 Skill 和 Sub-agent 这俩概念搅混了,还纠结了一阵「这方法论到底该做成 Skill 还是派个 sub-agent 去处理」。后来发现,这俩压根是两个维度的东西。这一篇,我想先把这两个概念掰开,再讲怎么用 Skill 解决一个具体的问题:项目内置了 16 种写作题材规范,怎么保证 Agent 每次都用对那一个?

🧭 基础概念:先搞清楚 Skill 的定位

Skill 是一本随用随取的「说明书」,Sub-agent 是一个派出去干活的「分身」。 它俩是正交的关系,不是二选一

我做了张对照,把它俩最本质的差别摆一起:

Agent Skill(说明书) Sub-agent(分身)
本质 一份SKILL.md,装着「怎么做某类事」的方法论 一个独立的 agent 实例
上下文 共享主 agent 的当前上下文,就地翻开来用 完全隔离,在全新对话里跑,只回传结论
分量 轻。启动只加载一句描述,用到才展开全文 重。要新起一套上下文、单独跑一轮
适合 「教 Agent 怎么写某类文章」的可复用方法论 「把一段独立子任务外包出去」,比如调研、终检

打个比方:Skill 像是我塞给这位写作副驾的一叠「写作锦囊」,写散文时翻散文那页,写技术文时翻技术文那页,它人还是那个人,只是手边多了本参考手册;Sub-agent 则像我另外雇了个专员,让他去图书馆翻一堆资料,翻完只把一页摘要递回来,翻资料的过程一点不占我这边的桌面

如果我把「随笔写作方法论」错做成 sub-agent,那每次写随笔都得新起一个隔离上下文、把方法论当结论传回来,又重又别扭;反过来,如果我把「翻几十篇资料做调研」硬塞成 Skill,那几十篇资料的噪声就全灌进主写作上下文里了。分清楚「共享还是隔离」「轻还是重」,该用哪个就一目了然。这一篇只讲 Skill,Sub-agent则留到第 12 篇专门再讲

🔩 Claude Code 是怎么装这本「说明书」的

概念清楚了,看看 Claude Code 的现成做法。Learn Claude Code 的源码解读系列第七篇专门拆了 Skills 机制,它把一个 Skill 放成一个文件:.claude/skills/<名字>/SKILL.md。这个文件本身不复杂:文件头几行写元信息,最要紧的是一个 name 和一句 description,那句描述尤其关键,它几乎是模型判断「该不该翻开这本手册」的唯一依据,所以要写得让人一眼认出用途;文件正文,就是这类活的方法论本身;需要的话,还能在同一个子文件夹内附上几份参考资源文件。就这么一份朴素的 markdown,就是一个 Skill 的全部

这个文件还有个讨喜的性质:它既能被用户用 /名字 斜杠命令显式唤起,也能被模型按需自己判断该不该翻开。Claude Code 会在启动时,按配置从用户级、项目级几个位置把这些 SKILL.md 都发现、登记好,随时待命

我本以为「命令」得用另一套叫 .claude/commands/ 的旧格式文件去写。后来发现官方已经把这套旧格式标为过时,推荐统一用 SKILL.md,因为它一份文件就同时支持了「用户敲命令」和「模型自主调用」两条路。所以在 SmartWriter 里,那些「命令」,本质上都做成了 Skill。 到第 7 篇讲 Slash Command 时还会再展开

🛠 SDK 的「渐进式加载」:一本平时不占地方的手册

Skill 这东西一多,总不能一次性全塞进上下文,那样很快就爆了。SDK 跟 Claude Code 的思路是一脉相承的,都是渐进式加载,分两段:

  1. 常驻态:一个 Skill 平时只把它的「名字 + 一句描述」挂在一份轻量索引里。这句描述很省,跟 System Prompt 一样稳定、可缓存。模型平时只知道「手边有这么本手册,讲的是 XX」,但不知道细节
  2. 触发态:当模型判断(或用户用 /名字 明确要求)该用这本手册了,它才去调一个 Skill 工具,把 SKILL.md全文取回来、翻开看。全文是这时候才进上下文的

这个设计的好处很明显:16 个题材手册全挂着,平时只占 16 句描述的地方,不会把上下文撑爆;真要用到哪本才展开读取,这样又快又省

📐 深挖 · 「翻开的那页」,可能被压缩悄悄撕掉(可跳过)

要注意的是,Skill 全文是以「工具返回结果」的形态注入当前对话的。而我们在第 2 篇讲过,上下文一旦触发压缩(compact),早期的工具返回结果是会被摘掉的重点对象

这意味着:一个长写作任务,写到中途触发了压缩,那本「翻开的题材手册」很可能被撕走,模型后面就「忘了」该按这个题材的方法论继续写。这跟我在第 4 篇讲画像时放弃「用工具结果注入画像、改走 CLAUDE.md」是同一个坑

所以对「题材方法论」这种必须全程在线的东西,我没有只依赖「模型自己去调 Skill 工具翻开」这一条路。这个顾虑,也是后面那套「确定性注入」设计的直接动因

还有一个约束单独记一下:SDK 的 skills 名单(哪些 Skill 进候选池),是在创建会话那一刻就绑定死的,不能中途逐条动态改。这条约束意味着「这次要不要把某本手册放进候选池」,需要在任务一开始、写第一个字之前就决定好

📚 SmartWriter怎么做:把 Skill 分成三类,别混成一锅

轮到 SmartWriter 自己了。我一开始把各种 Skill 混在一起想,感觉很乱,后来梳理清楚了,其实可以明确分为三类: 

它是什么 例子 跟画像的关系
① 模式 Skill(动作) 跨题材通用的写作动作 润色 / 扩写 / 重组 / reformat / 调研 / 翻译 + 一个兜底,共 7 个核心动作 + 1 个独立的小红书化 无关,是「怎么改」的动作方法论
② 题材 Skill(知识) 某一类文章「怎么写好」的结构、节奏、常见陷阱 16 种内置(随笔、技术文、行业报告……)+ 用户自定义 和题材画像配一对:画像是你个人的风格,Skill 是这类文章的通用写好方法论
③ 流程 Skill(编排) 把动作和知识串成一条工作流 定制版 doc-coauthoring(调研→大纲→撰写→终检) 是编排者,自己不承载题材质量

⚖️ 取舍现场 · 一开始「按平台」切的,错了

最早我把写作知识 Skill 按「公众号长文 / 小红书短文 / 技术文档」来切。看着挺合理?其实是把「平台」当成了「题材」,错配了

问题在于:同一篇产品技术文章,有可能既发公众号又发小红书,难道要为它写两份「怎么写好」的方法论、各自进化、还互相打架?明显不合理。真正决定「内容怎么组织、用什么语气逻辑」的是题材,平台只决定「最后长什么样」

最后我把它改成按题材切,把「平台」彻底挪到最后一公里的导出环节去(除了调性适配外,大部分工作由确定性工具做格式适配,不经模型创作)。这个「题材归题材、平台归导出」的边界划清后,整个 Skill 体系就合理了

分类搞清楚后,接下来就是「各自怎么实现、能用到什么程度」。这三类的实现难度是递增的:模式最省心,流程要上点保险,题材最费劲。下面按由易到难的坡度,一类一类讲。这里面有一条暗线:越是容易出错、代价越大的判断,我越是要把它从模型手里接管过来

🟢 模式 Skill:SDK 加持下最省心的一类

先说最省心的。模式 Skill 是一组跨题材的通用动作:润色、扩写、重组、调研、翻译,另外还有个独立的「小红书化」,它做的是内容层面的 reformat(标题党化、口语化),跟纯格式适配不是一回事,所以单拎出来、由用户显式触发,不塞进导出

它们的实现,几乎就是「照着 SDK 的默认玩法来」:每个动作写一份 SKILL.md,把这个动作的方法论讲清楚(比如「润色」那本,就写清楚精炼用词、调节奏、删冗余的具体做法),然后它既能被用户用 /polish 这种斜杠命令显式唤起,也能被模型按你话里的意图自主判断该不该用。产出契约也很明确:写作类的动作(润色、扩写、重组这些)直接更新你的作品

这一类基本开箱可用,我几乎没跟 SDK 费劲,主要功夫花在「把每本 SKILL.md 的内容写扎实」上。因为「润色」「扩写」这种动作,用户意图很明确、模型也不太容易理解错,就算它偶尔自主判断得不那么准,代价也小(大不了你再说一句)。唯一的小插曲是:像/polish 这类斜杠命令,处理不当会被直接吞掉,这个坑我留到下一篇细讲

🔗 流程 Skill:把动作串成一部「剧本」

往前迈一步,是流程 Skill。它比模式复杂在:模式是单个动作,流程是把一串动作和知识编排成一条工作流。我预装并定制的那本,是把「调研 → 大纲 → 撰写 → 终检」串起来的 doc-coauthoring

流程 Skill 不是一条代码写死的流水线,它更像一部剧本,让模型自己照着演。 它在「撰写」那一步会去加载对应的题材 Skill,在需要资料的那步会派一个 sub-agent 去调研,整个编排是模型读着这份剧本、自主推进的,而不是我在代码里写死的 DAG 流程图

对 doc-coauthoring 的定制,主要三处:一是把它原本「文档(docs / proposal / spec)」的语气泛化到「文章 / 专栏」的语义;二是把我们自己的画像注入规则、还有终检环节接进这个流程;三是让它的某些步骤去调我们的确定性工具(比如格式校验、画像组装那些)

既然是「模型照着剧本自己演」,那就有跳戏的风险:某一步演着演着漏了,或者顺序乱了。这类失误对大多数步骤问题不大,但对「必做」的关键环节(最典型的是终检,强制定稿前过一遍),不能全靠模型的自觉。所以这类关键节点,我用 hook 给它兜底焊死(hook 是什么、怎么焊,第 10 篇会专门讲),漏了就拦住、补上。比起模式 Skill 的「放心交给模型」,流程 Skill 开始上强度了,需要给关键步骤上确定性的保险

顺带说一句,用户也能自定义工作流。用户可以把几个模式 Skill 拖拽排序,拼成自己的流程。这事听着像要做个运行时的流程编排引擎,其实不用:实现的核心是把选中的步骤指令,按序拼进一个模板,生成一份新的流程 SKILL.md。可以理解为「写一部新剧本」,而不是「造一台编排机器」

到这儿,模式和流程这两类,SDK 那套「模型自主 + /name」的默认玩法,配上关键步的 hook 兜底,基本够用了。可轮到第三类,题材 Skill,这套默认玩法就不够灵了。接下来重点讲讲,它为什么「有点不一样」

🎯 真正的难题:16 个题材,怎么保证它用对那一个

题材 Skill 有个绕不过的难题:写作场景可谓千人千面,哪怕已经内置了 16 种题材,用户大概率还是会自定义更多。那每次写作,到底该翻开哪一本?

顺着模式、流程的思路,最直觉的做法当然是继续「相信模型」:把用户开启的题材 Skill 全塞进候选池,让模型凭那句描述自己挑。其实我也试过,但结果不太理想:

  1. 相近题材,模型容易挑错。 「观点评论」和「职场思考」、「随笔散文」和「生活记录」,这些题材的描述天然相似,模型在候选池里凭一句话去分辨,选错的概率不低。一旦选错还静默生效,产出就跑偏了,用户还不知道为什么
  2. 它可能跟画像打架。 还记得第 4 篇吗?我在 CLAUDE.md 里已经按题材注入了「题材画像」。如果模型这边又自作主张挑了另一个题材的 Skill,就会出现「画像说这是 A 题材、Skill 却按 B 题材来」的精神分裂

所以到了题材这一类,我把「确定性接管」直接拉满:题材 Skill 不让模型盲选,改成确定性的「单选注入」。 逻辑也很简单,就一句话:先由一套确定性的判定链路定出当前题材,再去查这个题材的 Skill 用户开没开

拆开是这么走的:

  1. 先用分层降级的题材判定链路(genre_inferrer)定出当前是哪个 genre,或者「定不出」
  2. 如果定出了具体题材:查用户在设置里开没开这个题材的 Skill。开了,就把这一本塞进候选、并确定性地注入;没开,就不塞,但题材画像照旧注入(这俩解耦,不互相卡)
  3. 如果定不出(推断失败、置信度低、降级了):一本题材 Skill 都不加载。宁可不套,也不硬套一个可能错的

题材这种高价值、又容易挑错的判断,要想尽办法先用确定性的逻辑兜住,实在没招再让模型去「挑」。至于「怎么又快又准地定出题材」,我在产品里加了两个前序步骤:用户新建任务时可以直接下拉预选题材(这是精度最高、成本最低的短路,直接跳过模型分类);以及一份人工维护的别名词表(首句里出现「专访」「对话实录」就直接判成访谈记录,命中就不劳模型)。两者的核心目的,都是尽量少触发模型分类调用

那用户自己新建一个不在 16 种里的题材(比如「产品复盘」),它的方法论手册从哪来?这里我没让写作 Agent 临场发挥去写这本手册,而是专门做了一个后台的「生成器」Skill(一个 meta-skill),它按一套固定动作,为这个新题材调研特征、参考 16 本内置手册的格式、拟出方法论,产出一份规范的 SKILL.md 落盘。为自定义题材造手册,题材本身没法提前预知,但造手册这件事是个「标准动作 + 固定规范」的活,适合交给一个确定的生成器来干

🔧 避坑 · 探针实测:指望模型主动翻手册,命中率只有一半

定下「题材 Skill 该用哪本」之后,我本来还留了一手,想着「就算不确定性注入,模型自己应该也会去调 Skill 工具把手册翻开吧」。为了验证,还专门写了个小测试

结果却不太 ok:即便任务已经预选好了题材,模型主动去调 Skill 工具、翻开对应手册的命中率,只有一半左右。也就是说,有一半的时候,那本我精心写好的题材方法论,模型压根没翻。根因之一是题材手册的那句描述太短,模型没有足够强的信号去触发

正解是彻底不赌模型的自觉:我把选定的那本题材手册,直接把全文拼进这次对话的第一条消息最前面(外面裹一个「题材方法论」的标记),确定性地喂进去。同时那条「模型自主调用」的路我也留着,两条一起上,谁成谁算(工程上这叫 belt-and-suspenders,裤腰带加背带,掉不了裤子)。而且呼应前面那个深挖盒子:压缩之后这段前缀会丢,我还加了个「压缩后自动重新注入」的 hook 兜底。凡是「必须发生」的关键环节,别赌模型自觉,用确定性的机制把它焊死

⚖️ 收个尾:一条「越关键越要接管」的爬坡之路

回头看这三类 Skill 的实现,其实是同一条坡度上的三个点,摆在一起对照看:

⚖️ 取舍现场 · 三类 Skill,按「确定性」逐级加码

交给模型的程度 我接管的程度 为什么这么分
模式 Skill 基本全交给模型(自主 +/name 几乎不接管 动作意图清晰、错了代价小,该信任模型
流程 Skill 编排交给模型「照剧本演」 关键必做步用 hook 兜底 大步可放手,但终检这种漏不得的得上保险
题材 Skill 不让模型挑 判定 + 注入整个确定性接管 相近题材易挑错、还和画像打架,错了整篇跑偏

Skill 这套机制本身很灵活、很「智能」,鼓励你把判断交给模型。但落到做产品这件事上,我更看重另一件事:按『出错代价』给判断分级,代价越大、越关键的,越要为模型补上确定性的机制。这跟上一篇「删掉 Bash、把安全焊在工具层」是同一种思路:关键的地方做减法、上确定性,把不确定性留给真正需要发挥的创作本身

这一篇就到这里。你可能注意到,前面反复提到「用户用 /名字 就能唤起一个 Skill」,也埋了个雷说「斜杠命令有被吞掉的经历」。那这个「/」,从用户敲下去到真正触发,中间到底发生了什么?

下一篇我们来拆 Slash Command,以及它背后的核心思想:产出契约。咱们继续聊