1. 从“skills”这个热词说起:它到底是什么,为什么突然火了
最近半年,不管是在技术社区还是开发者群聊里,“skills”这个词出现的频率高得离谱。你随便翻翻热搜词列表,能看到claude code、codex、agents、plugin、skills开发、codex skills、claude agent skills这些词扎堆出现。很多人第一反应是:这不就是“技能”吗,有什么好聊的?但如果你真在终端里敲过claude code,或者折腾过codex的配置,你就会明白,这里的 skills 指的是一套让 AI 编程助手真正“能干活”的能力封装机制。
我最早接触这个概念是在给团队搭内部编码助手的时候。当时我们用claude code做代码审查和重构,用codex做补全和单测生成,但很快就撞墙了——模型本身很聪明,可它不知道我们项目的目录约定、不知道我们内部 CLI 的用法、不知道我们数据库迁移的命名规范。每次都要在 prompt 里重复交代,效率极低。后来发现社区里已经有人在用 skills 的方式解决这个问题:把“怎么在这个项目里干活”的知识,写成结构化的、可被 agent 加载的模块。这就是 skills 的核心价值——它不是模型能力本身,而是模型能力的“外挂说明书 + 工具包”。
所以这篇文章我想聊的,不是某个具体产品的安装教程,而是把 skills 这套东西拆开来看:它的设计逻辑是什么、一个合格的 skill 应该包含哪些部分、怎么从零写一个能跑起来的 skill、以及在claude code、codex、agents anywhere这些不同宿主里,skills 的加载机制有什么差异。适合谁看?如果你已经在用 AI 编程工具,但觉得“它总是差那么点意思”,或者你想把团队内部的规范沉淀成可复用的资产,那这篇内容应该能帮你省下不少试错时间。
2. skills 的整体设计思路:为什么不是简单的 prompt 模板
2.1 从“一次性对话”到“可复用能力单元”的转变
很多人第一次听说 skills,会把它理解成“高级一点的 prompt 模板”。这个理解不能说错,但太浅了。普通的 prompt 模板是静态的文本,你复制粘贴到对话框里,模型读完就完了。而 skills 的关键区别在于三点:可发现、可加载、可组合。
可发现,意思是 agent 在运行过程中能主动判断“我现在需要某个 skill”,然后去查找并调用它。比如claude code在执行一个数据库迁移任务时,如果检测到项目里有db-migration这个 skill,它会自动加载相关规范,而不是等你手动提醒。可加载,意味着 skill 不是一次性塞进上下文,而是按需注入,避免把上下文窗口撑爆。可组合,则是说多个 skill 可以叠加使用,比如一个code-reviewskill 和一个security-checkskill 可以同时生效。
我实测下来,这套机制最直接的好处是:把“人脑里的隐性知识”变成了“agent 可读的显性资产”。以前你带新人,要口头交代一堆“我们项目里 API 返回格式统一用这个 wrapper”“日志必须打 traceId”“单测覆盖率低于 80% 不给合并”。现在这些都可以写进 skill,agent 每次干活都会自动遵守。
2.2 一个 skill 的最小结构:元数据 + 指令 + 资源
那一个 skill 到底长什么样?根据我在claude code和codex里的实践,一个最小可用的 skill 通常包含三部分:
- 元数据(metadata):名称、描述、触发条件、适用场景。这部分决定了 agent 什么时候会想起你。
- 指令(instructions):具体的操作规范、步骤、约束。这是 skill 的主体,通常用自然语言写,但要求足够具体。
- 资源(resources):可选的脚本、模板、配置文件、参考文档。agent 可以在执行时读取或调用。
我见过很多人写 skill 只写指令,不写元数据,结果 agent 根本不知道什么时候该用它。这就像你写了一本很好的操作手册,但放在书架最底层,没人知道它存在。元数据里的“触发条件”尤其重要,你要用 agent 能理解的方式描述“什么情况下加载我”。比如不要写“当需要处理数据库时”,而要写“当任务涉及 schema 变更、migration 文件生成、或 SQL 查询优化时”。
2.3 为什么 skills 比“塞系统提示词”更靠谱
有人会问:我直接把所有规范写进系统提示词不就行了?何必搞这么复杂?我一开始也这么想,直到系统提示词膨胀到几千字,模型开始“选择性遗忘”——前面说的规范,后面就忘了。而且系统提示词是全局的,你没法针对不同任务加载不同规范。
skills 的按需加载机制解决了这个问题。它把大块知识拆成小模块,agent 根据当前任务动态加载。这背后其实是一个很朴素的工程原则:关注点分离。代码要分模块,知识也要分模块。你写代码不会把所有逻辑塞进一个文件,那为什么要把所有规范塞进一个 prompt?
另外,skills 通常有版本管理的能力。你可以把 skill 文件放进 Git 仓库,改动了就有记录,团队可以 review。系统提示词改了什么,往往没人知道。这一点在团队协作场景里特别重要。
3. 核心细节解析:写一个能跑的 skill 要注意什么
3.1 元数据怎么写才能被 agent 正确识别
元数据是 skill 的“门面”,写得好不好直接决定它会不会被加载。我踩过的坑是:描述写得太抽象,agent 匹配不上。比如我写过一个api-designskill,描述是“帮助设计更好的 API”。结果 agent 从来不用它,因为“更好”这个词太模糊,agent 无法判断当前任务是否匹配。
后来我改成:“当任务涉及新增 REST 接口、修改请求/响应结构、或定义错误码时加载。包含本项目 API 命名规范、分页约定、错误码分段规则。” 改完之后,加载率明显上来了。所以元数据描述要满足两个条件:场景具体 + 关键词明确。你要想象 agent 是在做关键词匹配和语义匹配,它需要明确的信号。
还有一个细节是“优先级”或“互斥”声明。有些 skill 是互斥的,比如strict-mode和quick-prototype,你不可能同时用。这时候在元数据里标注清楚,避免 agent 同时加载两个冲突的规范。
3.2 指令部分的写法:具体、可执行、有边界
指令部分是 skill 的核心。我总结了一个原则:能写成检查清单的,就不要写成散文。比如不要写“代码要写得清晰易读”,而要写:
- 函数名使用动词开头,不超过 30 个字符
- 单个函数不超过 50 行,超过则拆分
- 复杂逻辑必须加注释,注释说明“为什么”而不是“做什么”
- 禁止使用魔法数字,常量必须提取并命名
这样 agent 执行起来有明确的判断标准。散文式的指令,模型解读空间太大,每次执行结果都不一样。
另外,指令里要明确“边界”。什么是这个 skill 不负责的?比如一个unit-testskill,你要写清楚“只负责生成测试代码,不负责修改被测代码”。否则 agent 可能会越界,把生产代码也改了。边界写清楚,后续排查问题也容易定位。
3.3 资源文件的组织方式与加载时机
资源文件是很多新手容易忽略的部分。我见过一个 skill 把大段 SQL 模板直接写在指令里,结果上下文被撑得很大。更好的做法是把模板放到单独的.sql文件里,指令里只写“参考templates/migration.sql的结构”。
资源文件的组织我一般按类型分目录:
my-skill/ skill.md # 元数据 + 指令 templates/ # 代码模板、配置模板 scripts/ # 可执行脚本 references/ # 参考文档、规范说明加载时机也要注意。不是所有资源都需要一开始就加载。可以在指令里写明“当需要生成 migration 时,读取templates/migration.sql”。这样 agent 只在真正用到时才读文件,节省上下文。
提示:资源文件里的内容也要保持“可被 agent 理解”。不要放二进制文件或压缩包,agent 读不了。纯文本、Markdown、代码文件是最安全的。
3.4 不同宿主对 skills 的支持差异
claude code、codex、agents anywhere这几个宿主对 skills 的支持方式不完全一样。claude code的 skills 机制相对成熟,支持目录扫描和自动加载,你只要把 skill 放在指定目录下,它就能发现。codex更偏向通过配置文件显式声明 skill 路径,加载时机也更可控。agents anywhere则强调跨平台,skill 的定义更偏向标准化格式。
我实际用下来的感受是:写 skill 时尽量保持格式中立。元数据和指令用 Markdown,资源用纯文本,这样在不同宿主之间迁移成本最低。如果你绑定了某个宿主的专有格式,换工具时就要重写,不划算。
4. 实操过程:从零写一个 code-review skill
4.1 明确目标和触发场景
假设我们要写一个code-reviewskill,用于在claude code里做代码审查。先明确目标:当 agent 收到“review 这个 PR”或“检查这段代码”的任务时,加载本 skill,按照团队规范输出审查意见。
触发场景要写具体:涉及代码 diff 分析、PR 评论生成、代码质量检查时加载。不要写“当需要审查代码时”,太笼统。
4.2 编写元数据与指令主体
元数据部分我这样写:
--- name: code-review description: 当任务涉及代码审查、PR 评论、diff 分析、代码质量检查时加载。包含团队代码规范、常见问题清单、评论格式要求。 version: 1.2 ---指令主体分几块:审查维度、严重级别定义、评论格式、禁止事项。审查维度包括命名规范、错误处理、边界条件、性能隐患、安全风险。严重级别分 blocker、major、minor、nit。评论格式要求每条意见包含“位置 + 问题 + 建议 + 示例”。
这里有个经验:严重级别定义要写清楚判断标准。比如 blocker 是“会导致线上故障或数据丢失”,major 是“违反团队强制规范”,minor 是“可优化但不影响功能”,nit 是“风格建议”。标准清楚了,agent 输出才稳定。
4.3 配置资源文件与模板
资源文件我放了两个:templates/comment.md是评论模板,references/checklist.md是详细检查清单。评论模板长这样:
**[级别] 位置** 问题:... 建议:... 示例:...检查清单里列了 30 多条常见问题,比如“是否处理了空值”“是否有未关闭的资源”“是否有硬编码密钥”。指令里写“审查时逐条对照references/checklist.md”,agent 就会去读。
4.4 在 claude code 中加载并验证效果
把 skill 目录放到claude code的 skills 路径下,然后跑一个测试任务:给它一段有明显问题的代码,看它是否加载了 skill 并按照格式输出。我第一次测试时发现它没加载,排查后发现是元数据里的 description 写得太短,匹配不上。改长之后正常了。
验证时要注意:不要只测一个案例。我一般会准备三个案例:一个明显有 blocker 的、一个只有 nit 的、一个没有问题的。看 agent 是否都能正确处理。特别是“没有问题”的案例,很多 skill 会强行找问题,这就是指令里边界没写清楚。
注意:skill 加载后,agent 的行为会变化。如果你发现它变得过于严格或过于宽松,先检查指令里的判断标准是否明确,而不是直接改模型参数。
5. 常见问题与排查技巧实录
5.1 skill 不加载或加载错误怎么办
这是最高频的问题。排查顺序我一般是这样:
- 检查元数据 description 是否包含任务关键词
- 检查 skill 目录是否在宿主扫描路径下
- 检查文件编码是否为 UTF-8,有些宿主对编码敏感
- 检查是否有语法错误,比如 YAML front matter 格式不对
我遇到过最隐蔽的一次是:skill 文件名带了空格,宿主扫描时跳过了。改成短横线连接就好了。所以文件名尽量用code-review这种格式,不要用code review。
5.2 agent 加载了 skill 但不遵守指令
这种情况通常是指令写得太模糊。比如写“注意错误处理”,agent 不知道具体要注意什么。改成“所有可能返回错误的调用必须检查返回值,并在失败时记录日志、返回统一错误码”,执行率就上去了。
另一个原因是指令太长,agent 读到后面忘了前面。解决办法是分节,每节加小标题,关键约束用加粗。或者把长指令拆成多个 skill,按需组合。
5.3 多个 skill 冲突或重复加载
当项目里 skill 多了,冲突是难免的。比如strict-mode和fast-iterate同时加载,agent 会无所适从。解决办法是在元数据里加conflicts字段,声明互斥关系。或者用优先级字段,高优先级的覆盖低优先级的。
重复加载的问题更常见:两个 skill 都涉及日志规范,agent 可能输出两套矛盾的要求。这时候要合并 skill,或者明确分工——一个管日志格式,一个管日志级别。
5.4 性能与上下文占用的平衡
skill 太多会导致上下文占用过高,agent 响应变慢。我的经验是:单个 skill 的指令部分控制在 500 字以内,资源文件按需加载。如果某个 skill 经常被用到,可以考虑把核心指令精简后常驻,详细内容放资源文件。
另外,定期清理不再使用的 skill。我每季度会 review 一次 skill 目录,把过时的、重复的删掉。这跟清理代码库是一个道理。
| 问题现象 | 可能原因 | 排查动作 | 解决方式 |
|---|---|---|---|
| skill 不加载 | 描述模糊、路径错误、编码问题 | 检查元数据、目录、编码 | 改描述、放对路径、转 UTF-8 |
| 加载但不遵守 | 指令模糊、过长、冲突 | 检查指令具体性、长度、互斥 | 改具体、拆分、加冲突声明 |
| 多个 skill 冲突 | 规范矛盾、优先级不明 | 检查重叠内容 | 合并或加优先级 |
| 上下文占用高 | skill 过多、资源过大 | 统计加载数量与体积 | 精简、按需加载、定期清理 |
5.5 几个我踩过的坑和对应技巧
第一个坑:把 skill 当成万能药。不是所有问题都适合用 skill 解决。有些是一次性任务,写个 prompt 就够了,没必要沉淀成 skill。判断标准是:这个知识会不会重复用到?会,才值得写 skill。
第二个坑:skill 写完就不管了。项目在变,规范在变,skill 也要跟着更新。我现在的做法是把 skill 放进 Git,跟代码一起 review,改代码时顺手改 skill。
第三个坑:过度依赖 skill 的自动化。skill 是辅助,不是替代。agent 加载了 skill 不代表它一定做对,关键任务还是要人工复核。我一般把 skill 当成“第一道防线”,而不是“最终保证”。
6. 从 skills 到 agents:这套机制还能怎么扩展
6.1 把 skill 组合成 agent 的工作流
单个 skill 解决单点问题,多个 skill 组合起来就能形成工作流。比如code-review+security-check+test-coverage三个 skill 串起来,agent 就能完成一次完整的 PR 审查。我在agents anywhere里试过这种组合,效果比单个 skill 好很多,因为每个 skill 专注一件事,组合起来覆盖全面。
组合的关键是定义好 skill 之间的输入输出关系。比如code-review输出问题列表,security-check接收这个列表并补充安全维度的问题。这需要在指令里写明“接收上游 skill 的输出格式”。
6.2 团队协作中的 skill 管理
团队用 skill,最大的挑战是版本一致。我见过有人本地改了 skill 没提交,导致别人跑出来的结果不一样。解决办法是:skill 跟代码同仓库,走同样的 PR 流程。另外,skill 的变更要有 changelog,写清楚改了什么、为什么改。
还有一个实践是“skill owner”制度。每个 skill 指定一个负责人,负责 review 变更和维护内容。避免出现“没人管”的 skill。
6.3 未来可能的方向
从热词里能看到agent skills测试、skills开发、claude agent skills这些词在增长,说明这个方向还在快速演化。我个人比较关注的是 skill 的“自动生成”——能不能从代码库和提交历史里自动提取规范,生成 skill 草稿。还有就是 skill 的“效果评估”,怎么量化一个 skill 到底有没有提升 agent 的输出质量。
不过这些都是后话。眼下最实在的,还是先把团队里最常用的那几个规范写成 skill,跑起来,用起来。我在实际使用中发现,哪怕只写三五个 skill,agent 的可用性就会有明显提升。踩过几次坑之后,我现在的习惯是:每遇到一个“又要重复交代”的场景,就停下来想想,这个能不能写成 skill。能,就花二十分钟写一个。积少成多,现在我的 skill 目录已经成了团队新人上手的重要参考。
最后分享一个小技巧:写 skill 时,先别追求完美。写个粗糙版本,跑几个任务,看 agent 哪里理解偏了,再针对性改。skill 是迭代出来的,不是一次写成的。我第一个 skill 改了七版才稳定,现在回头看第一版,简直没法看。但没关系,先跑起来最重要。