1. 从“skills”这个标题说起:它到底指什么
第一次看到“skills”这个标题,很多人会以为是泛泛而谈的能力清单,但在 Claude Code、Codex、agents、plugin 这一串热搜词的语境下,它其实指向一个非常具体的东西:Agent Skills,也就是给 AI 编程助手加装的“技能包”。你可以把它理解成给一个刚入职的实习生配的一本操作手册,手册里写清楚了遇到某类任务该调用哪些工具、按什么顺序执行、输出成什么格式。没有这本手册,模型只能靠通用推理硬扛;有了这本手册,它在特定任务上的稳定性和准确率会明显上一个台阶。
我最早接触这个概念是在折腾 Claude Code 的时候。当时我让它帮我做前端项目的组件重构,发现它每次生成的目录结构、命名规范都不一样,同一个项目里风格来回横跳。后来我把团队的代码规范、目录约定、常用命令写成一个 skill 文件挂上去,输出立刻收敛了。这就是 skills 的核心价值:把隐性的经验固化成显性的、可复用的指令集,让 agent 在特定领域里表现得像一个“懂行的人”,而不是一个什么都懂一点但什么都不精的通才。
这篇文章适合三类人看:一是刚上手 Claude Code 或 Codex、还在摸索怎么让 AI 听话的新手;二是已经用过一段时间、但输出质量忽高忽低、想找方法稳定下来的中级用户;三是想自己开发 skills、把团队内部流程沉淀下来的进阶玩家。我会从设计思路、核心机制、实操步骤到踩坑排查,把这一整套东西讲透,尽量让你看完就能动手。
需要先说明一点:skills 不是某个厂商独有的功能,不同工具对它的叫法和实现有差异。Claude Code 里叫 Agent Skills,Codex 生态里也有类似的自定义指令机制,社区里还有大量第三方 skills 仓库。我下面讲的内容以通用原理为主,具体到某个工具时会标注清楚,避免你把不同平台的机制搞混。
2. 核心机制拆解:skills 为什么能起作用
2.1 从“提示词”到“技能包”的认知升级
很多人对 skills 的第一反应是“这不就是长一点的提示词吗”。这个理解对了一半。普通的系统提示词是一段静态文本,模型读完就完了;而 skill 更像是一个带触发条件的结构化模块。它通常包含三部分:元信息(这个技能叫什么、什么时候用)、指令正文(具体怎么做)、可选的资源文件(脚本、模板、参考文档)。
为什么这个结构重要?因为模型的上下文窗口是有限的,你不可能把所有规范都塞进系统提示。skill 的设计思路是按需加载:平时它只是一个简短的描述挂在索引里,只有当任务匹配到触发条件时,完整内容才被拉进上下文。这就像你电脑里的软件,不是所有程序都常驻内存,用到哪个才加载哪个。这个机制直接决定了 skills 能规模化——你可以挂几十上百个技能,而不会把上下文撑爆。
我在实际项目里做过对比测试。同一个前端重构任务,纯靠对话描述需求,模型平均要来回三轮才能对齐预期;挂上一个写好的 skill 之后,基本一轮就能出可用的结果。差距不在模型能力,而在信息传递的效率。
2.2 触发机制:skill 是怎么被“叫醒”的
理解触发机制是玩转 skills 的关键。目前主流的触发方式有两种:描述匹配和显式调用。
描述匹配靠的是 skill 元信息里那段简短的说明。模型在处理任务时,会拿当前任务去和所有已注册 skill 的描述做语义比对,匹配度高的就激活。这种方式的好处是自然,你不需要记什么命令;坏处是可能误触发或者漏触发,尤其是当两个 skill 的描述写得太像的时候。
显式调用则是你直接点名,比如在对话里说“用 XX 技能处理这个”。这种方式精准,但需要你记得住技能名。
我的经验是:高频、边界清晰的技能用描述匹配,低频、容易混淆的技能用显式调用。比如“生成 React 组件”这种天天用的,让它自动触发;而“生成数据库迁移脚本”这种偶尔用、又容易和普通 SQL 生成混淆的,就手动点名。描述文字要写得有区分度,别用“处理代码”这种万能词,要写成“当需要把 Vue2 组件迁移到 Vue3 组合式 API 时使用”,越具体越不容易误触发。
2.3 和 plugin、agent 的关系理清
热搜词里同时出现了 skills、plugin、agents,这三个概念经常被混为一谈,我按自己的理解捋一下。
Agent是执行主体,是那个“干活的人”。Skill是这个人掌握的某项技能,是知识和流程。Plugin则更偏向能力扩展,通常是接入外部工具或服务的接口,比如让 agent 能读数据库、能调某个 API。
打个比方:agent 是一个员工,skill 是他脑子里的操作规范,plugin 是他手里的工具。员工可以有很多技能,也可以配很多工具,但技能和工具是两回事。一个 skill 在执行过程中可能会调用多个 plugin 来完成工作。搞清楚这个分层,你在设计自己的 skills 时就不会把“该写进技能流程的逻辑”和“该做成工具调用的能力”搅在一起。
3. 动手写第一个 skill:完整流程与关键细节
3.1 环境准备与目录结构
不管你用的是 Claude Code 还是 Codex,skills 的存放位置基本遵循一个约定:项目根目录下有一个专门的技能目录,通常叫.skills或者放在配置目录里。以 Claude Code 为例,项目级的技能一般放在项目内的约定目录,用户级的放在用户主目录下的配置文件夹里。项目级优先级高于用户级,这样团队可以共享一套规范,个人又能有自己的偏好。
目录结构上,一个 skill 通常是一个独立文件夹,里面至少有一个主文件(常见是 Markdown 格式),可选地带上脚本、模板、示例等辅助文件。我建议的命名规范是全小写加连字符,比如vue2-to-vue3-migration、api-error-handling,别用中文、别用空格、别用大写,避免在不同系统上出现路径问题。
提示:动手前先确认你的工具版本支持 skills 功能。老版本可能只支持简单的自定义指令,没有完整的按需加载机制。升级到较新版本再折腾,能省掉很多“为什么我的 skill 不生效”的困惑。
3.2 元信息怎么写才不容易误触发
元信息是 skill 的“门面”,决定了它什么时候被激活。核心字段一般包括名称、描述、可选的触发关键词。描述字段是重中之重,我总结了三条写法原则。
第一,写清楚“什么时候用”,而不是“这是什么”。差的写法是“一个用于处理 API 错误的技能”,好的写法是“当代码中出现网络请求、需要统一处理超时、重试和错误提示时使用”。前者是名词解释,后者是场景描述,模型对场景的匹配更准。
第二,加入区分性关键词。如果你的项目里同时有前端和后端的错误处理,那前端 skill 的描述里就要带上“组件、UI、用户提示”这类词,后端 skill 带上“接口、状态码、日志”这类词,让两者的语义空间拉开距离。
第三,控制长度。描述太长会占用索引空间,太短又区分度不够。我的经验是控制在两三句话,大概五十到一百字之间比较合适。
3.3 指令正文的结构化写法
正文是 skill 的灵魂。我见过太多人把正文写成一大段散文,结果模型执行时抓不住重点。正确的做法是结构化,用清晰的层级把流程拆开。
一个我常用的模板是这样的:先写目标(这个技能要达成什么),再写前置条件(执行前需要确认什么),然后是步骤(分步骤写清楚每步做什么、用什么工具、输出什么),最后是输出规范(格式、命名、注意事项)。步骤部分尽量用有序列表,每一步都写成可执行的动宾结构,比如“读取目标文件”“提取所有组件定义”“按组合式 API 重写”,而不是“考虑一下怎么改”。
这里有个细节很多人忽略:在步骤里明确“遇到什么情况该停下来问”。比如“如果发现目标文件超过五百行,先暂停并告知用户,不要直接改”。这种边界条件写进去,能避免 agent 在复杂场景下自作主张,把项目改得面目全非。
3.4 一个可复现的完整示例
我拿一个真实用过的 skill 举例,功能是“把 React 类组件转成函数组件加 Hooks”。元信息描述写成“当需要把 React 类组件重构为函数组件并使用 Hooks 时使用,涉及 state、生命周期、ref 的转换”。
正文我分成四块。第一块是目标:保持原有功能不变,把类组件转成函数组件。第二块是前置检查:确认文件是.jsx或.tsx,确认组件没有被其他类继承。第三块是转换步骤,我列了六步:识别 state 定义并转成 useState、识别生命周期方法并映射到 useEffect、识别实例方法并转成普通函数或 useCallback、识别 ref 并转成 useRef、处理 this 绑定、最后清理无用的 import。第四块是输出规范:保持原有 props 类型定义、保持导出方式不变、在文件顶部加一行注释说明这是自动转换的结果。
这个 skill 挂上去之后,我批量处理了十几个组件,成功率大概八成,剩下两成需要人工微调,主要是复杂的生命周期逻辑映射。这个成功率已经比纯对话高太多了。
4. 进阶玩法:让 skills 真正融入工作流
4.1 技能组合与依赖管理
单个 skill 能解决的问题有限,真正提升效率的是技能组合。比如我有一个“生成 API 接口”的 skill,一个“生成接口测试”的 skill,一个“生成接口文档”的 skill。单独用每个都要手动触发,但如果我在“生成 API 接口”的 skill 末尾写上“完成后自动调用测试生成和文档生成技能”,就能串成一条流水线。
这里要注意依赖顺序和失败处理。如果测试生成失败了,文档生成还要不要继续?我的做法是在 skill 里写明“如果前置技能执行失败,停止后续步骤并报告”,避免生成一堆半成品。技能之间的调用关系最好画个简单的依赖图记在项目文档里,不然技能多了之后自己都记不清谁依赖谁。
4.2 版本管理与团队协作
skills 是代码资产,就该像代码一样管理。我强烈建议把项目级的 skills 纳入版本控制,每次修改都写清楚改了什么、为什么改。团队协作时,skill 的修改要走评审,因为一个描述写歪了可能影响所有人的输出。
我们团队的做法是:skills 目录单独一个仓库,或者放在主仓库的一个子目录里,配一个简短的 README 说明每个技能的用途和维护人。新人入职第一件事就是拉下这套 skills,装上之后立刻就能按团队规范干活,省掉了大量口头培训。
注意:团队共享的 skill 里不要写死个人的路径、密钥、账号信息。这些应该通过环境变量或者配置文件注入,skill 正文里只写“从配置读取”,保证技能包可以安全地在成员之间流转。
4.3 效果评估与迭代
skill 写完不是终点,得持续迭代。我用的评估方法很朴素:记录每次执行的成功率和人工干预次数。连续用十次,如果八次以上不需要改,说明这个 skill 成熟了;如果一半以上要返工,说明描述或步骤有问题,得回去改。
迭代时优先改描述和触发条件,因为大部分“不生效”其实是没触发或者误触发。其次改步骤的粒度,太粗模型抓不住,太细又显得啰嗦。我一般会把步骤控制在五到十步之间,超过十步就考虑拆成两个技能。
5. 常见问题排查:那些我踩过的坑
5.1 技能不生效的排查顺序
技能挂上去没反应,是最常见的问题。我总结了一个排查顺序,按这个走基本能定位。
先确认文件位置对不对,项目级和用户级的目录别搞混。再确认文件格式,主文件的扩展名和编码要符合工具要求,UTF-8 是底线。然后看元信息,描述字段有没有写、格式对不对、有没有语法错误。接着看触发条件,是不是任务和描述压根不匹配。最后看版本,工具版本太老可能不支持完整机制。
我遇到过一次折腾半天的案例:skill 死活不触发,最后发现是文件名里有个大写字母,工具在某个系统上没识别到。改成全小写立刻好了。这种坑不踩一次根本想不到。
5.2 输出不稳定的应对
有时候 skill 触发了,但输出还是飘。原因通常有三个:指令正文有歧义、缺少示例、边界条件没写。
歧义最常见。比如你写“优化代码”,模型不知道是优化性能还是优化可读性。改成“在不改变功能的前提下,减少重复代码,提取公共函数”就明确多了。缺少示例也是大问题,模型对抽象描述的理解不如对具体例子。在 skill 里放一两个输入输出的示例,效果立竿见影。边界条件则是防止模型在异常情况下乱来,前面提过的“超过多少行就暂停”就是这类。
5.3 上下文冲突与优先级
当你挂了很多 skill,或者 skill 和系统提示、项目配置之间有冲突时,模型可能无所适从。这时候要理清优先级:一般来说,越具体的指令优先级越高,项目级高于用户级,显式调用高于自动触发。
如果发现两个 skill 打架,最直接的办法是合并或者明确分工。我遇到过“代码格式化”和“代码重构”两个 skill 冲突的情况,格式化 skill 想把所有代码都按统一风格改,重构 skill 想保留原有风格只改结构。后来我把格式化从重构 skill 里剥离出去,让重构 skill 明确写“不处理格式问题,格式由专门的格式化技能负责”,冲突就解决了。
5.4 常见问题速查表
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 技能完全不触发 | 文件位置错误 | 检查项目级/用户级目录 |
| 技能偶尔触发 | 描述区分度不够 | 加入场景关键词 |
| 输出格式不对 | 输出规范缺失 | 在正文补输出模板 |
| 执行到一半停住 | 边界条件未定义 | 补充异常处理说明 |
| 多个技能冲突 | 职责重叠 | 拆分或明确分工 |
| 升级后失效 | 机制变更 | 查工具更新日志 |
6. 我对 skills 这套东西的真实看法
折腾了大半年 skills,最大的感受是:它把“调教 AI”这件事从玄学变成了工程。以前让模型听话靠的是反复试提示词,运气成分很大;现在有了结构化的技能包,经验可以沉淀、可以复用、可以传承。这对个人是效率提升,对团队是知识资产。
但也要泼盆冷水:skills 不是银弹。它擅长的是流程明确、边界清晰、重复度高的任务,比如代码规范检查、模板生成、格式转换。对于那些需要大量创造性判断、需求本身还在模糊阶段的任务,硬套 skill 反而会限制模型的发挥。我的做法是分场景用:确定性任务上 skill,探索性任务放开手让模型自由发挥。
另外,别指望写一个 skill 就一劳永逸。业务在变,规范在变,skill 也得跟着迭代。我现在保持的习惯是每个月回顾一次常用 skills,把过时的删掉,把新踩的坑补进去。这个过程本身就是在梳理团队的工作方法,收获往往超出预期。
最后分享一个我最近在试的扩展方向:把 skills 和项目的自动化流程打通,让 agent 在提交代码前自动跑一遍相关技能做自检。这个思路还在验证阶段,但初步效果不错,能拦下不少低级错误。如果你也在折腾这块,欢迎交流。