1. 一个真实的翻车现场:写了Skill,Agent还是不听
上个月我花了一个下午,给团队常用的AI编程助手写了一份挺详细的"代码审查Skill"。SKILL.md里规定了审查重点、检查顺序、错误分级标准,甚至连什么样的问题算阻断、什么样的问题算建议,都写成了表格。我信心满满地提交,然后在一次真实的Pull Request审查里,Agent打开改动文件,盯着diff看了一会儿,然后给我提了一堆"这个函数命名可以更清晰"之类的泛泛之谈。最关键的一个安全问题——用户输入的SQL拼接——它压根没提。
那一瞬间我的第一反应是"这玩意到底有没有用"。如果你也遇到过类似的情况,或者正犹豫要不要给Agent写Skills,这篇文章就是写给你的。我不打算全盘吹Agent Skills怎么神,也不打算一棍子打死说它没用。我打算从机制、实操、调试这四条线把这个东西掰开,用我自己踩过的坑说明:Agent Skills这东西,本质上是"给Agent写操作手册",它有用,但它的有用方式和绝大多数人想的不一样。
先说清楚一个概念:Agent Skills,指的是在Claude这类具备Agent能力的AI助手里,通过本地文件系统预置的SKILL.md文件来给Claude注入领域技能。文件放在.claude/skills/<技能名>/SKILL.md这个路径下,里面用Markdown写上技能的触发条件、使用步骤、注意事项和示例。Claude是个典型的"长文本+工具使用"型模型,它在执行任务时会先扫描可用的Skills,遇到跟当前任务匹配的,就会主动加载这份"操作手册"来指导行为。
但"加载了手册"和"手册真正生效"是两码事。那次代码审查失败的根因,我后来复盘时发现有两个:一是我的Skill描述写得太模糊,Agent根本没在合适的时机判断出"这个任务该用这个Skill";二是Skill正文里塞了一堆原则性的东西,缺少可执行的分步清单,Agent读完以后相当于没读。这两个坑,几乎每个第一次写Skills的人都会踩,后面我会展开讲怎么避。
在开始之前,先把结论丢给各位:给AI编程助手写操作手册,有用。但它不是用来"增强模型能力"的,而是用来"约束模型行为"和"沉淀团队规范"的。你把这句话理解到位了,使用方法自然就对了。接下来的篇幅,我来解释为什么会得出这个结论,以及一份真正能用的Skills应该怎么写、怎么测、怎么迭代。
2. 先搞清楚Agent Skills到底在解决什么问题
想判断一个技术方案有没有用,得先看它解决什么痛点。Agent Skills解决的问题,和普通Prompt、Tool、MCP解决的问题有交集,但侧重点完全不同。我用一个对照表先把阵营拉开:
| 方案 | 类比 | 解决的问题 |
|---|---|---|
| System Prompt | 给新员工做的入职宣讲 | 设定总体的行为准则、语气、边界 |
| Tool / Function Call | 给新员工发一把电钻 | 赋予调用外部函数、获取数据的能力 |
| MCP | 给新员工接通公司内部各个系统 | 统一数据和服务访问的端口 |
| Agent Skills | 给新员工发一本岗位SOP手册 | 沉淀"这个活具体该怎么干"的操作知识 |
从这个类比可以看出来,Skills的定位非常特殊:它不直接给模型增加"能力",而是增加"工作方法"。
2.1 Skill是"操作手册",不是"能力包"
大多数人第一次接触Agent Skills时,会有个预期:我把最佳实践写进去,Agent的执行质量应该能立刻变强。这个预期在很多时候是落空的,因为一个Skill真正改变的不是模型的推理上限,而是它做具体任务时的"动作序列"。
举个数据相关的例子。我写过一个"数据探索Skill",里面规定:拿到数据集先看shape和dtypes,再统计缺失值比例,超过5%的字段要在报告中单独说明,然后才是画分布图、做相关性分析。这套流程一个合格的数据分析师闭着眼都会,但AI助手如果没有人给手册,它大概率上来就是一通df.describe()、df.corr(),然后给你丢一个图表堆砌物。跑出来的东西不算错,但很不像专业分析师的工作习惯。
这就是Skills的第一层价值:把团队里老师傅的工作流,变成显性的、可复制的操作步骤。模型自己是不会总结出一套"我们团队认可的工作方法"的,你得写给它。它不需要Skill也能干活,但有Skill的时候,干活的方式更接近你的预期。
2.2 加载机制:Skill是"按需翻阅",不是"每轮硬灌"
理解Skills的另一个关键点是它的加载方式。System Prompt是每轮对话都要进上下文的,它会持续占用注意力,所以你不能把一大本SOP塞进System Prompt里;Tools是模型可调用的接口,但调用接口不等于知道怎么组合这些接口去完成一个复杂流程;Agent Skills则不同,Claude会根据当前任务内容自动决定要不要找这份手册来读。
这个机制的好处是省token、省注意力。但坏处也很明显——它依赖模型的"判断力"来触发阅读。如果你的Skill描述写得不好,模型判断不出"这个任务该用它",那这个Skill就形同虚设。所以我后面会专门讲,description字段怎么写才容易唤醒Agent。
2.3 Skill和MCP的分工:一个管"怎么连",一个管"怎么干"
MCP(Model Context Protocol)最近在AI圈讨论度很高,很多人会把Skill和MCP搞混,或者觉得有了MCP就不需要Skill了。我的理解是这俩压根是互补关系。
MCP解决的是"模型怎么访问外部数据和工具"的问题。它是一套协议,让Claude能够以标准的方式连接到GitHub、文件系统、数据库这些资源。但连上数据库之后,怎么围绕这些数据产出符合规范的报表?MCP不管这个。Skill管的就是这一段:它规定操作流程、报告结构、检查要点。
打个比方:MCP是你给员工开通的内部系统账号,Skill是员工入职第一天拿到的工作手册。账号决定他能进哪些门,手册决定他进门以后该干什么、按什么顺序干、干完交什么东西。两者缺一不可。
所以我的建议是:在接入MCP之前或同时,先把手边那些重复性高、流程稳定的任务写成Skill。器人调得再好,流程没有固化下来,每次都是模型自由发挥,输出质量就很难稳定。Skill的本质,就是给"自由发挥"驯装一道轨。
3. 手写一个实战Skill:把研发团队规范做成SKILL.md
概念聊完,来点实操。我拿"代码提交信息规范Skill"来做例子,因为这个场景几乎每个开发者都熟,而且足够简单,可以完整体现一份SKILL.md的写法。
我给Skill建的标准目录是这样:
your-project/.claude/skills/commit-msg/SKILL.md注意commit-msg是这个技能的名字,目录名和技能名保持一致。一份SKILL.md通常由两部分组成:YAML格式的frontmatter(元信息)和Markdown格式的正文(操作指南)。
3.1 完整的SKILL.md示例
下面是我实际在用的一个精简版,用于让AI助手帮团队生成符合规范的Git提交信息:
--- name: commit-msg description: 根据git diff生成符合团队规范的commit message。当用户要求提交代码、生成提交信息、写commit message时使用。生成的信息需遵循Conventional Commits规范。 version: 1.0.0 metadata: author: team-dev --- # Commit Message生成技能 ## 使用时机 - 用户要求"提交代码"、"帮我commit"、"生成提交信息"时 - 用户要求为已有改动生成Pull Request标题和描述时 ## 工作流程 1. 先运行 `git diff --cached` 查看已暂存改动;如果没有暂存内容,运行 `git diff` 查看工作区改动 2. 按改动文件的功能归类,识别出本次提交的主体类型(feat/fix/refactor/docs/test/chore) 3. 检查是否有破坏性变更,若有必须在commit message中加 `BREAKING CHANGE:` 说明 4. 生成格式:`<type>(<scope>): <subject>`,如 `feat(auth): 增加邮箱验证码登录` 5. subject使用祈使句、不超过72个字符,不要以句号结尾 ## 输出格式 - 若改动涉及多个功能类别,按type分组输出多条commit建议 - 在commit message后附一段中文说明,简述每条建议的理由 ## 边界与注意事项 - 不要提交未暂存的文件 - 如果diff为空,直接告诉用户"没有可提交的改动",不要强行生成 - 生成的commit message中不要出现AI生成痕迹的套话,如"优化代码"这种无信息量的表述3.2 写好frontmatter,比写正文更关键
很多新手写SKILL.md时最容易忽视的就是开头的YAML部分。你可能会觉得description只是给人看的摘要,随便写两句就行。但实际上,description决定了Agent会不会在正确的时候读这份手册。
Claude的加载逻辑是这样的:拿到用户请求后,它会扫描已经安装的Skills列表,根据description里的内容判断这个Skill和当前任务的匹配度,然后再决定要不要打开SKILL.md。这个判断非常依赖description里出现了哪些关键词和场景描述。
拿上面这个例子来说,我在description里明确写了触发场景:"提交代码"、"生成提交信息"、"commit message",同时又写了功能边界:"根据git diff生成符合团队规范的commit message"。这样Agent在读这个Skill列表时,能快速判断"用户要提交代码,这个Skill可能相关"。如果你只写一句"用于生成commit message",Agent也不至于完全找不到,但触发准确度会下降不少。
另外一个容易被忽略的点是:一个目录下面可以放多个技能,也可以在不同的子目录里放配套资源。按照官方实践,如果你需要给Skill附上模板文件、示例数据,可以放在SKILL.md同目录下,然后正文里用相对路径引用。这样打包分享时所有东西都在一个文件夹里,不会散落各处。
3.3 正文结构:先给流程,再给边界
SKILL.md的正文,我建议按这个顺序来组织:
- 使用时机:什么场景下该用、什么场景下不该用。这一步是为了防止"错误唤起",非常重要。AI工具的特点是你给它的空间越大它越容易跑偏,明确边界能省掉大量返工。
- 工作流程:按步骤号列出从开始到结束的动作序列。步骤要足够细,但不要细到把模型的每一步思考都规定死。我一般每个步骤控制在"动作+产出"两句话以内,比如"运行命令查看改动"、"按类别归类提交类型"。
- 输出格式:定义结果长什么样。AI编程助手生成的代码、提交信息、报告都有"被下游直接消费"的需求,你这里定义得越明确,后面的人工校对成本越低。
- 边界与注意事项:这是很多人忽略的部分。把容易踩的坑、绝对不能做的事写在这里,比如"不要提交未暂存的文件"、"diff为空时不要强行生成"。它可以显著降低Agent的"自作主张率"。
我遇到过最典型的反面教材,是一个人把Skill写成了几千字的论文,前面五段都在讲"什么是好的代码注释",讲到第六段才进入实操。Agent读完以后记住的是抽象原则,执行的时候依然我行我素。正确做法是把可执行的步骤放在最前面,把原则解释放在最后或直接删除。Agent需要的是指令,不是论文。
4. 有用还是没用?真正的分水岭在这三个维度
回到标题那个核心问题:给AI编程助手写操作手册,到底有没有用?
经过这段时间的反复测试,我的答案是:有用,但作用范围比很多人想象的要窄。一个Skill有没有效果,我总结了三个判断维度。
4.1 第一维:任务流程是否稳定
这个最简单也最关键。如果你要固化的任务是"每次步骤都一样、判断标准相对固定"的,Skill的效果立竿见影。比如提交信息生成、测试用例编写、日志规范化、代码格式检查,这些任务的共同点是流程固定、评判标准清晰,写清楚步骤后Agent的执行一致性会大幅提升。
反过来,如果任务是高度探索性的,比如"帮我设计一个新产品的架构"、"写一段充满创意的营销文案",这种任务本身没有标准流程,你硬套一个Skill上去反而会限制模型的发挥空间。我试过一个失败的案例:给一个"系统架构设计Skill"规定了必须"先写需求分析、再画模块图、再写接口定义",结果生成的方案明显变僵了,模型为了符合流程而把真正重要的设计权衡稀释掉了。对这种探索类任务,我更推荐用普通的对话提示词,让模型自由发挥,然后人工介入讨论。
4.2 第二维:规则是否可以被显式表达
有些知识虽然流程固定,但"只可意会不可言传"。比如"代码味道",一个有经验的开发者看一段代码能感觉出哪里不对,但很难用几条规则总结出让AI照做的标准。这种情况写Skill就很为难:你写得太细,模型会被条条框框束缚;写得粗,模型行为跟没写差不多。
有个折中的办法:把"负面清单"写进Skill。不要试图定义"什么是好的",而是定义"什么是不允许出现的"。比如给代码审查Skill写清"不允许出现魔法数字"、"不允许吞掉异常"、"不允许修改与本次需求无关的文件",远比写十句"请注意代码质量"这种正确的废话有用得多。负面清单天然是显式的、可检查的,模型执行时更容易对齐。
4.3 第三维:Skill与工具的配合深度
如果你的任务需要和外部环境交互,比如操作浏览器、调用API、修改数据库,单独写一个Skill是不够的。Skill只规定"怎么做",但"用什么做"需要Tools和MCP来提供。我做过一个自动化测试Skill,里面要求Agent"打开浏览器登录系统,运行冒烟测试用例",结果模型严格遵守了,但没有可用的浏览器工具,于是卡在原地。
这个教训让我意识到:Skill是手册,不是工具箱。写Skill之前,你得先确认Agent已经具备完成这项任务所需的工具集。如果工具没接通,Skill写得再详细也只能生成一个"纸面流程",无法真正落地。实测下来,Skill加一个能配合它的MCP服务,效果会出奇的好:一个是流程规范,一个是能力基座,两者拼起来,才能让Agent像模像样地独立干完一件复杂事。
5. 让Skill真正被用起来的调试经验
说一千道一万,写Skill只是第一步,真正能拉开差距的是调试和迭代。这个环节里坑最多,我捡几个重点说。
5.1 调试Skill的唯一正确方式:固定输入,反复跑
我自己调试Skill时,绝不会让Agent随意干活,而是准备一组"固定测试样本":三个典型的正例、两个典型的反例、一个边界场景。每次改完SKILL.md,我就把这套样本重新跑一遍,对比输出差异。
比如调试"代码审查Skill"时,我准备了一个故意含有SQL注入极脆弱写法的PR,一个违反团队命名规范的PR,还有一个完全没问题的PR。每次改描述或者步骤,我就看这三个样本上的行为变化。这套方法比凭感觉调Prompt靠谱一百倍,因为它能让你看清楚"这次改动到底改变了什么"。如果三个样本的结果没有明显变化,说明改动没作用,果断回滚。
改Skill的频率也要克制。一次只改一个变量,改完跑全套样本,不要攒十处改动一起上——否则你根本分不清哪处改动导致了哪个行为变化。这和调试代码是一个逻辑。
5.2 给description做"召唤词"设计
我在前面提过description的重要性,这里再具体一点:好的description应该包含"任务识别词"和"应用场景句"两部分。
举个例子。我有一个"数据分表设计Skill",description一开始写的是"用于数据库分表设计",结果老是不被触发。后来我改成:
description: 当用户提到"分表"、"分库"、"数据量太大查询慢"、"表数据增长过快"等场景,或要求设计数据库水平拆分方案时使用。提供分表键选择、拆分策略、迁移方案。加了这些召唤词之后,触发率肉眼可见地提升。原理很简单:Claude扫描Skill描述时就像一个搜索系统,你的description里有哪些关键词,决定它能不能被"搜索"到。所以我会建议把你期望用户说的词、以及任务涉及的核心概念尽量都写进去,但不能堆砌无关关键词。
5.3 一上来先做"手动加载",再过度到"自动触发"
新写的Skill先别急着依赖自动触发。我在.claude/skills/目录里加了一个临时的activate-manual技能,里面只写了一句话:
使用前必须告知用户:"已激活技能:{技能列表},请确认是否继续。"这样我测试新Skill时,Claude每次读Skill都会先告诉我它认为该用哪些技能,我就能直观看到它的"技能选择是否合理"。如果Agent干一个要求代码格式化的活,却选了"数据分析Skill",那说明召唤词写歪了。等测了几轮,触发准确率稳定了,再把这个调试辅助技能删掉。
5.4 常见坑清单
把这段时间踩过的坑做个汇总,这些都是别人文档里不会写的实操细节:
- SKILL.md过长。我有一次写了一个超长Skill,结果加载后行为反而变差。实测下来单个Skill正文建议控制在3000字以内,核心步骤和负面清单优先,修辞和背景介绍能删就删。如果确实内容多,拆成两个Skill,各自聚焦一个场景。
- 多个Skill职责重叠。当你有两个Skill的描述都能覆盖同一个任务时,Agent会随机选一个,行为就变得不稳定。解决办法是让每个Skill的任务边界尽量唯一,相互之间用"不使用时机"来隔离。
- 只写"应该"不写"禁止"。模型的特性是顺从指令,你写的"应该"它会执行,但你可能忘了它也会执行很多你没提的"不应该"。"禁止放宽文件权限"、"禁止使用mock数据冒充真实测试结果"这种负面清单,往往比正面描述更有效。
- 版本管理缺失。Skill迭代是常态,建议在一个文件头部用YAML维护version字段,并在改动日志里保持简短的变更描述。回滚的时候,你至少知道上一个稳定版本长什么样。
6. 从"调提示词"到"沉淀技能":我的几点体会
最后不打算搞什么总结升华,聊点实际的体会。
Agent Skills这个东西,真正有价值的不是"让AI更聪明",而是把团队的工作规范从人的脑子里搬到仓库里。以前新人来了要跟着老师傅学两三周才能写出发规范、查得出问题的PR,现在老师傅把工作流写成一个SKILL.md,Agent立马就能按这套标准干活。规范的沉淀、复用、迭代,这套机制做得比纯Prompt工程优雅得多。
但也要承认它的边界。它不是万能的,在高度探索性的任务和"只可意会"的领域知识面前,它帮不上太多忙。我自己的用法是:在团队里先挑那些流程稳定、产出标准明确的任务试点,跑通三五个Skill之后,整个团队的AI协作质量会明显变得稳定,迭代和维护成本也低。
如果你准备动手尝试,我建议从最小的一个Skill开始写起。找一个你每周都会重复两三次、且每次都要跟AI重复解释需求的任务,把它固化成一份SKILL.md。写完测三遍,如果稳定了就提交到团队仓库里。你会发现,写第一份Skill最大的障碍不是技术,而是你对自己工作流中"隐性步骤"的觉察程度——当你真正开始把这些步骤逐条写出来时,你对"操作手册"到底有没有用的答案,会比任何评测都更清楚。