1. 从“skills”这个标题说起:它到底指什么
第一次看到“skills”这个标题,很多人会以为是某个招聘网站上的技能标签,或者是一份简历里的能力清单。但结合热搜词里的 Agent Skills、Google Cloud、npx、AI agents、claude agent skills、codex skills 这些词来看,这里说的“skills”其实是一个在 AI 智能体生态里越来越重要的概念——给 AI Agent 装配的可复用能力模块。
你可以把它理解成给一个刚入职的实习生发的“操作手册加工具箱”。Agent 本身有推理能力,但它不知道你们公司内部系统怎么登录、不知道某个 API 的鉴权方式、不知道生成一份周报要遵循什么格式。Skills 就是把这些“隐性知识”和“固定流程”打包成一个个独立单元,让 Agent 在需要的时候自己加载、自己调用。
这个内容能做什么?简单说,它让 AI Agent 从“什么都能聊两句”变成“某件事真的能干活”。适合谁来参考?三类人:一是正在做 AI Agent 应用开发的前端或全栈工程师;二是想把日常重复工作自动化的技术爱好者;三是需要给团队搭建内部 Agent 能力库的技术负责人。哪怕你之前只写过业务代码、没接触过 Agent 框架,只要你会用命令行、看得懂 JSON 或 YAML,这篇内容里的思路和步骤你都能直接拿去用。
我自己的感受是,skills 这个概念真正有意思的地方不在于“多了一个配置文件”,而在于它把能力边界这件事显式化了。以前我们写 prompt 是“求”模型做对,现在写 skill 是“规定”模型怎么做。这个转变,才是它值得花时间研究的原因。
2. 核心思路拆解:为什么是 Skills 而不是继续堆 Prompt
2.1 从 Prompt 工程到 Skill 工程的必然过渡
早期大家用 AI Agent,基本靠一段长长的 system prompt 把角色、规则、输出格式全塞进去。我试过写过一个两千字的 prompt 让 Agent 帮我处理数据清洗,刚开始效果还行,但只要任务稍微复杂一点,模型就开始“忘事”——前面说的格式要求,到后面就丢了。这不是模型笨,是上下文窗口里信息密度太高,注意力被稀释了。
Skills 的思路完全不同。它把一个大而全的 prompt 拆成若干个小而专的能力单元,每个单元只负责一件事,并且带有明确的触发条件和执行步骤。Agent 在运行时根据当前任务去“检索”需要哪些 skills,然后按需加载。这就像你不需要把整本员工手册背下来,只需要在遇到具体问题时翻到对应那一页。
从工程角度看,这个设计解决了三个实际问题。第一是可维护性:某个流程变了,只改对应的 skill 文件,不用动整个 prompt。第二是可测试性:每个 skill 可以单独验证输入输出,而不是只能端到端测整个 Agent。第三是可组合性:不同项目可以复用同一批 skills,就像前端项目复用 npm 包一样。
2.2 Skills 的典型结构:一个 Skill 里到底装了什么
虽然不同平台和框架对 skill 的定义略有差异,但一个标准的 skill 通常包含以下几个部分。我用一个“生成周报”的 skill 来举例说明。
元信息部分负责告诉 Agent 这个 skill 是干什么的、什么时候该用它。通常包括 name、description、trigger 条件。description 写得越具体,Agent 判断是否调用它就越准。我见过很多人 description 只写“处理数据”,结果 Agent 在完全不相关的场景也去调它,这就是描述太模糊的代价。
指令部分是核心,用自然语言写清楚执行步骤。注意这里不是写代码,而是写“给人看也能看懂”的操作说明。比如“第一步,从指定目录读取本周的 commit 记录;第二步,按模块分组统计变更行数;第三步,用 Markdown 表格输出”。步骤要细到即使换一个模型来执行也不会跑偏。
资源部分是可选的,包括脚本文件、模板文件、参考数据等。比如周报 skill 可以带一个 Markdown 模板文件,Agent 直接填充内容即可,不用每次自己编格式。这一步能大幅提升输出稳定性。
示例部分也很关键。给一两个输入输出样例,相当于给 Agent 做了 few-shot 演示。实测下来,带示例的 skill 比不带示例的 skill,首次执行成功率能高出不少。
2.3 为什么现在值得投入时间学 Skills
热搜词里出现了“claude agent skills: a first principles deep dive”“codex skills”“github skills”这些,说明主流 AI 工具链都在往这个方向走。背后的逻辑是:Agent 的竞争力正在从模型能力转向能力组织方式。模型本身越来越强,但强模型如果没有好的能力编排,依然干不了复杂活。
另一个现实原因是,skills 让非算法背景的开发者也能参与 Agent 建设。你不需要训练模型,不需要调参,只需要把你熟悉的业务流程写成结构化的 skill 文件。这对前端开发者尤其友好——我们本来就擅长写模块、写配置、写文档,这些技能直接迁移过来就能用。
注意:不要把 skill 写成“万能助手”式的描述。一个 skill 只解决一类问题,边界越清晰,Agent 调用越准确。我踩过的坑就是试图用一个 skill 覆盖“所有文档处理”,结果它在每种文档上都表现平平。
3. 实操环境准备:从零搭起一个可用的 Skills 工作台
3.1 工具链选型与安装
要跑通 skills 的完整流程,你需要三样东西:一个支持 skills 机制的 Agent 运行环境、一个包管理工具(npx 是最常见的选择)、以及一个存放 skill 文件的目录结构。
npx 在这里的角色是快速拉起工具和安装依赖。热搜词里出现“npx playwright install失败”,说明很多人在用 npx 装浏览器自动化相关的依赖。如果你也要做涉及网页操作的 skill,Playwright 是绕不开的。安装失败最常见的原因是网络下载超时,解决办法是设置国内镜像源,或者手动下载浏览器二进制包放到缓存目录。
具体操作上,先确认 Node.js 版本。我建议用 18 以上的 LTS 版本,太老的版本对 ESM 模块支持不好,而很多 skill 工具链已经全面转向 ESM。用node -v看一眼,如果低于 18,先去升级。
然后初始化项目目录。我的习惯是建一个agent-workspace作为根目录,里面分三个子目录:skills/放 skill 文件,scripts/放辅助脚本,logs/放运行日志。这个结构不是强制的,但后面 skill 多了之后你会感谢自己一开始就分了类。
3.2 Skill 文件的目录规范与命名约定
一个 skill 在文件系统里通常是一个独立文件夹,文件夹名就是 skill 的标识符。命名建议用 kebab-case,比如generate-weekly-report、fetch-api-data、validate-json-schema。不要用中文名,也不要用空格,因为很多工具在解析路径时对特殊字符处理不一致。
文件夹内部,至少有一个入口文件,通常是SKILL.md或skill.yaml。前者用 Markdown 写指令,后者用 YAML 写结构化配置。我个人更倾向 Markdown,因为写起来自由,而且可以直接在编辑器里预览。
如果 skill 需要附带脚本,放在同目录的scripts/子文件夹里。需要模板就放templates/,需要参考数据就放references/。这种“自包含”的设计让 skill 可以整个文件夹复制到另一个项目里直接用,不用改路径。
提示:skill 文件夹里不要放敏感信息,比如 API key、数据库密码。这些应该通过环境变量注入,skill 文件里只写“从环境变量 XXX 读取”。我见过有人把 token 直接写在 skill 里然后提交到仓库,这是大忌。
3.3 验证环境是否就绪
装完之后别急着写复杂 skill,先做一个最小验证。建一个hello-skill文件夹,里面放一个最简单的 SKILL.md,内容就是“当用户说‘打个招呼’时,输出‘你好,skill 已加载’”。然后启动 Agent,输入触发词,看它是否能正确调用。
这一步的目的是确认三件事:Agent 是否能发现 skill 目录、是否能解析 skill 文件、是否能按指令执行。任何一环出问题,后面写再多 skill 都是白费。我自己的经验是,环境问题占新手失败原因的一半以上,先把这条路走通,后面就顺了。
如果 Agent 没有反应,按这个顺序排查:先看 skill 目录路径是否配置正确,再看文件编码是否是 UTF-8,然后看触发词是否和 description 匹配。大部分问题出在路径配置上,尤其是用相对路径时,Agent 的工作目录可能和你终端所在目录不一致。
4. 从零写一个可用的 Skill:完整流程与关键细节
4.1 需求拆解:先想清楚“谁在什么情况下要做什么”
写 skill 之前,先用一句话把需求说清楚。格式是:当 [触发条件] 时,执行 [具体动作],输出 [预期结果]。比如“当用户要求整理本周代码提交时,读取 git log,按模块分组,输出 Markdown 表格”。
这句话里的每个部分都会直接影响 skill 的写法。触发条件决定 description 怎么写,具体动作决定指令步骤怎么拆,预期结果决定要不要带模板和示例。我见过很多人跳过这一步直接写文件,结果写到一半发现逻辑理不顺,又回头改,反而更慢。
拆解的时候还要考虑边界情况。比如 git log 读不到怎么办?提交记录为空怎么办?模块名识别不出来怎么办?这些不一定要在 skill 里全部处理,但你要心里有数,至少在指令里写一句“如果读取失败,输出错误原因并停止”。
4.2 编写 SKILL.md:指令部分的写法与避坑
指令部分我建议用有序列表,一步一行,每行只做一件事。不要写成一大段话,模型解析列表比解析段落更稳定。下面是一个简化示例的结构:
--- name: generate-weekly-report description: 当用户要求生成周报或整理本周工作时使用 trigger: 周报, weekly report, 本周总结 --- ## 执行步骤 1. 运行 `git log --since="7 days ago" --pretty=format:"%h %s"` 获取本周提交 2. 按提交信息中的模块前缀分组,前缀格式为 `[模块名]` 3. 统计每个模块的提交数量 4. 按以下模板输出: | 模块 | 提交数 | 主要变更 | |------|--------|----------| | ... | ... | ... | ## 注意事项 - 如果 git log 无输出,回复“本周暂无提交记录” - 模块名前缀识别失败时,归入“其他”分类这里有几个细节值得说。frontmatter 里的 description 要写“什么时候用”,不是“这个 skill 是什么”。trigger 里中英文都写上,因为用户可能混用。指令里的命令要写完整,不要写“获取提交记录”这种模糊描述,模型不知道用什么命令。
注意:指令里不要写“尽量”“尽可能”这类模糊词。Agent 对模糊词的处理很不稳定,要么写“必须”,要么写“如果 X 则 Y”。我早期写过一个 skill 里用了“尽量简洁”,结果模型有时候输出三行,有时候输出三十行。
4.3 添加示例与模板:让输出稳定下来的关键一步
示例部分放在指令后面,用“输入示例”和“输出示例”成对出现。示例不用多,一到两组就够,但要覆盖典型场景。比如周报 skill 的示例可以是一组有三条提交记录的输入,对应一个两行表格的输出。
模板文件放在templates/目录里,在指令中引用路径。模板的好处是格式完全可控,模型只负责填内容,不负责编格式。我实测下来,带模板的 skill 输出格式一致性能到九成以上,不带模板的可能只有六七成。
如果 skill 涉及代码生成,示例里最好包含一段完整的代码块,让模型知道你要的代码风格。比如你要 Python 代码,示例里就写 Python,不要写伪代码。模型会模仿示例的风格,这一点在多次实测中都很明显。
4.4 本地测试与迭代:怎么判断一个 Skill 写好了
测试分三轮。第一轮测触发:用不同的说法输入,看 Agent 是否都能正确调用这个 skill。比如“帮我写周报”“整理一下本周工作”“生成 weekly report”,三种说法都应该触发。
第二轮测执行:在正常输入下,看输出是否符合预期。重点看格式是否和模板一致、数据是否准确、边界情况是否处理了。
第三轮测异常:故意给错误输入,比如在一个没有 git 仓库的目录下调用,看 Agent 是否按指令里的异常处理逻辑执行。这一轮最能暴露问题,也最容易被跳过。
迭代的时候每次只改一个地方,改完重新测。同时改多处,出了问题你不知道是哪处引起的。我自己的习惯是给每个 skill 建一个CHANGELOG.md,记录每次改了什么、为什么改,后面 skill 多了之后回头查很方便。
5. 常见问题与排查技巧实录
5.1 Skill 不被触发或触发错误
这是最高频的问题。表现是 Agent 要么不调用 skill,要么在不该调用的时候调用。原因通常有三个:description 太模糊、trigger 词覆盖不全、或者有多个 skill 的 description 重叠。
排查方法是把 Agent 的决策日志打开,看它在判断时匹配到了哪些 skill。如果发现两个 skill 的 description 相似度很高,就要把它们的边界重新划清楚。比如“处理文档”和“处理 Markdown 文档”就会打架,后者应该改成“当输入文件扩展名为 .md 时使用”。
另一个技巧是在 description 里加入“不适用场景”。比如“本 skill 仅用于周报生成,不用于日报或月报”。这种负向描述能有效减少误触发。
5.2 执行结果不稳定或格式跑偏
同一个 skill,有时候输出很规范,有时候格式就乱了。这通常是因为指令里的约束不够硬。解决办法是把格式要求写成模板文件,让模型填充而不是生成。如果不能用模板,就在指令里用“必须”“严格按以下格式”这类强约束词,并且把格式示例放在指令紧邻的位置。
还有一个原因是上下文太长。如果 Agent 在一次对话里加载了太多 skill,注意力会被分散。这时候可以考虑把大 skill 拆成小 skill,或者限制单次加载的 skill 数量。
5.3 依赖安装失败与路径问题
热搜词里“npx playwright install失败”是个典型。这类问题的排查顺序是:先看网络是否能访问下载源,再看磁盘空间是否足够,然后看 Node 版本是否兼容。如果都正常,尝试清除缓存重装。
路径问题更隐蔽。skill 里引用的脚本路径,在不同运行环境下可能解析成不同的绝对路径。我的做法是统一用相对于 skill 目录的路径,并且在指令里写明“脚本位于本 skill 目录下的 scripts/ 子目录”。这样无论 Agent 的工作目录在哪,都能正确定位。
5.4 常见问题速查表
| 问题现象 | 可能原因 | 排查动作 | 解决方向 |
|---|---|---|---|
| Skill 不触发 | description 模糊 | 查看决策日志 | 细化 description,加负向描述 |
| 触发错误 skill | 多个 skill 描述重叠 | 对比 description | 重新划分边界 |
| 输出格式乱 | 缺少模板或约束 | 检查指令 | 加模板文件,用强约束词 |
| 脚本找不到 | 路径解析错误 | 打印实际路径 | 改用相对 skill 目录的路径 |
| 依赖安装失败 | 网络或版本问题 | 检查网络和 Node 版本 | 换源或升级 Node |
| 执行超时 | 步骤太多或外部调用慢 | 看日志定位慢步骤 | 拆分 skill 或加超时处理 |
提示:每次遇到新问题,解决后把现象和方案记到速查表里。三个月后你会拥有一份比任何官方文档都贴合自己环境的排查手册。
6. Skills 的进阶玩法与能力扩展
6.1 Skill 组合:让多个能力串成一条流水线
单个 skill 解决单点问题,但真实任务往往是多步的。比如“抓取数据 → 清洗 → 生成报告 → 发送通知”就是四个 skill 串联。Agent 框架通常支持在指令里引用其他 skill,格式类似“调用 skill: fetch-data”。
组合的时候要注意数据传递。上一个 skill 的输出格式,要能被下一个 skill 的输入解析。我的做法是在每个 skill 的指令里明确写出“输入格式”和“输出格式”,组合时先检查两者是否匹配。不匹配就在中间加一个转换 skill,不要硬塞。
另一个经验是给组合流程加一个“总控 skill”,只负责编排顺序和错误处理,具体干活交给子 skill。这样流程变了只改总控,子 skill 可以复用。
6.2 把 Skill 当成团队资产来管理
当 skill 数量超过十个,就需要考虑版本管理和共享机制。最简单的做法是用 git 仓库管理 skills 目录,每个 skill 一个文件夹,改动走 commit。团队里谁写了好用的 skill,提交上来大家都能用。
更进一步可以给 skill 加版本号,在 frontmatter 里写version: 1.2.0。当某个 skill 的接口变了,依赖它的组合流程要同步更新。这跟管理 npm 包的思路是一样的,只是规模小很多。
我还见过把 skill 发布到内部 registry 的做法,用类似npx install-skill <name>的方式分发。这对大团队有价值,小团队用 git submodule 就够了。
6.3 从“能用”到“好用”:持续优化的几个方向
第一是减少人工确认环节。初期为了安全,很多 skill 会在关键步骤前问用户“是否继续”。用久了之后,可以把确认条件收窄,只在真正有风险的步骤才问。
第二是增加自检逻辑。在 skill 指令末尾加一步“检查输出是否满足以下条件”,不满足就重试或报错。这能显著降低人工检查成本。
第三是收集使用数据。记录每个 skill 的调用次数、成功率、平均耗时,据此决定优化优先级。调用多但成功率低的 skill,就是最值得投入时间改进的。
7. 我在这条路上踩过的坑与真实体会
最开始我写 skill 的时候,总想一次写完美,结果一个 skill 改了十几版还是不满意。后来想通了,skill 是长出来的,不是设计出来的。先写一个能跑的最小版本,用起来,遇到问题再改,这样迭代速度反而快得多。
另一个坑是过度抽象。我试过把好几个 skill 的公共部分抽成一个“基础 skill”,结果每个具体 skill 都要先加载基础 skill,链路变长,调试变难。后来我放弃了这种抽象,宁可每个 skill 里有一点重复,也要保持独立可测。重复的成本远低于耦合的成本。
还有一个体会是关于文档的。skill 写多了之后,最大的成本不是写,而是找。哪个 skill 是干什么的、什么时候该用哪个,如果没有一份索引,自己都会忘。所以我现在每加一个 skill,就同步更新一份SKILLS_INDEX.md,按场景分类列出所有 skill 的名称和一句话说明。这份索引后来成了团队里被翻得最多的文件。
最后分享一个小技巧:给 skill 写 description 的时候,想象你在跟一个刚来的同事说话。你会怎么跟他描述“什么时候该找你要这个东西”?把这句话直接写进去,通常就是最好的 description。不用追求术语精确,追求的是“对方能听懂”。