ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

AI编程Agent技能包实战:用agent-skills与Claude Code实现TDD自动化

AI编程Agent技能包实战:用agent-skills与Claude Code实现TDD自动化 1. 从“agent-skills”说起为什么它值得单独拿出来聊第一次看到agent-skills这个标题我脑子里蹦出来的不是某个具体工具而是一类正在快速成型的东西——给 AI coding agent 用的“技能包”。你可以把它理解成一套可插拔的能力模块agent 本身负责推理、规划、调用工具而 skills 负责告诉它“遇到这类任务时具体该怎么做、按什么顺序做、做到什么程度算合格”。这个思路解决了一个很现实的问题。现在用 Claude Code、Cursor、Windsurf 这类 AI coding agent 的人越来越多但大家普遍会遇到同一个尴尬agent 很聪明可它不知道你团队的规范。比如你要求所有新功能必须先写测试再写实现它可能上来就给你把业务代码写完了你要求提交前必须跑 lint 和类型检查它可能改完文件就直接说“完成了”。每次都要在 prompt 里重复交代效率极低还容易漏。agent-skills这类项目的核心价值就在这儿把重复的、有固定套路的工程实践沉淀成 agent 可以直接加载和执行的技能定义。它不是一个孤立的工具而是一种组织方式。配合skills CLI、Claude Code这类运行环境你可以把 TDD 流程、代码审查清单、重构规范、文档生成模板全部打包成 skill让 agent 在合适的时机自动调用。这篇文章适合三类人看一是已经在用 Claude Code 或类似 agent 工具、想进一步提升自动化程度的开发者二是团队里负责制定工程规范、想让 AI 真正落地到生产流程的技术负责人三是对 AI coding agent 生态感兴趣、想搞清楚“skills 到底是怎么回事”的同行。我会从设计思路、核心机制、实操落地、常见坑几个角度把这件事讲透。2. agent-skills 的整体设计与核心思路拆解2.1 为什么是“技能”而不是“提示词”很多人第一反应是这不就是高级一点的 prompt 吗我直接把规范写进 system prompt 不就行了。刚开始我也这么想但实际用下来会发现两者有本质区别。Prompt 是一次性、上下文相关的。你在一个会话里写了“先写测试”换个会话就没了而且随着对话变长早期 prompt 的权重会被稀释。Skill 是持久化、可复用、可组合的。它是一份独立的定义文件有明确的触发条件、执行步骤和验收标准。agent 可以在需要的时候主动加载它不需要你每次重复。更关键的是skill 把“知识”和“执行”分开了。知识部分是你团队积累的最佳实践执行部分是 agent 的推理和工具调用能力。这种分离带来的好处是规范可以独立迭代不用动 agent 本身同一个 skill 可以被不同 agent、不同项目复用skill 之间还能互相引用形成能力网络。从工程角度看这其实是在给 agent 建立一套可测试、可版本控制的行为契约。你可以像 review 代码一样 review skill 的定义可以给 skill 写测试用例可以在 CI 里验证 agent 是否真的按 skill 执行了。这一点对于想把 AI 引入生产流程的团队来说是决定性的。2.2 目录结构与加载机制的设计考量一个典型的agent-skills项目目录结构通常长这样agent-skills/ ├── skills/ │ ├── test-driven-development/ │ │ ├── SKILL.md │ │ ├── examples/ │ │ └── scripts/ │ ├── code-review/ │ │ ├── SKILL.md │ │ └── checklist.md │ └── refactoring/ │ ├── SKILL.md │ └── patterns/ ├── cli/ │ └── index.ts └── package.json每个 skill 一个目录核心是SKILL.md。这个文件不是随便写的文档它有约定俗成的结构元信息名称、描述、触发条件 执行步骤 示例 验收标准。agent 读取这个文件后就能理解“什么时候该用这个技能”以及“用了之后要产出什么”。为什么用 Markdown 而不是 JSON 或 YAML因为 agent 本身就是靠自然语言推理的Markdown 对模型最友好可读性也最好。你写 JSON 描述步骤模型还得先解析结构再理解语义多一层损耗。Markdown 直接就是模型训练时见过无数次的格式理解成本最低。加载机制上skills CLI通常提供几个命令list列出所有可用技能show name查看某个技能的详情install name把技能注册到当前 agent 环境。安装的本质是把 skill 目录链接或复制到 agent 的配置路径下让 agent 在启动时能扫描到。这里有个设计细节值得注意技能是按需加载还是全量加载。全量加载简单但会占用上下文窗口按需加载需要 agent 有判断能力实现复杂但更高效。目前主流做法是启动时只加载技能的元信息名称和描述真正执行时才读取完整内容。2.3 与 Claude Code 等 agent 的协作方式agent-skills不是要替代 Claude Code而是增强它。Claude Code 本身有很强的代码理解和工具调用能力但它默认不知道你的工程规范。Skill 就是补上这一环。协作流程大致是这样你在 Claude Code 里提出一个任务比如“给用户模块加一个手机号验证功能”。Claude Code 分析任务后发现这属于“新功能开发”于是查找已安装的 skills找到test-driven-development加载它的定义。定义里写着第一步先写一个会失败的测试第二步运行测试确认失败第三步写最小实现让测试通过第四步重构。Claude Code 就按这个流程执行每一步都调用相应的工具写文件、跑命令、读输出。这个过程中skill 扮演的是流程控制器的角色。它不关心具体代码怎么写那是 agent 的能力它关心的是“先做什么、后做什么、什么算做完”。这种分工让 skill 可以跨语言、跨框架复用。同一个 TDD skill用在 Python 项目和 TypeScript 项目上流程完全一样只是 agent 生成的代码不同。3. 核心细节解析与实操要点3.1 SKILL.md 到底该怎么写这是整个项目里最需要花心思的地方。写得好agent 执行顺畅写得烂agent 要么不触发要么执行到一半跑偏。我踩过几次坑之后总结出一个比较稳的模板--- name: test-driven-development description: 当需要开发新功能或修复 bug 时使用确保先写测试再写实现 trigger: 新功能开发、bug 修复、代码修改 --- ## 执行步骤 1. 理解需求明确输入输出 2. 编写一个会失败的测试用例 3. 运行测试确认它确实失败 4. 编写最小实现让测试通过 5. 运行全部测试确认没有破坏其他功能 6. 重构代码保持测试通过 ## 验收标准 - 每个新功能都有对应的测试 - 测试在实现之前编写 - 所有测试通过 - 没有跳过或注释掉的测试 ## 示例 附上一个完整的 TDD 循环示例几个关键点。第一description要写清楚什么时候用而不是这是什么。模型是根据场景匹配技能的你写“测试驱动开发技能”它可能不知道啥时候该调用你写“当需要开发新功能或修复 bug 时使用”匹配就准确多了。第二步骤要可执行、可验证。不要写“编写高质量代码”这种没法验证的话要写“运行npm test并确认输出中没有 failing”。agent 需要明确的信号来判断自己是否做对了。第三验收标准要独立于实现。不要写“使用了 Jest 框架”要写“所有测试通过”。这样 skill 才能跨技术栈复用。注意SKILL.md 不要写太长。我见过有人写了三千字结果 agent 加载后反而抓不住重点。核心步骤控制在 10 条以内细节放到 examples 目录里需要时再读。3.2 skills CLI 的安装与基本操作skills CLI是管理技能的命令行工具通常通过 npm 全局安装npm install -g agent-skills/cli安装后验证skills --version skills listlist会扫描当前项目或全局配置下的所有 skill输出名称和描述。如果什么都没显示说明还没安装任何技能。安装一个技能skills install test-driven-development这个命令做的事情是从注册表或本地路径找到 skill 目录复制到~/.agent-skills/下并在 agent 的配置文件中注册。不同 agent 的配置路径不一样Claude Code 通常读~/.claude/skills/CLI 会自动处理路径映射。查看某个技能的详情skills show test-driven-development这会打印 SKILL.md 的完整内容方便你在安装前确认它是否符合预期。移除技能skills remove test-driven-development这里有个实操心得安装前先 show 一下。有些社区贡献的 skill 写得比较粗糙触发条件太宽泛装上去之后 agent 动不动就调用反而干扰正常流程。先看内容再决定装不装能省很多事。3.3 触发条件的设计让 agent 在对的时候做对的事触发条件是 skill 设计里最微妙的部分。写得太窄agent 该用的时候想不起来写得太宽不该用的时候乱用。我的经验是触发条件应该描述任务特征而不是技术关键词。比如差的写法trigger: 当用户提到 test、jest、pytest 时好的写法trigger: 当需要新增功能、修改现有行为、或修复缺陷时前者依赖关键词匹配用户换个说法就失效了后者描述的是任务本质不管用什么词表达只要任务性质对上了就能触发。另外触发条件之间要有互斥性。如果你装了test-driven-development和quick-prototyping两个技能前者要求先写测试后者要求先跑通再说它们的触发条件如果都覆盖“新功能开发”agent 就会纠结用哪个。解决办法是在描述里加限定比如 TDD 用于“生产代码”quick-prototyping 用于“探索性原型”。3.4 技能之间的组合与依赖单个技能能解决的问题有限真正强大的是技能组合。比如一个完整的“功能开发”流程可能涉及requirement-analysis把模糊需求拆成明确任务test-driven-development按 TDD 流程实现code-review自查代码质量documentation更新相关文档这些技能可以串成一条流水线。实现方式有两种一种是在 skill 里显式引用其他 skill比如在feature-development的步骤里写“调用 test-driven-development 技能”另一种是让 agent 自己根据当前阶段判断该加载哪个。显式引用的好处是流程可控坏处是灵活性差。隐式判断的好处是灵活坏处是可能漏掉步骤。我的建议是核心流程用显式引用辅助技能用隐式判断。TDD 这种必须严格执行的就写死在流程里文档更新这种可以视情况而定的就让 agent 自己决定。4. 实操过程与核心环节实现4.1 从零搭建一个 agent-skills 项目假设你要在团队里落地这套东西第一步是建仓库。我建议直接用 monorepo 结构skills 和 CLI 放一起方便版本同步。mkdir agent-skills cd agent-skills npm init -y mkdir -p skills cli然后创建第一个技能mkdir -p skills/test-driven-development/examples touch skills/test-driven-development/SKILL.md把前面模板里的内容填进去。接着写一个最简单的 CLI核心功能就是扫描skills/目录、解析 SKILL.md 的 frontmatter、提供 list 和 show 命令。// cli/index.js const fs require(fs); const path require(path); const SKILLS_DIR path.join(__dirname, .., skills); function listSkills() { const dirs fs.readdirSync(SKILLS_DIR); return dirs.map(dir { const skillPath path.join(SKILLS_DIR, dir, SKILL.md); if (!fs.existsSync(skillPath)) return null; const content fs.readFileSync(skillPath, utf-8); const match content.match(/name:\s*(.)/); const descMatch content.match(/description:\s*(.)/); return { name: match ? match[1].trim() : dir, description: descMatch ? descMatch[1].trim() : }; }).filter(Boolean); } const command process.argv[2]; if (command list) { console.table(listSkills()); }这个最小实现跑通后再逐步加 install、remove、sync 等命令。不要一上来就追求功能完整先把核心链路走通。4.2 在 Claude Code 中加载并验证技能Claude Code 的技能加载路径通常是~/.claude/skills/。你可以手动把 skill 目录复制过去也可以用 CLI 的 install 命令。cp -r skills/test-driven-development ~/.claude/skills/然后在 Claude Code 里发起一个任务比如“给 utils 模块加一个日期格式化函数”。观察它的行为如果它先创建了测试文件运行测试看到失败再写实现说明 skill 生效了。如果它直接写实现说明触发条件没匹配上需要调整 SKILL.md 里的 description。验证的时候有个技巧故意给一个模糊的任务。比如“优化一下用户模块”。好的 skill 应该能让 agent 先追问清楚要优化什么而不是直接动手。如果 agent 上来就改代码说明 skill 里缺少“需求澄清”这一步。4.3 参数计算与选择以测试覆盖率为例Skill 里经常需要设定量化标准比如测试覆盖率。写多少合适我见过团队要求 100%结果 agent 为了凑覆盖率写了一堆无意义的断言反而降低了测试质量。我的建议是分层次设定代码类型建议覆盖率理由核心业务逻辑90% 以上出错代价高必须充分覆盖工具函数80% 左右逻辑相对简单重点覆盖边界UI 组件60% 左右交互逻辑多快照测试为主配置文件不强制通常由集成测试覆盖这个标准写进 skill 的验收条件里agent 就会按这个目标执行而不是盲目追求 100%。计算方式上用jest --coverage或pytest --cov输出的行覆盖率作为依据但要注意行覆盖不等于逻辑覆盖。一个 if-else 只测了 if 分支行覆盖率可能显示 100%但 else 分支根本没测。所以 skill 里最好加一条“关键分支必须有对应用例”。4.4 实操现场一次完整的 TDD 技能执行记录我拿一个真实任务跑了一遍记录如下。任务给一个 Express 应用加/health接口返回{ status: ok }。Agent 加载 TDD skill 后的执行序列读取SKILL.md确认流程创建tests/health.test.js写入测试请求/health期望状态码 200body 为{ status: ok }运行npm test输出显示Cannot GET /health测试失败符合预期创建routes/health.js实现路由在app.js中注册路由再次运行npm test测试通过运行npm run lint无报错输出总结完成了什么、测试结果如何、下一步建议整个过程没有人工干预耗时约 40 秒。对比不用 skill 的情况agent 通常会直接写路由和实现测试要么不写要么事后补一个走过场的。TDD skill 的价值就在于把顺序锁死了agent 没有偷懒的空间。提示第一次跑的时候agent 可能会在“运行测试确认失败”这一步卡住因为它不确定失败是不是预期的。解决办法是在 skill 里写清楚“确认失败信息与预期一致比如 404 而非语法错误”。这样 agent 就有了判断依据。5. 常见问题与排查技巧实录5.1 技能不触发怎么办这是最高频的问题。表现是明明装了 skillagent 却按自己的方式执行。排查顺序如下。先检查 skill 是否真的被加载了。在 Claude Code 里输入/skills或类似命令看列表里有没有。如果没有检查文件路径对不对SKILL.md 的 frontmatter 格式是否正确。YAML frontmatter 对缩进敏感name:前面不能有空格冒号后面要有一个空格。如果加载了但不触发问题多半在 description。把 description 改得更贴近任务描述。比如原来写“测试驱动开发”改成“当需要编写新功能、修改现有逻辑或修复缺陷时按测试先行的方式执行”。改完后重启 agent 会话让它重新读取。还有一个隐蔽原因上下文里已经有其他指令覆盖了。比如你在 prompt 里写了“快速实现一个 demo”agent 可能判断这属于原型开发主动跳过了 TDD skill。这时候要么调整 prompt要么给 skill 加一个更高优先级的触发条件。5.2 技能执行到一半跑偏有时候 agent 开始按 skill 执行了但中途偏离。比如 TDD 流程走到“写最小实现”它却顺手把重构也做了还改了不相关的文件。原因通常是 skill 的步骤描述不够原子化。每一步应该是一个独立、可验证的动作。不要写“实现功能并重构”要拆成“实现功能运行测试通过”和“重构再次运行测试通过”两步。agent 在每一步结束时都有明确的完成信号就不容易越界。另外可以在 skill 里加一条约束“除非当前步骤明确要求否则不要修改任务范围之外的文件”。这句话能挡掉大部分跑偏行为。5.3 多个技能冲突的解决装了多个 skill 后agent 可能同时匹配到两个。比如code-review和refactoring都可能在“代码修改”后触发。解决办法是在 skill 里声明优先级和互斥关系。可以在 frontmatter 里加priority: 10 conflicts: [quick-prototyping]CLI 在加载时检查冲突如果两个互斥的 skill 同时匹配按优先级高的执行并提示用户。这个机制需要 CLI 支持实现起来不复杂但能省很多调试时间。5.4 常见问题速查表现象可能原因解决方法skill 不加载路径错误或 frontmatter 格式错检查~/.claude/skills/下是否有对应目录验证 YAML 缩进加载了不触发description 太窄或太泛改成描述任务特征而非技术关键词执行中途跑偏步骤不够原子化拆分步骤每步加验证条件多个 skill 冲突触发条件重叠加 priority 和 conflicts 声明执行结果不稳定验收标准模糊把“高质量”换成可量化的检查项上下文占用过大skill 内容太长核心步骤精简细节移到 examples5.5 几个我踩过的坑第一个坑在 skill 里写死了具体命令。比如写“运行npm test”结果换到 Python 项目就失效了。后来改成“运行项目对应的测试命令”让 agent 自己判断通用性好了很多。第二个坑验收标准写得太主观。写“代码整洁”agent 觉得挺整洁我觉得不行。改成“函数不超过 50 行、没有重复代码块、命名符合项目现有风格”可操作性就强了。第三个坑忽略了 skill 的版本管理。团队里几个人各自改 skill没有版本控制导致行为不一致。后来把 skills 仓库纳入 Git 管理每次修改走 PR问题就解决了。6. 技能生态的扩展与个人实践体会agent-skills这套东西真正有意思的地方是它打开了一个可积累的工程知识库的可能性。你每解决一类问题就可以把解法沉淀成一个 skill。时间长了这个仓库就是你团队工程实践的完整映射。新人入职装上这套 skillsagent 就能按团队规范干活比看文档快得多。我现在维护的 skills 仓库里除了 TDD还有几个用得比较顺的api-design负责按 RESTful 规范生成接口error-handling统一异常处理模式commit-message按约定式提交格式生成提交信息。每个都不复杂但组合起来agent 的产出质量明显上了一个台阶。扩展方向上我觉得有两个值得尝试。一是技能的市场化社区贡献、评分、按需安装类似 npm 的生态。二是技能的自动化测试给每个 skill 写测试用例在 CI 里跑确保 agent 按预期执行。后者对生产环境尤其重要毕竟你不能指望每次都人工检查 agent 有没有偷懒。最后分享一个小技巧写 skill 的时候先手动跑一遍流程把每一步的实际操作和输出记下来再整理成 skill 定义。这样写出来的步骤最贴近真实执行agent 理解起来也最顺。凭空想象的流程往往会在某个环节卡住因为你自己都没实际走过。
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表