agent-skills 技能包实战:用 TDD 与 skills CLI 规范 AI 编码行为

📅 发布时间:2026/10/7 22:09:09
agent-skills 技能包实战:用 TDD 与 skills CLI 规范 AI 编码行为
1. 从agent-skills这个标题里能读出什么第一次看到agent-skills这个项目名我的直觉是这不是一个具体的应用而是一套给 AI coding agent 用的能力扩展集合。换句话说它解决的不是AI 能不能写代码而是AI 写代码时够不够专业、够不够守规矩。这两年 AI coding agent 的进化速度非常快从最早的代码补全到能读整个仓库、能跑终端命令、能自己改文件、能提交 PR工具形态已经发生了质变。但真正在项目里用过的人都知道agent 的聪明和靠谱是两回事。它可能一口气生成两百行代码但没写一个测试它可能把功能实现了但顺手改坏了三个不相关的文件它可能在你没注意的时候执行了一条破坏性的命令。这些问题的根源不在于模型能力不够而在于缺少一套明确的技能约束和工作规范。agent-skills 这类项目要做的就是把这些规范沉淀成可复用、可组合、可被 agent 自动加载的技能包。每个 skill 本质上是一段结构化的指令告诉 agent 在特定场景下应该遵循什么流程、检查哪些事项、产出什么格式的结果。关键词里出现的 test-driven-development 就是一个典型例子——它不是一个库而是一种工作方式的封装先写测试、再写实现、最后重构agent 每次接到编码任务时都按这个节奏走。这篇文章适合三类人看一是已经在用 AI coding agent 但觉得输出质量不稳定的开发者二是想给自己团队搭建一套 agent 工作规范的技术负责人三是单纯好奇skills CLI这类工具到底怎么落地的人。我会从技能包的设计逻辑讲起一路讲到怎么在 Claude Code 这类环境里把它跑起来中间穿插我自己踩过的坑和实测有效的配置方式。需要先说明一点agent-skills 目前没有一个统一的官方标准不同团队、不同工具对skill的定义和加载方式差异很大。下面讲到的目录结构、CLI 用法、配置字段都是基于当前主流实践总结出来的通用模式你在具体项目里需要根据实际使用的 agent 工具做适配。2. 技能包到底封装了什么拆解 agent-skills 的核心构成2.1 一个 skill 的最小结构很多人以为 skill 就是一段提示词写几句你要认真写测试就完事了。实测下来这种松散的自然语言指令在长对话里很容易被 agent 遗忘尤其是上下文变长之后早期的约束会被稀释。真正好用的 skill 是有固定结构的通常包含这么几个部分元信息名称、描述、触发条件。这部分决定了 agent 什么时候该加载这个 skill。适用场景明确写出当用户要求实现新功能时当代码审查发现潜在 bug 时这类条件。执行流程分步骤的操作指引越具体越好最好能对应到具体的命令或文件操作。产出规范要求 agent 输出什么格式比如必须附带测试文件、必须更新文档、必须给出变更说明。边界与禁忌明确哪些事不能做比如不要修改配置文件不要执行删除操作。我见过不少团队把 skill 写成了一篇小作文结果 agent 要么忽略要么只执行了其中一部分。经验是单个 skill 聚焦一件事流程步骤控制在 5 到 8 步超过这个数量就该拆成两个 skill。2.2 为什么用目录而不是单个文件agent-skills 这类项目通常采用目录结构来组织技能一个 skill 一个文件夹里面放主指令文件可能还有辅助的模板、示例、脚本。这么做有几个实际好处。第一是可组合。不同项目需要的能力不一样前端项目可能更关注组件测试和可访问性检查后端项目更关注接口契约和数据库迁移。用目录组织就能按需挂载而不是把所有规则一股脑塞给 agent。第二是可维护。技能是会迭代的今天发现 agent 老忘记处理边界条件就补一条规则进去。如果所有技能挤在一个大文件里改起来很容易互相影响。第三是便于版本管理。技能包跟着代码仓库走谁改了什么、为什么改git log 里清清楚楚。这对团队协作特别重要因为 agent 的行为规范本质上也是团队规范的一部分。一个典型的目录长这样skills/ test-driven-development/ SKILL.md templates/ test-template.md code-review/ SKILL.md checklist.md commit-convention/ SKILL.md主文件一般叫 SKILL.md 或者 skill.md这个命名约定在多个 agent 工具里是通用的agent 扫描目录时能自动识别。2.3 触发机制skill 是怎么被 agent 用起来的这是最容易被忽略、也最容易出问题的一环。skill 写好了agent 怎么知道该用它目前主流有两种模式。一种是显式调用用户在对话里直接说用 TDD 技能来实现这个功能agent 去加载对应 skill。这种方式可控性强但依赖用户记得住有哪些技能。另一种是自动匹配agent 根据当前任务描述和 skill 的元信息做语义匹配觉得相关就自动加载。这种方式省心但容易误触发或者漏触发。我实测下来纯自动匹配在技能数量超过十个之后准确率会明显下降经常该加载的没加载不该加载的反而加载了。比较稳妥的做法是混合核心技能比如代码审查、提交规范设为自动加载因为它们几乎每个任务都用得上专项技能比如某个特定框架的迁移流程设为手动触发避免干扰。提示如果你的 agent 工具支持在项目根目录放一个配置文件来声明技能加载策略强烈建议用上。把哪些技能常驻、哪些按需写清楚比让 agent 自己猜要可靠得多。3. 用 skills CLI 把技能包管起来3.1 为什么需要一个 CLI手工管理技能目录在只有两三个技能的时候还行一旦技能多起来、要在多个项目之间复用就会变得很痛苦。你会遇到这些问题技能更新了怎么同步到所有项目某个项目只需要其中几个技能怎么按需安装团队新人怎么快速把环境配好skills CLI 就是来解决这些问题的。它本质上是一个包管理器只不过管理的不是代码依赖而是 agent 的技能包。核心命令通常包括安装、列出、更新、移除这几类。需要说明的是不同实现的 CLI 命令名和参数会有差异下面给的是常见形态具体以你所用工具的文档为准。3.2 安装与初始化假设你已经有了一个技能仓库第一步是把它拉到本地并初始化# 克隆技能仓库 git clone your-skills-repo ~/.agent-skills # 进入项目目录初始化技能配置 cd your-project skills initskills init一般会做两件事在项目里创建一个配置文件比如.skills.json或skills.config.yaml记录这个项目要用哪些技能同时在项目里建立软链接或者复制技能文件到 agent 能识别的目录。这里有个坑要提前说软链接和复制的选择会影响后续更新行为。用软链接技能仓库更新后项目自动生效但如果你在项目里改了技能文件改的其实是源仓库容易污染全局。用复制项目之间互不影响但每次技能更新都要重新同步。我的建议是个人项目用软链接图省事团队项目用复制保证隔离性。3.3 按需挂载技能配置文件里通常长这样{ skills: [ test-driven-development, code-review, commit-convention ], autoLoad: [ code-review, commit-convention ] }skills数组声明这个项目启用了哪些技能autoLoad声明哪些是常驻的。没在 autoLoad 里的技能agent 需要被明确要求才会加载。安装单个技能的命令一般是skills add test-driven-development移除则是skills remove test-driven-development实测下来skills add之后最好重启一下 agent 会话因为很多工具是在会话启动时扫描技能目录的运行中新增的技能不一定会被识别。3.4 技能版本与团队同步技能包也是会演进的。今天定的代码审查清单下个月可能因为引入了新的静态检查工具而要调整。这时候版本管理就很重要。如果技能仓库本身用 git 管理可以在项目配置里锁定一个 commit 或者 tag{ skillsSource: git...:team/agent-skills.git, skillsRef: v1.2.0 }这样团队里每个人拉到的技能版本是一致的不会出现我这边 agent 行为和你那边不一样的诡异情况。踩过的坑是早期我们没锁版本结果某次技能更新后agent 突然开始强制要求每个函数都写文档注释把大家搞得很不适应。后来锁了版本升级变成一个有意识的行为就顺畅多了。4. 把 test-driven-development 技能真正跑通4.1 TDD 技能为什么值得单独拿出来讲在 agent-skills 的关键词里test-driven-development 是唯一一个明确指向具体工作方法的。这不是偶然。TDD 对 AI coding agent 来说价值比对人还大。原因在于agent 最大的问题是不知道自己写对了没有。人写代码心里有个预期跑一下大概能判断对不对。agent 没有这个直觉它只能靠反馈。而测试就是最直接、最结构化的反馈。先写测试等于先给 agent 立了一个明确的目标——让这些测试通过。它有了目标行为就会收敛很多不会天马行空地发挥。我做过对比同一个功能需求不启用 TDD 技能时agent 生成的代码平均要来回改三四轮才能用启用之后通常一到两轮就能达到可提交状态。差别主要在于TDD 技能强制 agent 先想清楚什么叫做完了而不是先写一堆实现再补测试。4.2 TDD 技能的流程设计一个可用的 TDD 技能流程大致是这样的理解需求拆解行为agent 先把需求拆成若干个可验证的行为点每个行为点对应一个测试用例。写失败的测试先写测试确认测试在当前代码下是失败的红。写最小实现只写让测试通过的最少代码不提前优化不加没要求的功能。跑测试确认通过绿。重构在测试保护下清理代码保持测试全绿。循环回到第 2 步处理下一个行为点。关键在于第 3 步的最小实现。agent 天然倾向于一次写很多觉得这样效率高。但 TDD 技能要明确约束它这一步只解决当前测试不要顺手把后面的功能也做了。这个约束看起来反直觉实际效果很好因为一旦 agent 开始顺手多做测试覆盖就容易出现盲区。4.3 实测中的意外情况跑通 TDD 技能的过程中我遇到过几个典型问题分享出来供参考。测试框架识别错误。agent 有时会默认用某个它熟悉的测试框架而项目实际用的是另一个。解决办法是在技能里明确写出项目使用的测试命令比如运行测试请使用npm run test:unit而不是让 agent 自己猜。测试写得过于宽松。agent 为了让测试快点通过有时会写出expect(result).toBeDefined()这种几乎没有约束力的断言。TDD 技能里要专门加一条断言必须验证具体的值或行为禁止只验证存在。重构阶段失控。第 5 步重构时agent 有时会改着改着把测试也改了这就破坏了 TDD 的意义。技能里要写死重构阶段不允许修改测试文件如果发现测试本身有问题必须先停下来说明。注意TDD 技能对 agent 的上下文长度有要求。如果一次让它处理太大的需求拆解出来的行为点会很多上下文容易爆。建议把需求切小一个 skill 调用处理一个相对独立的功能点。5. 在 Claude Code 环境里落地 agent-skills5.1 环境准备阶段容易忽略的细节Claude Code 这类终端里的 AI coding agent对技能目录的识别通常有约定位置。常见的是项目根目录下的特定文件夹或者用户主目录下的全局配置目录。落地时第一件事是确认你的 agent 到底从哪里读技能。我建议的做法是先放一个最简单的技能进去然后问 agent你现在能识别到哪些技能看它的回答。如果识别不到就检查目录位置和文件命名。这一步花五分钟能省掉后面半小时的困惑。另一个细节是权限。agent 要读取技能文件、要执行测试命令这些都需要相应的文件系统权限和终端权限。在受限环境里agent 可能读不到技能目录表现就是技能明明配了但没生效。排查时优先看 agent 的日志里有没有权限相关的报错。5.2 技能与 agent 工作流的衔接技能不是孤立存在的它要和 agent 的整个工作流串起来。一个完整的链路大概是用户提出需求 → agent 匹配到相关技能 → 按技能流程执行 → 产出符合规范的结果 → 用户验收。这里有个衔接点容易被忽略技能产出的结果要能被后续步骤消费。比如 TDD 技能产出了测试文件和实现代码代码审查技能要能接着审查这些产出。如果两个技能对文件命名、目录结构的约定不一致衔接就会断掉。所以设计技能时最好先画一遍完整工作流确认各技能之间的接口是对齐的。5.3 多模型环境下的技能适配现在很多人在 Claude Code 里接的不一定是默认模型可能会切换到其他模型来跑。不同模型对指令的遵循程度不一样同一个技能在不同模型下的表现可能有明显差异。我的经验是技能里的指令要写得足够笨也就是不依赖模型的推理能力而是把每一步都写清楚。比如不要写合理处理错误而要写捕获异常后记录错误信息到日志并返回统一的错误响应格式。指令越具体跨模型的稳定性越好。另外切换模型后建议重新跑一遍技能验证。有些模型对长指令的注意力分布不同可能在某个步骤上掉链子。发现之后针对性地把那一步的指令再细化通常就能解决。6. 技能包设计中的经验与避坑6.1 技能粒度太粗和太细都不行技能粒度是个反复要调的东西。太粗一个技能管一大摊事agent 执行时容易顾此失彼太细技能数量爆炸匹配和加载都变复杂。我的判断标准是一个技能应该对应一个可独立验收的产出。比如写测试是一个技能跑测试并修复失败是另一个技能因为这两件事的产出不同验收标准也不同。而写测试和写实现如果硬拆开反而会因为它们交替进行而频繁切换不如合在 TDD 技能里。6.2 指令的确定性少用形容词多用动词和具体值这是我在写技能时体会最深的一条。形容词对 agent 来说几乎没有约束力。写出高质量的代码这种话agent 看了等于没看。但每个函数不超过 50 行所有公共方法必须有类型标注错误信息必须包含错误码这种agent 就能照着做。所以写技能时尽量把模糊的要求翻译成可检查的条件。如果某个要求实在没法量化就给出正例和反例让 agent 对照。6.3 技能之间的冲突处理技能多了之后冲突几乎不可避免。比如一个技能要求提交前必须跑全量测试另一个技能要求快速迭代时只跑相关测试这俩就会打架。处理冲突的原则是明确优先级并且让 agent 知道冲突时听谁的。可以在技能元信息里加一个优先级字段或者在项目配置里声明技能的执行顺序。更简单的办法是把可能冲突的技能合并成一个内部用条件分支来处理不同场景。6.4 持续迭代把踩过的坑写回技能技能包最大的价值在于它会随着使用不断变好。每次 agent 犯了错不要只是当场纠正而要想这个错误能不能通过改技能来预防如果能就把它写进技能里。我们团队有个习惯每周复盘一次 agent 的翻车记录挑出共性问题更新到技能包。几个月下来agent 的靠谱程度提升非常明显。这个过程本身就是把团队经验沉淀下来的过程比写文档有效得多。7. 关于技能包复用与扩展的一些想法技能包做出来之后很自然会想到复用。跨项目复用是最基本的把通用技能放在一个共享仓库里各项目按需引用。再往上可以考虑跨团队共享但这里要小心不同团队的规范差异可能很大直接拿来用往往水土不服。比较务实的做法是共享骨架各团队根据自己的情况填充细节。扩展方面技能包可以和现有的工程工具链结合。比如把 lint 规则、CI 检查项、代码审查清单都映射成技能让 agent 在写代码阶段就遵守这些规范而不是等到 CI 阶段才被打回。这样能省下不少来回折腾的时间。还有一个方向是把技能和项目文档打通。很多项目的规范散落在各种 wiki 和 README 里人都不一定看得全更别说 agent 了。把这些规范整理成技能等于给 agent 提供了一份可执行的规范手册。最后分享一个我自己的小技巧给技能包写一个自检技能专门用来检查其他技能是否被正确加载、配置是否有冲突。每次调整技能配置后跑一下能提前发现不少问题。这个技能本身很简单但省下的排查时间很可观。