
1. 从“agent-skills”说起为什么我们需要给AI编码代理装上一套技能系统第一次看到agent-skills这个项目名的时候我脑子里蹦出来的不是某个具体工具而是一个很朴素的问题我们天天在用的 AI coding agents比如 Claude Code、Cursor、各种 CLI 代理它们到底缺什么答案其实不复杂——缺的是可复用、可组合、可测试的“技能”。模型本身很聪明但每次让它干一件事你都得重新描述一遍上下文、约束、验收标准这就像招了一个天才工程师但每天早上都要重新给他讲一遍公司代码规范。agent-skills想解决的就是这件事。它本质上是一套围绕 AI 编码代理构建的技能封装与调度体系核心关键词包括skills CLI、test-driven-development、Claude Code等。你可以把它理解成给代理准备的“工具箱 操作手册 质检流程”每个 skill 是一个独立的能力单元有明确的输入输出、有对应的测试用例、可以通过 CLI 被调用和组合。它适合谁适合已经在用 Claude Code 或类似代理写代码、但觉得“每次都要重复调教”的开发者也适合想把自己的工作流沉淀成标准能力、让团队共享的工程负责人。我自己的感受是单纯依赖对话式代理短期很爽长期很乱。你今天让它写个接口明天让它改个 bug后天让它补测试每次都要重新对齐风格和边界。agent-skills的价值就在于把这些重复劳动抽象成“技能”让代理从“每次现学”变成“按技能执行”。这篇文章我会从设计思路、核心细节、实操流程、常见问题几个角度把我在实际使用中踩过的坑和总结的技巧都摊开讲尽量让你看完就能上手复现。2. 整体设计与思路拆解为什么是“技能”而不是“提示词”2.1 从提示词工程到技能工程的必然演进早期我们用 AI 编码代理基本靠提示词。写一段详细的 prompt告诉它项目结构、编码规范、测试要求然后祈祷它别跑偏。但提示词有几个天然缺陷不可测试、不可复用、不可组合。你没法给一段 prompt 写单元测试也没法把“写接口”和“写测试”两个 prompt 稳定地串起来更没法保证今天有效的 prompt 明天还一样有效。agent-skills的思路是把“提示词”升级成“技能”。一个 skill 不是一段话而是一个结构化的包里面有描述、有触发条件、有执行步骤、有验收标准甚至还有配套的测试用例。这就像从“口头交代任务”变成“写一份标准作业程序SOP”。SOP 的好处是谁来执行、执行多少次结果都趋于一致。我试过把同一个需求分别用纯 prompt 和 skill 的方式交给代理纯 prompt 的产出波动很大有时多写了个没用的工具函数有时漏了边界处理而 skill 方式因为带了明确的验收条件代理会主动去检查自己有没有满足产出稳定得多。这个差异在单人项目里可能不明显但在团队协作里就是天壤之别。2.2 技能系统的三层架构描述层、执行层、验证层拆开来看agent-skills的设计大致分三层。描述层负责定义这个技能是干什么的、什么时候用、输入输出是什么通常用一份结构化的元数据文件来表达。执行层是代理真正干活的部分可能是一段脚本、一组命令、或者一段引导代理行为的指令。验证层是最容易被忽略但最关键的部分它用测试来确认技能执行结果是否符合预期这也是test-driven-development被列为关键词的原因。为什么验证层这么重要因为 AI 代理有个通病它很会“看起来完成了”。你让它写个函数它写出来了语法也对但逻辑可能是错的。没有验证层你就得人工去检查那技能化的意义就少了一半。有了验证层代理在完成技能后可以自己跑测试失败了就重试或报告形成闭环。提示设计 skill 时验证条件要尽量具体、可执行避免“代码质量好”这种模糊描述。比如“函数对空输入返回默认值”就比“处理边界情况”强得多。2.3 为什么选择 CLI 作为主要交互方式skills CLI是这个项目里另一个核心点。为什么不是 GUI不是插件而是 CLI我的理解是AI 编码代理的主战场就在终端里。Claude Code 本身就是终端优先的工具开发者的很多操作也在命令行完成。CLI 的好处是可脚本化、可组合、可版本控制。你可以把 skill 的调用写进 CI 流程可以用管道把多个 skill 串起来也可以用 git 管理 skill 的变更历史。相比之下GUI 虽然直观但很难自动化插件虽然集成度高但受限于宿主环境。CLI 是最“中性”的接口它不挑编辑器、不挑操作系统Ubuntu、macOS 都能跑。我在 Ubuntu 和 macOS 上都试过只要 Node 环境正常skills命令的行为基本一致这对跨平台团队很友好。2.4 与 Claude Code 等代理的协作关系需要明确一点agent-skills不是要替代 Claude Code而是增强它。Claude Code 负责理解意图、生成代码、执行命令agent-skills负责提供结构化的能力包和验证机制。两者是互补的。你可以把 skill 看成给 Claude Code 准备的“外挂知识库 质检员”。实际使用中我通常会让 Claude Code 先加载相关的 skill 描述然后按 skill 的步骤执行最后跑 skill 自带的测试。这样代理的行为就被约束在一个可预期的范围内而不是自由发挥。对于团队来说这意味着新人用同样的 skill产出的代码风格和质量能和老手接近降低了协作成本。3. 核心细节解析与实操要点一个 skill 到底长什么样3.1 技能目录结构与元数据设计一个标准的 skill 通常是一个独立目录里面至少包含描述文件、执行逻辑和测试。我参考常见实践给出一个比较通用的结构my-skill/ skill.json # 元数据名称、描述、触发条件、输入输出 steps.md # 执行步骤说明供代理阅读 run.sh # 可选的执行脚本 tests/ test_basic.sh # 验证脚本skill.json是核心它决定了这个技能什么时候被激活。里面一般会有name、description、triggers、inputs、outputs、validation这些字段。triggers可以是关键词也可以是文件类型或命令模式。比如一个“生成单元测试”的 skilltrigger 可以设置为“当用户要求补测试时”。这里有个经验描述要写给代理看不是写给人看。人看描述能脑补代理不能。所以描述里要明确“做什么、不做什么、成功标准是什么”。我见过有人把描述写成一句话“处理用户请求”结果代理根本不知道什么时候该用形同虚设。3.2 触发条件与上下文注入的平衡触发条件设计是个技术活。太宽泛代理动不动就调用干扰正常流程太狭窄该用的时候用不上。我的做法是用组合条件既要有正向触发词也要有排除条件。比如“当用户提到‘测试’且当前目录存在源码文件时触发”这样能过滤掉纯文档场景。上下文注入也很关键。代理执行 skill 时需要知道项目结构、依赖、已有代码风格。这些信息不能靠代理自己猜要在 skill 里显式声明需要读取哪些文件。我通常会让 skill 先执行一个“上下文收集”步骤把关键文件列出来再进入正式执行。这样代理的每一步都有依据不会凭空发挥。注意上下文注入要控制规模。一次性塞太多文件代理的注意力会被稀释反而容易忽略重点。我一般限制在 5 到 10 个关键文件以内。3.3 测试驱动开发在技能系统中的落地方式test-driven-development在这里不是口号而是具体的操作顺序。写一个 skill 时我会先写验证脚本再写执行步骤。验证脚本描述“什么样算成功”执行步骤描述“怎么做到”。这个顺序逼着我把验收标准想清楚而不是先写一堆步骤再补测试。举个例子我要做一个“给函数补类型注解”的 skill。验证脚本会检查目标函数是否都有类型注解、注解是否与返回值匹配、是否引入了必要的 import。执行步骤则引导代理去读函数、推断类型、添加注解。先写验证的好处是代理在执行时能明确知道终点在哪不会过度修改。实测下来先写测试的 skill 成功率明显高于后补测试的。因为后补测试时执行步骤已经定型测试往往变成“迁就现有实现”而不是“定义正确行为”。3.4 技能组合与依赖管理单个 skill 能力有限真正强大的是组合。agent-skills支持 skill 之间声明依赖比如“生成接口”依赖“生成数据模型”“生成测试”依赖“生成接口”。依赖关系让代理能按正确顺序执行不会出现先写测试后写实现的倒置。依赖管理要注意循环依赖。A 依赖 BB 又依赖 A代理就会卡住。我的做法是画一张依赖图确保是单向的。如果确实需要互相调用就抽出一个更基础的 skill 作为共同依赖。另外依赖的版本也要管skill 升级后可能影响下游最好在元数据里标注兼容版本。4. 实操过程与核心环节实现从零搭一个可用的 skill4.1 环境准备与 skills CLI 初始化先确认基础环境。Node 版本建议 18 以上skillsCLI 通过包管理器安装。Ubuntu 和 macOS 的步骤略有差异但核心一致。安装完成后用skills init初始化一个技能目录CLI 会生成模板文件。# 安装 CLI示例具体以官方文档为准 npm install -g skills-cli # 初始化一个技能 skills init my-first-skill cd my-first-skill初始化后会得到skill.json、steps.md和tests/目录。我建议先别急着改跑一遍skills validate确认模板本身是通的再动手。这一步能排除环境问题避免后面把环境错误当成技能逻辑错误。4.2 编写第一个技能以“自动补全单元测试”为例我拿一个真实场景来演示给一个已有的 JavaScript 函数补单元测试。先写验证脚本检查测试文件是否存在、是否覆盖了主要分支、是否能跑通。#!/bin/bash # tests/test_basic.sh set -e TEST_FILEsrc/utils.test.js if [ ! -f $TEST_FILE ]; then echo 测试文件不存在 exit 1 fi npx jest $TEST_FILE --silent echo 测试通过然后写steps.md引导代理读取目标函数、识别分支、生成测试用例、运行验证。skill.json里把 trigger 设为“当用户要求补测试且存在未测试函数时”。这里的关键是让代理先读再写。我试过直接让代理生成测试结果它经常假设函数行为写出来的测试和实际不符。加上“先读函数源码”这一步后准确率提升明显。4.3 参数计算与阈值选择以“代码复杂度检查”技能为例有些 skill 涉及数值判断比如复杂度检查。这里要选阈值。圈复杂度Cyclomatic Complexity常用阈值是 10超过就提示重构。为什么是 10这是业界长期实践的经验值超过 10 的函数通常难以测试和维护。但这个值不是绝对的对业务逻辑密集的代码可以放宽到 15。我在 skill 里会把这个阈值做成可配置项默认 10允许项目覆盖。计算方式是基于 AST 统计分支节点数。代理执行时先解析代码算出每个函数的复杂度超过阈值的列出来并给出重构建议。验证脚本则检查输出是否包含所有超标函数。提示阈值类参数一定要可配置不同项目、不同语言的最佳值不一样。硬编码的阈值迟早会变成噪音。4.4 完整执行流程与现场记录把上面的环节串起来一次完整的 skill 执行大致是这样代理接收到用户请求匹配到对应 skill读取skill.json确认触发条件按steps.md逐步执行中途调用run.sh完成具体操作最后跑tests/验证。如果验证失败代理会根据失败信息重试或报告。我在实际跑“补测试”技能时记录过一次过程代理先列出未测试函数然后逐个生成测试跑验证发现有一个测试因为异步处理失败它自动调整了 await 的位置再次验证通过。整个过程没有人工干预。这说明只要验证脚本写得够细代理的自纠错能力是能发挥出来的。5. 常见问题与排查技巧实录5.1 技能不触发或误触发怎么办这是最常见的问题。不触发通常是 trigger 写得太窄或者描述文件没被正确加载。排查时先确认skills list能看到这个技能再用skills match 你的请求看匹配结果。如果匹配为空就放宽 trigger。误触发则相反通常是 trigger 太宽泛加排除条件即可。我踩过的一个坑是trigger 里用了中文关键词但代理的匹配逻辑对中文分词支持不好导致时灵时不灵。后来改成中英文都写稳定性就上来了。5.2 验证脚本失败但代码看起来没问题这种情况多半是验证脚本本身有 bug或者环境不一致。先手动跑一遍验证脚本确认它在当前环境能通过。如果手动能过、代理跑不过可能是代理执行时的环境变量或工作目录不同。在 skill 里显式声明工作目录和环境变量能解决大部分问题。还有一种可能是测试有副作用比如依赖外部服务。这种测试不适合放在 skill 验证里应该 mock 掉。验证脚本要尽量纯粹只依赖本地代码。5.3 技能执行超时或卡死超时通常是因为 skill 里的某一步在等待输入或者陷入了循环。检查steps.md里有没有“等待用户确认”这类步骤代理环境下这类步骤容易卡住。改成自动判断或设置默认值。循环则多半是依赖关系没理清用skills graph看依赖图找出环并打破。5.4 常见问题速查表问题现象可能原因排查方法解决方向技能不触发trigger 过窄或描述未加载skills match测试放宽 trigger检查加载误触发频繁trigger 过宽查看匹配日志加排除条件验证失败但代码正常验证脚本或环境问题手动跑验证脚本固定环境变量和工作目录执行超时等待输入或死循环检查 steps 和依赖图去掉交互步骤打破循环组合技能顺序错乱依赖声明缺失skills graph补依赖声明5.5 独家避坑技巧第一个技巧给 skill 加版本号。技能会迭代旧版本可能被其他技能依赖。没有版本号升级就是灾难。第二个技巧验证脚本要能独立运行不要依赖代理的中间产物否则排查时无从下手。第三个技巧skill 描述里写清楚“不做什么”这比写“做什么”更能约束代理行为。我试过在描述里加一句“不要修改测试文件以外的文件”代理的越界行为明显减少。6. 技能系统的扩展与团队协作实践6.1 把个人技能沉淀为团队资产一个人用 skill 是效率工具一个团队用 skill 就是资产。我们团队的做法是建一个共享的 skill 仓库每个人把自己常用的技能提交上去经过评审后合并。评审重点看验证脚本是否充分、描述是否清晰、依赖是否合理。合并后的 skill 通过内部 CLI 分发新人入职第一天就能用上老手沉淀的能力。这个过程中最大的阻力不是技术而是习惯。很多人觉得“我自己写 prompt 更快”不愿意花时间封装。我的应对方式是先做几个高频场景的 skill让大家尝到甜头比如“生成 CRUD 接口”“补测试”“格式化提交信息”。用顺了之后大家自然会想把自己的经验也封装进去。6.2 技能与 CI 流程的集成skill 的验证脚本天然适合放进 CI。每次提交代码CI 可以跑一遍相关 skill 的验证确保技能产出的代码符合标准。更进一步可以把 skill 本身也纳入 CI每次修改 skill 就自动跑它的测试防止技能退化。我在项目里配过这样的流程PR 触发后先跑 skill 的单元测试再跑 skill 作用于示例代码的集成测试。两层都过才允许合并。这样 skill 的质量就有了保障不会出现“昨天还能用今天就不行”的情况。6.3 面向不同代理的适配策略虽然agent-skills和 Claude Code 配合得很好但团队里可能有人用别的代理。适配的关键是把技能逻辑和代理接口解耦。steps.md用自然语言写任何能读文本的代理都能执行run.sh用标准 shell任何能跑命令的代理都能调用验证脚本用通用测试框架不绑定特定代理。这样换代理时技能本身不用大改。我试过把同一套 skill 分别给两个不同的代理用只要代理能读文件、能执行命令基本都能跑通。差异主要在代理对自然语言步骤的理解程度上这可以通过把步骤写得更细来弥补。6.4 技能库的长期维护心得技能库用久了会膨胀需要定期清理。我的做法是每季度 review 一次看哪些技能调用频率低、哪些验证经常失败、哪些已经被更好的技能替代。低频且不稳定的直接归档避免干扰代理的匹配。另外技能之间的依赖要定期检查防止某个基础技能升级后下游全挂。还有一点技能描述要随项目演进更新。项目结构变了、规范变了技能描述不更新代理就会按旧规则执行产出过时代码。我把技能描述的更新纳入代码评审清单改项目结构时必须同步改相关技能。7. 我对 agent-skills 的实际体会与后续玩法用了一段时间agent-skills我最大的体会是它把 AI 编码从“对话”变成了“工程”。对话是随性的工程是可重复的。当你把重复劳动封装成技能代理就从“每次都要重新沟通的临时工”变成了“按标准流程作业的熟练工”。这个转变在个人项目里可能只是省点时间在团队项目里就是质量和效率的双重提升。后续我打算尝试的方向有两个。一是把技能和代码生成模板结合让技能不仅能改代码还能生成新模块的骨架。二是探索技能的自动发现让代理根据当前任务自动推荐相关技能而不是等用户显式调用。这两个方向都还在试验阶段等有稳定结果再分享。如果你也在用 Claude Code 或类似代理我建议从一个小技能开始比如“自动补测试”或“格式化提交信息”先跑通整个流程再逐步扩展。别一上来就搞大而全的技能库那样容易在细节里迷失。先让一个技能稳定工作比十个半成品有用得多。