ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI编码代理技能体系实战:agent-skills与测试驱动开发

AI编码代理技能体系实战:agent-skills与测试驱动开发 1. 从“agent-skills”说起为什么AI编码代理需要一套技能体系第一次看到“agent-skills”这个词很多人会以为它只是某个仓库里堆了一堆提示词模板。但真正用过 Claude Code、在终端里跑过 AI coding agents 的人会明白事情远没有这么简单。一个 AI 编码代理能不能稳定干活取决于它有没有一套可复用、可组合、可测试的“技能”体系。这套体系决定了它是每次都要你从头解释需求还是能像一个熟悉项目的老手一样自己找到入口、自己跑测试、自己修问题。我最初接触这个概念是在给一个中型后端项目做重构的时候。当时我让 AI 代理帮我改一个鉴权中间件结果它把三个不同模块的调用顺序搞反了测试全红。后来我意识到问题不在于模型不够聪明而在于我没有给它一套明确的“技能”——它不知道这个项目的测试怎么跑、日志在哪看、哪些文件不能碰。agent-skills 要解决的正是这个断层把人类工程师脑子里的隐性流程变成代理可以加载、可以执行、可以验证的显式技能。这篇文章适合三类人看。第一类是想把 AI 编码代理真正用进日常开发的人第二类是在搭内部研发工具链、需要统一代理行为的团队第三类是对 skills CLI、test-driven-development 这些实践感兴趣、想自己动手做一套的人。我会从设计思路讲到实操细节再到踩过的坑尽量把每个选择背后的理由说清楚。你不需要先成为 Claude Code 专家但最好对命令行和基本测试流程不陌生。2. 核心设计思路技能不是提示词而是可执行的能力单元2.1 为什么“技能”比“提示词”更适合代理很多人第一次用 AI 编码代理习惯写一大段提示词把背景、约束、期望输出全塞进去。短期看有效长期看会崩。原因是提示词是扁平的、一次性的而项目是立体的、持续演进的。agent-skills 的思路是把能力拆成独立单元每个单元有自己的触发条件、执行步骤和验证方式。这就像你不会把“做饭”写成一整页说明书而是拆成“切菜”“热锅”“调味”几个可复用的动作。从工程角度看技能单元至少带来三个好处。第一是可测试你可以单独验证一个技能是否按预期工作而不是每次跑整个代理流程。第二是可组合一个“运行单元测试”的技能可以被“修复失败测试”的技能调用。第三是可版本化技能文件可以进 Git可以 review可以回滚。这三点加起来才让 AI 编码代理从“玩具”变成“工具”。2.2 skills CLI 的定位与选型考量skills CLI 在这套体系里扮演的是“技能加载器”和“执行入口”的角色。它不负责推理也不负责生成代码它负责把技能定义解析出来按顺序喂给代理并收集执行结果。我选它而不是自己写脚本核心原因是它把技能发现、参数注入、结果回传这三件事标准化了。自己写当然也行但一旦技能数量超过十个维护成本会指数上升。选型时我对比过三种方案纯提示词模板、自定义脚本、skills CLI。纯提示词模板最轻但无法保证执行顺序和错误处理。自定义脚本最灵活但每个项目都要重写一遍。skills CLI 处在中间既有约定俗成的结构又允许你在技能内部写任意逻辑。对于需要长期维护的代理工作流这个平衡点很关键。2.3 与 test-driven-development 的天然契合test-driven-development 在这里不是口号而是代理能否自我纠错的基础。一个没有测试反馈的代理就像一个蒙眼修车的人只能靠猜。agent-skills 里我把“跑测试”做成一个独立技能把“根据失败信息定位文件”做成另一个技能把“修改后重跑”做成第三个技能。这样代理的每一步都有明确输入和输出出错时能定位到具体环节而不是笼统地说“它没改对”。实测下来带测试反馈的技能链修复成功率比纯提示词方式高出不少。原因很简单测试给了代理一个客观的停止条件。没有这个条件代理会一直改到看起来“差不多”为止而“差不多”在工程里往往意味着还有隐藏问题。3. 核心细节解析一个技能单元到底包含什么3.1 技能定义文件的结构一个典型的技能定义我通常包含五个部分名称、触发条件、前置依赖、执行步骤、验证方式。名称要短且唯一比如run-unit-tests而不是run-the-unit-tests-for-backend。触发条件描述什么时候加载这个技能可以是文件类型、命令关键词或上游技能的输出。前置依赖列出必须已经完成的技能避免顺序错乱。执行步骤是具体命令或操作序列。验证方式说明怎么判断这个技能成功了。这里有个容易忽略的点验证方式不能只写“命令返回 0”。很多命令返回 0 但输出是空的或者返回非 0 但其实是可忽略的警告。我一般会要求技能同时检查退出码和关键输出片段。比如跑测试时除了退出码还要确认输出里包含 “passed” 且不包含 “failed”。这个细节看起来小但能挡掉大量假阳性。3.2 参数注入与上下文传递技能之间需要传递信息比如“定位失败文件”技能要把文件路径传给“修改文件”技能。skills CLI 通常支持两种方式环境变量和标准输出解析。环境变量适合简单值标准输出适合结构化数据。我倾向让技能输出 JSON再由 CLI 解析成上下文。这样即使技能内部逻辑变了只要输出格式不变下游技能就不用改。参数注入的另一个坑是路径问题。代理执行命令时的工作目录可能和你手动执行时不一样。我踩过一次坑技能里写的是相对路径./tests但代理在项目根目录的上一级执行结果找不到目录。后来我强制所有技能使用绝对路径或者在技能开头先cd到项目根。这个改动让稳定性提升明显。3.3 技能粒度怎么把握粒度太粗一个技能干太多事出错难定位。粒度太细技能数量爆炸组合成本高。我的经验是一个技能对应一个可独立验证的动作。比如“安装依赖”是一个技能“跑测试”是一个技能“解析测试输出”是一个技能。但“安装依赖并跑测试”就不适合作为一个技能因为中间任何一步失败你都不好判断是安装问题还是测试问题。另一个判断标准是复用频率。如果一个动作在多个工作流里都会出现就值得单独成技能。如果只在一个特定场景用一次可以先内联在调用方里等复用需求出现再抽出来。过早抽象和过晚抽象都会带来麻烦我一般等第三次重复时再抽。4. 实操过程从零搭一套可用的 agent-skills 工作流4.1 环境准备与基础目录结构先在项目根目录建一个skills文件夹里面每个技能一个子目录子目录里放skill.yaml或skill.json作为定义文件。如果技能需要辅助脚本也放在同一子目录里。这样技能是自包含的复制到别的项目也能用。我还会建一个skills/README.md简单说明每个技能的用途和依赖方便团队其他人接手。基础目录大概长这样project/ skills/ run-unit-tests/ skill.yaml run.sh locate-failing-file/ skill.yaml locate.py apply-fix/ skill.yaml src/ tests/这种结构的好处是技能和业务代码分离不会互相污染。技能目录可以单独打成一个包分发给其他项目。4.2 编写第一个技能run-unit-tests这个技能的目标很明确在项目根目录执行测试命令并返回结构化结果。skill.yaml里我定义触发条件为“当代理需要验证代码改动时”前置依赖为空执行步骤调用run.sh验证方式检查退出码和输出关键词。run.sh的内容大致是#!/bin/bash set -e cd $(dirname $0)/../.. pytest --json-report --json-report-file/tmp/test-report.json这里用--json-report是为了让输出结构化方便下游技能解析。如果项目不用 pytest换成对应测试框架的 JSON 输出选项即可。关键是不要依赖人类可读的文本输出那东西格式一变就崩。注意技能脚本里的cd一定要基于脚本自身位置计算不要假设调用者的工作目录。这是我在多个项目里反复踩过的坑。4.3 编写第二个技能locate-failing-file这个技能读取上一个技能生成的/tmp/test-report.json找出失败的测试用例映射回源文件路径。locate.py的核心逻辑是解析 JSON提取failed列表再根据测试文件命名规则反推源文件。比如tests/test_auth.py::test_login对应src/auth.py。这里有个细节不同项目的测试和源文件映射规则不一样。我一般把映射规则写成配置放在技能目录的config.yaml里而不是硬编码在脚本中。这样换项目时只改配置不改逻辑。映射规则可以用正则也可以用简单的字符串替换看项目规范。4.4 编写第三个技能apply-fix这个技能接收文件路径和失败信息调用代理生成修改建议然后写回文件。写回前我会先备份原文件到/tmp万一改坏了还能恢复。写回后自动触发run-unit-tests形成闭环。如果测试通过技能返回成功如果不通过把新的失败信息传给locate-failing-file再走一轮。这个循环我设置了最大重试次数一般是 3 次。超过 3 次还修不好就停下来让人介入。不设上限的话代理可能在一个死循环里烧掉大量资源。这个上限不是拍脑袋定的我观察下来大部分简单问题 1 到 2 轮能解决复杂问题 3 轮还搞不定通常说明需求本身有歧义需要人澄清。4.5 把技能串起来一个完整工作流示例假设代理收到任务“修复登录接口的失败测试”。工作流是这样跑的先加载run-unit-tests发现test_login失败然后加载locate-failing-file定位到src/auth.py接着加载apply-fix生成修改并写回最后再跑一次run-unit-tests确认通过。整个过程代理只需要知道任务目标不需要知道具体步骤步骤由技能链定义。这种设计的好处是你可以单独替换任何一个技能。比如测试框架从 pytest 换成 unittest只改run-unit-tests和locate-failing-fileapply-fix完全不用动。这就是技能单元化的价值。5. 常见问题与排查技巧实录5.1 技能加载失败路径与权限问题最常见的问题是技能找不到。原因通常是路径写错或权限不足。排查时先确认skills目录在代理的工作目录下再确认技能文件有读权限。如果是团队协作还要注意 Git 是否忽略了某些技能文件。我一般会在 CLI 里加一个--list-skills命令先列出所有可用技能确认加载正常再跑工作流。另一个隐蔽问题是技能名称冲突。两个技能同名CLI 可能只加载其中一个。我要求所有技能名称全局唯一并且在 CI 里加一个检查重复名称直接报错。这个检查花不了多少时间但能避免很多诡异问题。5.2 测试输出解析失败格式变化与编码问题测试框架升级后JSON 输出格式可能变。比如某个字段从failed改成failures解析脚本就挂了。我的应对方式是给解析脚本加版本检查发现格式不符合预期时输出明确的错误信息而不是静默失败。静默失败最可怕代理会以为没有失败测试然后继续做错误的事。编码问题也遇到过。测试输出里有中文或特殊字符时如果脚本没指定 UTF-8解析会乱码。我在所有读写 JSON 的地方都显式指定encodingutf-8这个问题就没再出现。5.3 代理陷入循环重试上限与人工介入前面提到重试上限这里展开说。代理循环通常有两种原因一是失败信息不明确代理不知道改哪里二是修改引入了新问题新旧问题交替出现。第一种情况要改进locate-failing-file的输出让它给出更具体的定位。第二种情况要检查apply-fix是否改动了不该改的文件。我还会在循环里加一个“改动指纹”检查。如果连续两轮修改的文件和内容完全一样说明代理卡住了直接停止并报警。这个检查用文件哈希就能实现成本很低但能省下大量无效重试。5.4 常见问题速查表问题现象可能原因排查方法解决方式技能未加载路径错误或权限不足用--list-skills查看修正路径补读权限测试结果为空JSON 格式变化检查测试框架版本更新解析脚本代理反复改同一处失败信息不明确查看定位技能输出增强定位精度修改后测试更差改动范围过大对比修改前后 diff限制单次改动文件数循环无法停止缺少重试上限查看循环计数设置最大重试次数提示每次技能链跑完后把中间产物测试报告、定位结果、修改 diff保留一段时间。出问题时这些是唯一的线索删了就很难复现。6. 工具选型与扩展让技能体系适配不同项目6.1 技能定义格式的选择YAML 和 JSON 我都用过。YAML 可读性好适合人写JSON 解析严格适合机器生成。我的做法是技能定义用 YAML因为大部分时候是人维护技能之间的数据传递用 JSON因为要程序解析。这样两边的好处都占到。如果团队有偏好统一用一种也行关键是不要混着来混着来容易在解析上出问题。6.2 与不同 AI 编码代理的对接agent-skills 本身不绑定特定代理。只要代理能执行命令、能读文件就能接入。我试过把同一套技能用在不同的代理上发现差异主要在代理对技能输出的理解能力。有的代理能直接解析 JSON有的需要你把 JSON 转成自然语言再喂给它。这个适配层我一般写在 CLI 里而不是改技能本身。技能保持纯粹适配逻辑集中管理换代理时只改一处。6.3 技能库的版本管理与分发技能库进 Git 是基本操作。我还会给技能库打 tag每个项目引用特定 tag避免上游改动影响下游。分发方式有两种一是 Git submodule二是打包成内部包。submodule 适合技能和项目一起演进内部包适合多个项目共享稳定技能。我倾向后者因为 submodule 的更新流程对不熟悉的人不太友好。6.4 扩展方向从修复测试到更多场景这套体系不只能修测试。我后来扩展出“生成接口文档”“检查代码风格”“更新依赖版本”等技能。每个新技能都遵循同样的结构触发条件、依赖、步骤、验证。扩展时最大的挑战不是写技能而是定义清楚验证方式。没有验证方式的技能等于没有质量门禁用久了会积累一堆不可信的结果。7. 一些实操心得与后续可做的事我在实际使用中发现技能体系最大的价值不是让代理变聪明而是让代理的行为变得可预测。可预测意味着你可以放心把它放进自动化流程而不是每次都要盯着。这一点在团队协作里尤其重要因为不同人对代理的信任度不一样可预测的行为能降低沟通成本。踩过几次坑之后我养成了一个习惯每加一个新技能先单独跑通再接入工作流。单独跑的时候用真实项目数据不要用构造的假数据。假数据跑通不代表真数据能跑通这个教训我吃过不止一次。另外技能的输出尽量保持稳定不要频繁改格式。格式一改所有下游都要跟着改维护成本会悄悄涨上去。这个内容后续还可以这样扩展把技能库和 CI 打通让代理在合并请求里自动跑技能链把结果作为评论贴出来。这样即使代理没完全修好至少能给出明确的失败定位人接手时省很多时间。我现在就在往这个方向做效果比预想的好。
返回列表