最近一段时间,我在几个自动化项目里反复折腾Agent,最大的体感是:skill这个词正在从提示词技巧变成一种可以安装的工程流程。半年前我们聊“调提示词”,还是复制粘贴一大段文字让模型按规矩办事;现在主流Agent工具已经把一套完整的工作方法——包括触发条件、执行步骤、输出规范、甚至配套脚本——打包成一个独立的“技能包”,放到指定目录里,Agent就能在需要的时候自动发现并执行。它解决的问题很直接:AI不再需要你每次重复讲流程,团队也不用心口相传维护一堆prompt。这篇文章从使用者的视角,拆Skill的内部结构、安装方法、踩坑记录,以及我理解的工程化边界。想给Agent团队建SOP,或者在搭Agent自动化流程的人,应该能直接拿去对照用。
1. Skill的本质:从“一段提示词”到“一个可安装模块”
1.1 一个Skill内部到底装了什么
我见过很多人第一次拆开Skill目录时会愣一下:一个技能包看起来并不复杂,通常就是几个文件和目录,但它的组织方式非常有讲究。拿我做过的“代码评审”技能举例,目录大致是:
code-review/ ├── SKILL.md ├── scripts/ │ └── collect_scope.sh └── templates/ └── review.mdSKILL.md是入口,里面用frontmatter声明了技能名、触发描述、版本号,正文则是一份逐步操作的说明。scripts目录放的是可选脚本,用于辅助Agent收集变更范围这类机械操作;templates目录是输出模板,保证每次评审报告的章节一致。这套结构里,真正让Skill“可安装”的不是脚本,而是SKILL.md的存在,它相当于给Agent递了一份“按需加载的操作手册”。
这里有个容易被忽略的关键点:为什么不把这些操作手册直接塞进系统提示词?因为上下文窗口是有限的。平时如果让Agent把所有SOP都记在脑子里,对话一长就互相干扰,还烧token。Skill的设计是先让Agent读取一小段描述,判断“现在这个任务该用哪套流程”,确认需要后再把完整的说明加载进来。这个“按需加载”机制,就是它能从零散prompt变成工程流程的第一步。
1.2 Skill和Prompt、插件、MCP的边界
我第一次接触时也犯过迷糊:这不就是变相的Prompt吗?和插件有什么区别?和MCP是不是一回事?后来我在实际工程里对照过,才理清楚它们的边界。下面这张表是我自己整理出来,分享给团队用的:
| 对比项 | Prompt | 插件 | MCP | Skill |
|---|---|---|---|---|
| 核心形态 | 文本 | 代码模块 | 协议+服务 | 文档+脚本+资源 |
| 是否按需加载 | 否 | 是 | 是 | 是 |
| 是否可版本管理 | 基本不行 | 可以 | 可以 | 可以 |
| 侧重解决的问题 | 告诉模型怎么做 | 扩展模型能力 | 连接外部数据和工具 | 固定一套流程并稳定产出 |
| 维护成本 | 靠人复制粘贴 | 开发成本高 | 需要部署服务 | 中低 |
举个例子你就明白了。做自动周报场景,MCP负责连接日历、记录和数据库,解决的是“模型能读到数据”的问题;Skill负责规定“先拉哪些数据、按什么维度分类、最后生成什么格式的周报”,解决的是“模型该怎么按一套SOP干活”的问题。两者是合作关系,不是替代关系。如果你听到有人说“用MCP就能取代Skill”,基本可以判断他没真正在实践中跑过完整的自动化流程。
插件则更偏代码级别,它要处理生命周期、权限、集成点,属于开发者工具。Skill更偏“模型可读的操作手册”,写得好不好,直接决定模型执行得顺不顺。它比Prompt工程更接近“工程”两个字,是因为它能被结构化地安装、注册、调用和验收。
1.3 为什么说它正在变成“工程流程”
我判断一个东西是否算工程流程,会看五个维度:能不能安装、有没有版本、能不能被触发、有没有明确的输出定义、能不能测试。Skill这五点几乎都满足。
安装方面,把Skill文件夹放进约定目录,Agent就能自动发现,连代码都不用改,这比传统的插件开发轻量太多了。版本方面,SKILL.md的frontmatter里可以写version字段,配合版本管理仓库的tag做语义化版本管理。触发方面,有显式的when_to_use和description,模型会在合适的时机选择加载它。输出方面,可以在模板里定义交付物的章节和字段,避免每次生成都“随缘”。测试方面,给定一组输入,你可以验证它是否按步骤执行、是否产出预期格式。
这五个特征组合在一起,Skill就不再是“某个prompt技巧”,而是一份能把个人经验固化成团队资产的工程模块。我在某个团队推广的时候,经常用一句话给他们找感觉:Skill就是给Agent写的SOP,但比普通SOP更硬核,因为它真的是Agent会照着执行的。这句话虽然朴素,但这个定位很关键。
2. 写一个能用的Skill:流程设计到SKILL.md
2.1 先定流程,再写文件
很多人第一次写Skill就栽在一个地方:直接打开SKILL.md开始编步骤,结果写完模型执行起来乱七八糟。我建议的顺序是反过来的,先把“人类专家接到这个任务后会怎么干”画出来,再动笔写文件。
拿“代码评审”这个技能举例,我先会写下这样几行:
- 输入:PR地址,或者本地diff范围。
- 步骤:
- 收集变更文件列表;
- 读取关键文件的diff内容;
- 按严重程度把问题分成阻断、警告、建议三类;
- 对每个问题给出具体修改建议。
- 输出:一份包含总体结论、风险清单、逐条修改建议的评审报告。
这一步是在用最简单的文字固化流程,不需要画图,也不需要写复杂分支。流程清晰后,Skill的骨架就出来了。后面写的所有指令和示例,都要围绕这个骨架来组织。我见过太多人一上来就堆“高质量、全面、严谨”这类形容词,结果Agent执行时反而不知道重点在哪。流程优先,形容词靠后,这是写Skill的第一条铁律。
2.2 SKILL.md怎么组织,字段别乱填
一个规范的SKILL.md通常分两大部分:frontmatter和正文。frontmatter是YAML格式,负责给Agent一个“该什么时候用我”的快速判断;正文是Markdown,负责讲清楚具体怎么做。下面是我常用的模板:
--- name: code-review description: 对指定代码变更进行结构化评审,输出风险清单和修改建议。当用户要求review代码、检查PR、评估改动影响、准备merge前检查时使用。 when_to_use: 面对PR/MR、分支diff或一段待审查代码,需要给出结构化评审结论时。 version: 1.2.0 ---正文部分我会按顺序写“执行步骤”“输出格式”“硬性规则”“示例”。执行步骤用编号列表,每步只写必要信息,不要夹带解释。输出格式里明确章节顺序,比如“结论先行,再列风险,最后给修改建议”。硬性规则部分写“不要修改任何源代码文件”“不要跳过读取diff”“不要只给结论不给依据”。示例则放一段精简的输入输出样例,让模型看到活的目标形态。
这里要提醒一句:frontmatter里的字段名尽量保持小写,不要随意发明新字段,很多Agent工具只会读取约定好的字段。description要写成“用户用口语说这句话时,模型能判断该调用这个技能”的形式,而不是写成产品宣传语。正文里每条指令要尽量可执行,宁可少说也要说得准确。
2.3 触发机制:让Agent在合适的时机想起这个Skill
Skill的触发其实分几种,理解它们能帮你做更好的路径设计。最常见的触发方式是语义匹配:Agent读description,判断当前用户请求是否匹配。所以description写得越具体,触发越精准。第二种是显式调用,比如用户输入“/code-review”,Skill的name字段会被当成命令名来匹配,这在Agent已经明确知道要用什么技能时最高效。第三种是Skill被另一个Skill调用,适合串联流程,比如先跑“日志脱敏”,再让“周报生成”接手。
实际使用中,误触发比不触发更常见。原因往往是description写得太宽,或者里面包含了高频词汇。比如你在“代码评审”的描述里写“当用户提到代码问题时使用”,那用户问“这段代码为什么要这么写”也会被误触发,可这明明是个解释性问题,不需要评审。我自己的习惯是给description加负向条件,明确写“不要用于解释代码原理、不要用于编写新代码”。这招能显著降低误调用率。另外,不要指望模型记住所有Skill,很多工具会做截断或排序,description开头30个字的信息密度,直接决定这个Skill能不能被想起。
3. 把Skill安装进工作流:挂载、验收与分发
3.1 安装路径与挂载约定
Skill要“能安装”,首先得有明确的安装协议。不同Agent工具的做法不完全一样,但整体思路是通的:把Skill目录放进一个Agent能扫描到的地方,它就会被发现。以我常用的某个命令行Agent为例,它支持用户级目录和项目级目录,默认会扫描类似这样几个位置:
~/.agent/skills/ # 用户级,所有项目可用 .agent/skills/ # 项目级,跟着仓库走 /tmp/team-shared-skills/ # 团队共享目录,通过环境变量指定安装动作本身简单到不能再简单:复制文件夹过去,或者从代码仓库拉取下来,然后重启会话让Agent重新扫描。但这里有一个实操细节值得留意:如果你在项目仓库里放了.agent/skills,那么这个目录应该被纳入版本管理,而不是塞进忽略文件。否则团队成员clone下来之后,Agent的行为就不一致。
我建过不少团队级Agent流程,最后发现最稳妥的方式是用环境变量统一指定SKILL_DIR,让所有人指向同一个经过review的共享目录。用户级目录给个人做实验,项目级目录给具体项目固定流程,共享目录给团队做标准能力。三层隔离,互不干扰,排查问题也简单。
3.2 验收一个Skill:从“能跑”到“可信”
“我的Skill好像能工作”和“这个Skill可以放心交给团队用”之间,隔着一次认真的验收。我一般会跑一组固定的测试用例,覆盖触发、执行、输出、安全四方面。下面这个表格是我实际用过的验收模板,你可以直接抄:
| 测试项 | 测试输入 | 预期结果 |
|---|---|---|
| 触发精准 | “帮我review一下这个PR” | 激活code-review,而不是直接用通用能力回答 |
| 负向触发 | “这段代码为什么这么写” | 不激活code-review,正常回答 |
| 步骤完整 | 提供一段diff | Agent先收集变更范围,再逐项评审 |
| 输出格式 | 同一段diff跑两次 | 报告的章节顺序和字段保持一致 |
| 脚本安全 | 查看脚本是否只读 | 没有修改任何源文件,没有在预期位置之外写文件 |
跑测试时,我强烈建议用“不完美但真实”的数据,别用精心构造的理想样例。真实数据才会暴露出步骤缺失、描述歧义、脚本路径错误这类问题。我在某个模拟项目里跑过三轮,前两轮都出现“Agent跳过收集范围直接开评”的问题,原因是步骤列表里我说的是“收集变更文件列表”,但正文示例没有展示怎么看diff,模型就把这一步省略了。补上示例后再测,才稳定下来。
3.3 版本管理与团队分发:把它当代码一样维护
很多团队压根没把Skill当成正经资产,目录散落在各种聊天记录和下载文件夹里,这是最浪费的用法。我的建议是给所有Skill建一个统一的代码仓库,用语义化版本管理。SKILL.md里的version字段和仓库tag保持一致,每次更新都写变更记录,写清楚“改了哪个步骤、为什么改”。分发就用仓库拉取或者打包解压,团队内部可以做一个简单的发布脚本,拉取某个版本号的技能集合。
这里有个容易踩的坑:多人直接在共享目录里改Skill。你改一版,我改一版,最后谁也不知道线上Agent跑的是哪个版本。正确做法是所有人都改仓库里的统一副本,通过评审后再发布。技能仓库的Review重点不只是看代码,更要看SKILL.md描述是否和实际步骤一致,看示例是否更新。把这些流程立起来,Skill才真正从“个人技巧”升级成了“团队工程流程”。
4. 实战踩坑:Skill工程化的常见问题与排查
4.1 SKILL.md写太长,模型反而不听话
我第一版“代码评审”Skill写了快两百行,里面塞了各种评审理论、最佳实践。结果Agent每次加载都要吃掉一大段上下文,执行起来反而丢三落四,优先级全乱。后来我把内容砍到七十行左右,只留下核心步骤、硬性规则和一个示例,效果立刻变好。
原因其实不难理解:上下文有限,指令太多会互相稀释。一个Skill应当是“操作卡”,不是“教科书”。如果细节实在多,就拆成references目录,在SKILL.md里写“当遇到XX情况时,读取references/xx.md”,让Agent按需加载,而不是首屏全量塞进去。这条经验适用于所有给模型看的文档:能少写就少写,能晚加载就晚加载。
4.2 触发不灵:多数情况是description写歪了
有段时间团队同事反馈“我说帮我看看这段代码有什么问题,它没走评审技能”。我一开始怀疑是工具bug,后来翻日志发现Agent确实没识别出“看代码问题”等于“需要评审”。问题不在工具,在description。
我把description改成了更接近用户真实口语的形式:“当用户要求review代码、检查PR、评估改动影响、准备merge前检查,或者让帮忙找出代码中的缺陷时使用。”并补了一句:“不要用于解释代码原理,不要用于编写新代码。”改完之后,触发率明显上升。这个案例说明一个道理:排版、字段、路径这些表面问题通常很好修,真正影响体验的,是你对模型“如何理解意图”的假设。多站在用户口吻去写description,比一味堆关键词有效得多。
4.3 技能里的脚本:权限和安全必须提防
Skill带脚本是它的优势,同时也是最大的风险来源。我认识一个开发者,把一段“批量替换文本”的脚本塞进自己的Skill里,测试时没限制工作目录,结果在临时环境里把一批不该动的文件给改了。虽然只是测试,也吓出一身汗。
从那以后我给自己定了几条铁律:默认生成的脚本一律只读,最多输出统计信息,绝不直接修改文件;必须写文件时,先打印“将要修改哪些文件”的清单,让用户确认后再执行;新Skill上线前,要在隔离的临时目录或容器里跑一遍;团队仓库里,凡是改动技能的合并请求,必须有另一个人review脚本部分。Skill越普及,安全问题越容易被忽略,因为Agent执行脚本往往比传统插件更隐蔽。
4.4 跨工具兼容:别让Skill绑死在专属能力上
Skill如果想作为长期资产,就不能只适配某一个Agent工具。我在把一套Skill从工具A迁到工具B时发现,工具A能自动执行bash脚本,工具B默认只读文档,于是脚本部分完全失效。好在我的SKILL.md里本来就把“纯指令”放在第一位,脚本只是可选加速,核心流程换过去依然能跑。
所以我的原则很明确:技能包里的SKILL.md,必须保证不依赖任何脚本也能完成绝大部分步骤。脚本只负责“帮Agent更快地拿数据”,不负责“决定流程怎么走”。这样的好处是,将来换工具、升级模型,你的技能资产不会一瞬间报废。要让Skill可移植,核心不是代码,是流程描述写得好不好。
5. 把Skill变成团队资产:写、审、测、发的闭环
5.1 给技能库配上SOP
把几个Skill放进共享目录不叫团队资产,只能叫文件共享。真正的团队级Skill管理,需要一个简单的闭环:写、审、测、发。
- 写:统一用SKILL.md模板,要求必须有name、description、when_to_use、version四个字段。
- 审:评审必须有人review,重点看描述和步骤是否一致。
- 测:要求提供一份最小测试用例,拿真实但非关键的数据跑一遍。
- 发:打tag后发布,团队通过脚本或配置拉取特定版本。
这个过程听起来像软件工程,其实本质就是软件工程。Skill是运行在Agent里的代码,只是形态更轻、更偏文档。给它配上SOP,团队里新老成员都能稳定生产技能,而不是靠几个“会调prompt的人”撑场面。
我还建议给SKILL.md加一道格式校验,比如写个简单的脚本检查frontmatter是否完整、version是否符合语义化版本格式。这些枯燥的小工具,恰恰是工程化该有的样子。
5.2 技能市场来了,但先把自己手上的用完
我理解大家看到“skill正在变成一种可以安装的工程流程”时,第一反应是:未来会不会像应用商店一样,直接搜一个技能,一键安装到我的Agent里?这个方向大概率会出现,因为工程化的最后一步就是分发。团队内部可以先做私有技能仓库,未来公共生态成熟了再接上。
但我的建议是别急着等生态。先把手头最高频、最重复的三个流程做成Skill:比如“会议纪要按照固定模板输出”“日志脱敏后再贴给外人看”“每周项目复盘自动生成”。把这三五个技能跑稳,你自然就理解里面哪些环节值钱、哪些是伪需求。到公共技能市场出现那天,你已经是一个有作品集的创作者,而不是观望者。
5.3 保持克制:Skill不是万能的
Skill不是银弹。它擅长把“稳定、可重复、流程明确”的经验固化下来,但不适合处理高度动态、强依赖外部判断的任务。如果一个流程每次跑出来的结果都差异很大,先别急着写Skill,回去问流程本身是否稳定。我在做某个数据分析技能时,发现输出波动主要来自数据口径不统一,Skill怎么写都没用,最终是改了数据定义才解决。
换句话说,Skill是把好的流程复制粘贴给Agent,它不能让一个混乱的流程变好,只会把混乱稳定地放大。所以写Skill前先打磨流程,写完之后持续看执行日志,这两件事,比任何技巧都重要。
最后分享一个我自己的判断标准:每次准备写一个Skill之前,我都会问自己,“如果明天换掉底层的模型,这个Skill还能不能直接用?”如果答案是“恐怕不行,得靠模型自己脑补”,我就先不写。能被写进SKILL.md的,一定是那种“不太聪明但很听话的执行者”照着也能做出来的流程。这个方法帮我筛掉了不少看起来炫但经不起换环境的技能。你现在不需要搞一个庞大的技能库,先挑一个最痛、最重复的流程装进去,跑通一次,就能体会到这种工程化带来的差别。等哪天你觉得一个Skill版本迭代很自然了,那就说明,它确实已经从提示词,长成了真正的工程流程。