
1. agent-skills 到底在解决什么问题第一次看到agent-skills这个词很多人会以为它又是一个新的 AI 框架或者某个大模型的插件市场。实际上它更像是一套给 AI coding agent 用的“技能说明书集合”——把常见的开发任务拆成一个个可复用的技能单元让 agent 在写代码、跑测试、改 bug 的时候有章可循而不是每次都靠临场发挥。我最初接触这个概念是在折腾 Claude Code 的时候。当时我让它帮我改一个 Node.js 项目的接口结果它上来就把整个文件重写了测试全挂。后来我才意识到问题不在于模型能力不够而在于我没有给它一套明确的“技能约束”——比如“改代码前先跑测试”“每次只改一个函数”“改完必须验证”。agent-skills要做的就是把这些约束和流程沉淀成结构化的技能定义让 agent 按照固定的套路干活。这套东西适合谁如果你只是偶尔用 AI 补全几行代码那可能感受不深。但如果你已经在用 Claude Code、Cursor、Copilot 这类工具做完整的项目开发或者正在搭建自己的 agent 工作流那agent-skills的思路就非常值得研究。它解决的核心问题是如何让 AI agent 的行为可预测、可复用、可验证而不是每次都要靠长篇大论的 prompt 去“哄”它。关键词里提到的test-driven-development、skills CLI、AI coding agents其实都指向同一个方向把软件工程里成熟的实践比如 TDD、代码审查、增量修改翻译成 agent 能理解的技能格式然后通过命令行工具去管理和调用。下面我会从实际使用的角度把这套东西拆开讲清楚。2. 技能文件的结构与编写逻辑2.1 一个技能单元包含哪些字段agent-skills的核心载体是技能文件通常是一个 Markdown 或者 YAML 格式的文档。我见过几种不同的组织方式但万变不离其宗一个完整的技能定义一般包含这几个部分技能名称与触发条件告诉 agent 什么情况下该用这个技能。比如“当用户要求修改现有函数时触发”。前置检查执行前必须确认的事情。比如“确认当前分支干净”“确认测试全部通过”。执行步骤具体的操作流程一步一步写清楚。这部分是技能的主体。验证标准怎么判断这个技能执行成功了。比如“所有测试通过”“lint 无报错”。回滚方案如果执行失败怎么恢复到之前的状态。我自己的习惯是用 Markdown 写技能因为可读性好agent 解析起来也方便。下面是一个简化版的技能文件示例场景是“安全地修改一个已有函数”# Skill: safe-function-modify ## 触发条件 用户要求修改某个已存在的函数且该函数有对应的单元测试。 ## 前置检查 - 运行 git status确认工作区干净 - 运行 npm test确认当前测试全部通过 ## 执行步骤 1. 定位目标函数及其测试文件 2. 先修改测试文件补充或调整测试用例 3. 运行测试确认新测试失败红 4. 修改函数实现使其通过测试绿 5. 运行完整测试套件确认无回归 ## 验证标准 - 新增测试通过 - 原有测试无失败 - lint 检查无新增错误 ## 回滚方案 如果验证失败执行 git checkout -- . 恢复到修改前状态。这个结构看起来简单但实际写起来有很多讲究。最关键的是执行步骤必须足够具体不能有歧义。我一开始写技能的时候喜欢用“优化代码结构”这种模糊表述结果 agent 理解成了重写整个模块。后来改成“将函数内重复的字符串拼接提取为常量”行为就稳定多了。2.2 为什么技能要写成“检查-执行-验证”三段式这个结构不是拍脑袋想出来的它对应的是软件工程里最基本的质量控制循环。前置检查是为了确保起点状态可控执行步骤是为了让操作可复现验证标准是为了让结果可判断。三者缺一不可。我踩过的一个坑是只写了执行步骤没写前置检查。结果 agent 在一个有未提交更改的分支上直接改代码改完发现测试挂了想回滚都回滚不了因为分不清哪些改动是它做的、哪些是我之前留下的。从那以后我每个技能文件里都会强制加上git status检查。另一个坑是验证标准写得太宽松。比如只写“代码能运行”结果 agent 改完代码确实能跑但性能下降了十倍。后来我把验证标准细化成“单元测试通过 基准测试耗时不超过原值 120%”问题就解决了。提示技能文件里的每一步都应该是可执行的命令或者可观察的状态避免写“确保代码质量良好”这种无法验证的描述。2.3 技能之间的依赖与组合单个技能能解决的问题有限真正好用的时候是把多个技能串起来。比如“新增一个 API 接口”这个任务可以拆成create-route→create-controller→create-test→run-integration-test四个技能依次执行。这里有个设计上的取舍是把所有步骤写在一个大技能里还是拆成多个小技能我的经验是如果一个步骤可以独立验证就把它拆出来。因为独立技能可以在不同场景下复用而且出问题的时候容易定位是哪一步挂了。但拆得太细也有问题。我曾经把一个数据库迁移任务拆成了十几个技能结果 agent 在执行过程中频繁切换上下文反而容易出错。后来我总结了一个原则单个技能的执行时间控制在 2-5 分钟以内太短了切换成本高太长了出错难排查。3. 用 skills CLI 管理技能库的实操细节3.1 安装与初始化skills CLI是配套的命令行工具用来管理本地的技能库。安装方式通常是通过包管理器比如 npm 或者 brew。我是在 macOS 上用的命令大概是npm install -g agent-skills/cli安装完之后在项目根目录执行初始化skills init这个命令会创建一个.skills目录里面包含默认的技能模板和配置文件。配置文件一般是skills.config.json用来指定技能库的路径、默认的 agent 类型、以及一些全局参数。我建议在初始化之后先跑一遍skills list看看默认带了哪些技能。通常会有一些通用的技能比如code-review、write-test、refactor之类的。这些默认技能可以直接用也可以根据自己的项目特点修改。3.2 技能库的目录组织随着技能越来越多目录结构就变得很重要。我试过几种组织方式最后稳定下来的是按“领域 动作”两层分类.skills/ ├── backend/ │ ├── create-api.md │ ├── modify-schema.md │ └── add-middleware.md ├── frontend/ │ ├── create-component.md │ └── update-style.md ├── testing/ │ ├── write-unit-test.md │ └── run-e2e.md └── common/ ├── git-commit.md └── code-review.md这样组织的好处是当 agent 需要执行某个任务时可以根据任务类型快速定位到对应的技能目录。skills CLI也支持按目录过滤比如skills list --category backend只列出后端相关的技能。注意技能文件的命名要尽量用动词开头比如create-、modify-、delete-这样在列表里一眼就能看出每个技能是干什么的。3.3 在 Claude Code 中调用技能Claude Code 本身支持通过配置文件加载自定义指令agent-skills的思路就是把这些指令结构化。具体做法是在项目的.claude目录下创建一个skills子目录然后把技能文件软链接过去或者在配置文件里指定技能库路径。我用的是软链接方式ln -s .skills .claude/skills这样 Claude Code 启动时会自动读取.claude/skills下的所有技能文件。然后在对话中我只需要说“用 safe-function-modify 技能修改这个函数”它就会按照技能文件里定义的步骤执行。实测下来这种方式比直接在 prompt 里写一大段指令要稳定得多。因为技能文件是持久化的不会因为对话轮次多了就被“遗忘”。而且技能文件可以版本控制团队里每个人用的都是同一套标准。3.4 技能版本管理与团队协作技能文件既然是文件就可以用 Git 管理。我们团队的做法是建一个独立的agent-skills仓库每个人都可以提交新的技能或者修改现有技能。修改需要经过 code review确保步骤清晰、验证标准明确。这里有个细节技能文件里的命令要尽量用项目里已有的脚本而不是直接写底层命令。比如不要写npx jest --coverage而是写npm run test:coverage。这样当项目的测试框架换了只需要改package.json里的脚本不用改所有技能文件。另外技能文件里涉及路径的地方尽量用相对路径或者环境变量避免硬编码绝对路径。我见过一个技能文件里写了/Users/zhangsan/project/...结果别人拉下来根本没法用。4. 把 TDD 流程固化进技能的实际效果4.1 为什么 TDD 特别适合做成技能测试驱动开发的核心循环是“红-绿-重构”这个循环本身就是高度结构化的先写一个失败的测试再写最少的代码让它通过最后在测试保护下重构。每一步都有明确的输入和输出非常适合写成技能。我一开始是手动在 prompt 里描述这个流程的但每次都要重复写一遍而且 agent 经常会跳过“先写测试”这一步直接去改实现代码。后来我把 TDD 流程写成了一个技能文件情况就完全不一样了。技能文件里明确写了“第 1 步修改测试文件第 2 步运行测试确认失败第 3 步修改实现代码”。agent 在执行的时候会严格按照这个顺序来不会跳步。而且因为每一步都有验证标准如果它跳过了某一步验证就会失败我能立刻发现。4.2 一个完整的 TDD 技能执行案例拿一个具体的例子来说。假设我要给一个电商项目添加“计算订单折扣”的功能。我调用的技能是tdd-add-feature执行过程大概是这样的第一步前置检查。agent 运行git status确认工作区干净运行npm test确认现有测试全部通过。这一步大概花了 10 秒。第二步写测试。agent 在tests/discount.test.js里新增了一个测试用例输入是订单金额 100 元、用户等级 VIP期望折扣后价格是 90 元。然后运行npm test discount确认这个测试失败报错信息是“calculateDiscount is not defined”。第三步写实现。agent 在src/discount.js里新增了calculateDiscount函数先写了一个最简单的实现VIP 用户打九折。然后运行测试通过了。第四步补充边界测试。agent 又加了几个测试用例非 VIP 用户不打折、订单金额为 0 时返回 0、负数金额抛出异常。然后逐一实现直到所有测试通过。第五步重构。agent 发现折扣逻辑可以抽成一个配置对象方便以后扩展。它在测试保护下做了重构重构后再次运行测试确认全部通过。第六步最终验证。运行完整的测试套件和 lint 检查确认没有回归。整个过程大概花了 3 分钟比我手动写快了不少而且质量更稳定。最关键的是每一步都有测试保护我不需要担心它改坏别的东西。4.3 TDD 技能执行中的常见偏差与修正不过实际用下来也不是每次都这么顺利。我遇到过几种典型的偏差偏差一agent 写的测试太弱。比如只测试了正常路径没测试边界条件。修正方法是在技能文件里明确要求“每个新函数至少包含 3 个测试用例正常输入、边界输入、异常输入”。偏差二agent 为了让测试通过而修改测试。这是最危险的情况。修正方法是在技能文件里加一条硬性规则“禁止修改已有测试的断言逻辑除非用户明确要求”。同时在前置检查里加上“确认测试文件的修改只包含新增用例”。偏差三agent 跳过了重构步骤。因为重构不是必须的agent 有时候会直接结束。修正方法是在验证标准里加上“代码重复率不超过阈值”或者“函数复杂度不超过阈值”强制它做重构。这些修正都是在实际使用中慢慢积累的。我现在写新技能的时候会先把可能出现的偏差列出来然后在技能文件里加上对应的约束。5. 技能设计中的取舍与踩坑记录5.1 技能粒度太粗和太细都会出问题前面提到过技能粒度的问题这里展开说一下。我最初写的技能都很粗比如一个fix-bug技能包含了“定位问题、写测试、修复、验证”所有步骤。结果 agent 在执行的时候经常在“定位问题”这一步就卡住了因为它不知道该用什么方法定位。后来我把fix-bug拆成了reproduce-bug、write-failing-test、fix-implementation、verify-fix四个技能。每个技能只做一件事执行起来就顺畅多了。但拆得太细也有问题比如reproduce-bug这个技能如果 bug 很容易复现这个技能就显得多余。我现在的做法是默认拆细但允许在技能文件里定义“可跳过条件”。比如reproduce-bug技能里写“如果用户已经提供了复现步骤跳过本技能”。这样既保持了灵活性又不会让 agent 做无用功。5.2 技能文件里的“禁止事项”比“允许事项”更重要写技能文件的时候我花最多时间的地方不是“要做什么”而是“不要做什么”。因为 agent 的能力边界很广如果不明确禁止它可能会做出一些你意想不到的操作。比如我在modify-schema技能里明确写了“禁止直接修改生产环境的数据库”“禁止删除已有字段”“禁止修改字段类型”。这些禁止事项都是踩过坑之后加上去的。有一次 agent 在执行数据库迁移的时候直接删了一个字段虽然测试环境没问题但差点影响到生产数据。另一个例子是在git-commit技能里我写了“禁止使用git add .”“禁止跳过 pre-commit hook”。因为 agent 有时候图省事会一次性把所有改动都提交包括一些临时文件。提示技能文件里的禁止事项要用明确的否定句式比如“禁止...”“不得...”“不允许...”避免用“尽量避免”这种模糊表述。5.3 技能执行失败后的恢复策略技能执行失败是常有的事关键是怎么恢复。我在每个技能文件里都会写回滚方案但回滚方案本身也需要设计。最简单的回滚是git checkout -- .但这会丢失所有未提交的改动包括我自己手动改的部分。所以后来我改成了更精细的回滚在技能执行前先创建一个临时分支或者 stash失败后恢复到那个点。具体做法是在前置检查里加一步git stash push -m before-skill-execution然后如果技能执行失败执行git stash pop这样就能精确恢复到技能执行前的状态。不过要注意如果技能执行过程中产生了新的文件git stash是管不到的需要手动清理。我还遇到过一种情况技能执行到一半失败了但已经改了一部分文件。这时候如果直接回滚会丢失所有进度。我的做法是在技能文件里定义“检查点”每完成一个关键步骤就提交一次。这样失败后可以从最近的检查点继续而不是从头再来。6. 让技能库真正落地的几个关键习惯6.1 技能文件要跟着项目一起演进技能库不是写完就完了它需要跟着项目一起演进。我们团队的做法是每次做完一个任务如果发现技能文件里有不准确或者缺失的地方就顺手改掉。比如发现某个命令变了就更新技能文件里的命令发现某个步骤经常出问题就补充说明或者加约束。这个习惯看起来简单但坚持下来效果很明显。我们的技能库从最初的 5 个技能慢慢长到了 30 多个覆盖了日常开发的大部分场景。而且因为每次都是小改不会出现“技能库和实际项目脱节”的情况。我还建议定期做一次技能库的“体检”把所有技能过一遍删掉不再使用的合并重复的更新过时的命令。我一般每个月做一次大概花半小时。6.2 新技能先在小范围试用再推广写一个新技能之后不要急着让所有人都用。先自己在小范围试用几次看看执行效果怎么样有没有遗漏的步骤或者不合理的约束。试用没问题了再提交到团队技能库。我踩过的一个坑是写了一个deploy-to-staging技能没怎么测试就提交了。结果别人用的时候发现技能里写的部署命令需要特定的环境变量但技能文件里没写。后来我在技能文件里加了一个“环境要求”章节列出了所有需要的环境变量和配置。6.3 技能执行日志要保留skills CLI一般会记录每次技能执行的日志包括执行时间、执行结果、失败原因等。这些日志很有价值可以用来分析哪些技能经常失败、哪些步骤容易出问题。我每周会看一次日志找出失败率最高的技能然后针对性地优化。比如发现run-e2e技能经常超时我就把超时时间从 30 秒调到了 120 秒失败率立刻降下来了。日志还可以用来做技能库的“热度分析”哪些技能用得最多哪些几乎没人用。用得少的技能可以考虑删掉减少维护成本。6.4 技能命名要统一规范最后说一个看似小事但影响很大的点技能命名。我们团队一开始命名很随意有的用驼峰有的用下划线有的用空格。结果在列表里看起来很乱而且容易搞混。后来我们定了一个规范全部用小写字母单词之间用连字符动词开头不超过 4 个单词。比如create-api-route、modify-db-schema、run-unit-test。这样命名之后技能列表看起来清爽多了而且从名字就能大致猜出技能的功能。这个规范还带来一个好处可以用前缀做分组。比如所有create-开头的技能都是创建类操作所有run-开头的都是执行类操作。在 CLI 里可以用skills list --prefix create快速过滤。我在实际使用中最大的体会是agent-skills这套东西的价值不在于技术有多复杂而在于它把“怎么让 AI 好好干活”这件事从玄学变成了工程。你不需要每次都绞尽脑汁想 prompt只需要把成熟的流程写成技能文件然后让 agent 照着执行。当然技能文件本身也需要不断打磨但这个过程是有积累的每改一次下次就更顺一点。