ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

agent-skills:用TDD工作流和skills CLI驯服AI coding agent

agent-skills:用TDD工作流和skills CLI驯服AI coding agent 1. 从agent-skills这个标题能读出什么第一次看到agent-skills这个仓库名我的直觉是这不是又一个提示词大全而是一套把 AI coding agent 当新同事来培养的技能体系。标题里的agent指向的是执行主体——AI 编码代理skills指向的是能力单元——它到底会干什么、怎么干、干到什么程度算合格。两者拼在一起本质是在回答一个很现实的问题我们怎么把一个大模型从能聊天变成能交付这个问题的背景是过去一年多 AI coding agent 的爆发。从终端里的 Claude Code到编辑器里的各类 agent 插件再到各家模型厂商推出的 agent 框架工具已经足够多了。但真正上手用过的人都会发现一个尴尬的事实同一个模型有人用它十分钟改完一个 bug有人折腾一下午还在跟它对线。差距不在模型本身而在你有没有给它一套明确的技能定义和工作规范。agent-skills要解决的正是这个断层。它把让 agent 干活这件事拆成可复用、可组合、可测试的技能模块每个技能对应一类具体任务比如写测试、改代码、做代码审查、跑命令、处理报错。关键词里出现的test-driven-development、skills CLI、AI coding agents也印证了这一点这不是纯理论而是带命令行工具、带工作流、带测试闭环的工程化方案。这篇文章适合三类人看一是刚开始接触 AI coding agent、还在纠结怎么让它听话的开发者二是已经在用 Claude Code 这类工具、但效率始终上不去的进阶用户三是想把 agent 能力沉淀成团队规范、避免每个人各玩各的技术负责人。我会从技能的本质讲起一路讲到 CLI 怎么用、TDD 工作流怎么落地、以及我在实际使用中踩过的那些坑。全程按为什么这么设计来讲而不是甩一堆命令让你照抄。2. 技能不是提示词agent-skills 的底层设计逻辑2.1 为什么提示词工程在 agent 场景下会失效很多人对 AI coding agent 的理解还停留在写个好提示词的阶段。你精心打磨一段 prompt告诉它你是一个资深工程师请帮我重构这段代码然后满怀期待地按下回车。结果呢它可能给你返回一段看起来很美、但根本跑不起来的代码或者干脆把你的函数签名改得面目全非。问题出在哪提示词是一次性指令而技能是可复用的能力契约。提示词解决的是这一次我要它做什么技能解决的是这一类任务它应该怎么做、做到什么标准、怎么验证做对了。前者是临场发挥后者是制度化沉淀。打个比方提示词像是你临时口头交代实习生帮我把这个表格整理一下而技能像是公司给实习生的一本《表格整理规范手册》里面写清楚了字段怎么对齐、空值怎么处理、异常数据怎么标记、完成后怎么自检。前者依赖实习生的悟性后者保证无论谁来干产出都在同一个水准线上。agent-skills的核心洞察就在这里agent 的可靠性不来自模型多聪明而来自技能定义多清晰。一个技能通常包含几个要素——触发条件什么情况下用这个技能、执行步骤具体怎么做、约束条件不能做什么、验证标准怎么算做完了。这四样东西凑齐agent 才真正具备独立完成一类任务的能力。2.2 一个技能模块的解剖结构虽然agent-skills的具体实现会随版本演进但一个成熟的技能模块结构上通常跑不出这几个部分。我按自己的理解拆一下你可以对照着看自己手头的 agent 配置缺了哪块。组成要素作用缺失后的典型症状触发描述告诉 agent 何时该调用这个技能agent 该用的时候不用不该用的时候乱用输入约定明确技能需要哪些上下文agent 反复追问或基于错误假设开工执行步骤分步骤的操作指引agent 跳步、漏步产出不完整约束边界明确禁止的操作和红线agent 擅自改配置、删文件、动生产数据验证标准定义完成的客观判据agent 自认为做完了实际一跑就崩失败处理出错时怎么回退、怎么上报agent 卡死、死循环、或悄悄放弃这张表是我自己在配置多个 agent 工作流之后总结出来的。你会发现大部分agent 不听话的抱怨根子都在约束边界和验证标准这两栏是空的。你只告诉它要做什么没告诉它不能做什么、怎么证明做对了那它当然只能靠猜。2.3 技能组合从单点能力到工作流单个技能再强也只是一招。真正让 agent 产生质变的是技能的编排组合。agent-skills里提到的test-driven-development就是一个典型的组合型技能——它不是单一动作而是一条完整的工作流先写测试、再写实现、跑测试、根据失败信息修正、直到全绿。这条工作流之所以重要是因为它给 agent 装了一个自动纠错回路。没有 TDD 的 agent写完代码就交差对不对全靠你人工验有了 TDD 的 agent它自己就能通过测试结果判断对错然后自我修正。这个差别用过的人都懂——前者你是质检员后者你是验收员工作量差着量级。技能组合的另一个价值是可测试性。每个技能单独可测组合起来的工作流也可测。这意味着你可以像测代码一样测你的 agent 配置给它一个标准输入看它是否产出标准输出。这套思路一旦建立agent 的迭代就从玄学调参变成了工程优化。3. skills CLI把技能管理变成命令行操作3.1 为什么技能需要一个 CLI有人会问技能不就是几个配置文件吗我手动建目录、写文件不就行了为什么要专门搞个 CLI我一开始也这么想直到技能数量超过十个之后问题全冒出来了。技能之间有依赖关系A 技能依赖 B 技能的输出格式技能有版本今天改了一版明天想回滚技能要分环境本地调试用的和团队共享的不一样技能还要能一键安装到新机器上而不是每次手动复制粘贴。这些需求手动管理根本扛不住。skills CLI的价值就在这——它把技能从散落的文件变成了可管理的包。安装、卸载、列出、更新、校验全走命令。这跟 npm、pip 管理依赖是一个道理当数量少的时候你觉得多余数量一多你就离不开。3.2 典型命令与使用场景下面这些命令形态是基于常见 skills CLI 的设计惯例整理的具体参数以你实际安装的版本为准。我按使用频率从高到低排。# 列出当前已安装的所有技能确认环境里有什么 skills list # 安装一个技能通常支持从本地路径或远程源安装 skills install skill-name # 查看某个技能的详细信息包括触发条件、依赖、版本 skills info skill-name # 更新技能到最新版本 skills update skill-name # 卸载不再需要的技能保持环境干净 skills remove skill-name # 校验技能配置是否合法避免带病上岗 skills validate skill-name这里我要重点说skills validate这个命令。很多人装完技能就直接用从来不校验结果 agent 行为诡异还找不到原因。校验能提前发现的问题包括依赖的技能没装、输入输出格式对不上、约束条件写成了矛盾条款。花十秒钟跑一下校验能省你半小时的排查时间。3.3 技能目录的组织方式CLI 背后对应的是一套目录结构。理解这个结构你才能知道技能到底住在哪、怎么被加载的。常见的组织方式大致是这样skills/ ├── test-driven-development/ │ ├── skill.yaml # 技能元数据名称、版本、触发条件 │ ├── steps.md # 执行步骤说明 │ ├── constraints.md # 约束边界 │ └── examples/ # 示例输入输出供 agent 参考 ├── code-review/ │ ├── skill.yaml │ └── ... └── run-command/ ├── skill.yaml └── ...每个技能一个目录目录里放元数据、步骤、约束、示例。这种结构的妙处在于技能之间物理隔离互不污染。你想改某个技能只动它自己的目录不会牵连别的。想删某个技能直接删目录干净利落。提示技能目录的命名建议用短横线连接的小写英文比如test-driven-development而不是TestDrivenDevelopment。这不是审美问题而是很多 CLI 在解析路径时对大小写和特殊字符敏感统一命名能避免一堆莫名其妙的加载失败。3.4 技能加载的优先级与冲突处理当技能多起来之后一个绕不开的问题是两个技能都声称能处理同一类任务agent 该听谁的这就要说到加载优先级。通常的规则是项目级技能覆盖用户级技能用户级技能覆盖全局默认技能。也就是说你在某个项目里专门配的技能优先级高于你个人全局配的更高于系统自带的。这个设计符合直觉——越贴近具体场景的配置越应该说了算。但优先级只能解决谁覆盖谁解决不了两个平级技能打架。这时候就需要在技能元数据里显式声明互斥关系或者用命名空间把技能分组。我的经验是宁可把技能拆细一点也不要让一个技能管太宽。一个技能只干一件事冲突的概率就低一个技能想包打天下最后一定是到处打架。4. 用 TDD 工作流驯服 AI coding agent4.1 为什么 TDD 特别适合 agenttest-driven-development出现在关键词里不是偶然。在所有软件工程实践里TDD 可能是最适合 AI coding agent 的一种。原因有三。第一TDD 把对不对变成了可自动判定的问题。人写代码对错靠 review、靠经验、靠直觉agent 写代码如果有一套测试在对错就是测试过没过这个二值问题。二值问题 agent 自己能判断不需要人来当裁判。第二TDD 天然是分步的而 agent 擅长执行分步指令。红-绿-重构每一步都有明确的输入和输出。你让 agent写一个完美的模块它容易懵你让它先写一个会失败的测试它执行得很稳。第三TDD 提供了即时反馈而反馈是 agent 自我修正的燃料。测试失败的信息会告诉 agent 哪里错了它据此调整再跑再调。这个循环不需要人介入agent 自己就能转起来。4.2 红-绿-重构在 agent 场景下的具体落地理论说完了讲实操。把 TDD 工作流交给 agent 执行我通常按下面这个节奏走。第一步明确需求边界。在让 agent 动手之前我会先用一两句话把这个函数/模块要做什么、输入是什么、输出是什么、边界情况有哪些讲清楚。这一步不能省因为 agent 不会读心需求模糊它就只能瞎猜。第二步让 agent 先写测试。指令大概是根据上面的需求写一组测试用例覆盖正常路径和至少两个边界情况先不要写实现。这时候 agent 产出的测试我会快速扫一眼确认它理解的需求跟我一致。如果测试写歪了后面全白搭所以这一步的检查很关键。第三步让 agent 写实现跑到测试全绿。指令是现在写实现让上面所有测试通过不要修改测试本身。这里有个细节明确禁止它改测试。否则 agent 发现实现太难可能会偷偷把测试改简单那就失去意义了。第四步让 agent 重构。测试全绿之后再让它在不改变测试结果的前提下优化代码结构。这一步可选但对代码质量有帮助。第五步人工验收。最后我会自己跑一遍测试再看一眼实现确认没有为了过测试而写的畸形代码。4.3 一个完整的 TDD 交互示例光说步骤太干我举个具体例子。假设要让 agent 实现一个计算购物车总价的函数支持折扣和满减。我先给需求实现一个calculateTotal(items, discount)函数。items 是商品数组每项有 price 和 quantitydiscount 是折扣率0 到 1 之间。返回折后总价保留两位小数。边界情况空数组返回 0discount 为 0 时不打折discount 为 1 时返回 0。然后让 agent 写测试。它可能产出类似这样的东西def test_calculate_total_empty_cart(): assert calculate_total([], 0.1) 0 def test_calculate_total_no_discount(): items [{price: 10.0, quantity: 2}] assert calculate_total(items, 0) 20.0 def test_calculate_total_with_discount(): items [{price: 10.0, quantity: 2}] assert calculate_total(items, 0.5) 10.0 def test_calculate_total_full_discount(): items [{price: 10.0, quantity: 2}] assert calculate_total(items, 1) 0我扫一眼发现它漏了保留两位小数的验证于是补一句再加一个测试验证小数精度比如价格是 9.99、数量是 3 的情况。它补上之后我再让它写实现。这样一轮下来产出的代码质量比直接让它写个购物车函数高出一大截。4.4 TDD 工作流里最容易翻车的三个点第一个坑测试写得太宽泛。agent 有时候会写出assert result is not None这种废话测试跑起来永远绿但什么都没验证。对策是在指令里明确要求每个测试必须验证具体的数值或行为。第二个坑agent 偷偷改测试。前面提过实现遇到困难时agent 可能把测试改松。对策是明确禁止并且在验收时对比测试文件的改动。第三个坑测试之间互相依赖。agent 写的测试有时会共享状态导致单独跑能过、一起跑就挂。对策是要求每个测试独立不依赖执行顺序。注意TDD 工作流对 agent 的上下文长度有要求。如果测试和实现加起来太长agent 可能会忘记前面的测试内容。这时候要把任务拆小一次只处理一个函数或一个模块。5. 把 agent-skills 接进 Claude Code 这类工具5.1 接入前先想清楚你要 agent 干什么现在聊接入。很多人一上来就研究怎么配置我觉得顺序反了。先想清楚你要 agent 承担哪几类任务再去配对应的技能否则就是堆配置堆完发现没一个用得上。我的做法是先列一张任务清单把日常开发里重复性高、规则明确、容易验证的活儿挑出来。比如写单元测试、根据报错定位问题、批量重命名变量、生成接口文档、跑 lint 并修复。这些活儿共同点是——有明确的对错标准agent 干完你能快速判断好坏。反过来像设计系统架构决定技术选型这种模糊任务现阶段还是人来主导更靠谱。5.2 环境准备里最容易被忽略的两件事接入 Claude Code 这类工具环境准备通常不复杂但有两件事特别容易被忽略。第一件是工作目录的隔离。别让 agent 直接在你有未提交改动的仓库里撒欢。我的习惯是给 agent 单独开一个工作目录或者至少先git commit一次这样它改坏了你能一键回滚。没有版本控制兜底的 agent 操作等于裸奔。第二件是权限边界。agent 能执行终端命令这件事威力大也风险大。要明确它能碰哪些目录、能跑哪些命令。比如读文件、跑测试、装依赖通常没问题但删文件、改系统配置、动数据库这类操作一定要设卡。这不是不信任 agent而是任何自动化都需要护栏。5.3 技能与工具的协同让 agent 知道什么时候用什么接入之后真正的挑战是让 agent 在合适的时机调用合适的技能。这靠的是技能元数据里的触发描述写得够不够清楚。举个例子你有两个技能write-test和fix-bug。如果触发描述都写得很模糊agent 可能在你让它修 bug 的时候跑去写测试。好的触发描述应该是这样的write-test当用户要求为新功能添加测试或补充测试覆盖时触发。fix-bug当用户提供报错信息、失败测试或描述具体缺陷时触发。触发条件写得越具体agent 的判断越准。这跟给新人写 SOP 是一个道理你写得越含糊他越容易做错。5.4 验证接入是否成功的三个信号配完之后怎么知道接对了我看三个信号。信号一agent 会主动调用技能而不是每次都要你提醒。你让它修个 bug它自己就走fix-bug流程而不是干等着你一步步指挥。信号二产出质量稳定。同一个技能处理同类任务结果水准一致不会这次很好下次很烂。稳定说明技能定义清晰agent 有章可循。信号三出错时能自我修正。agent 跑测试失败后会自己分析原因、调整、重跑而不是直接把失败结果甩给你。这个信号最能说明 TDD 工作流真正跑通了。三个信号都出现说明你的 agent-skills 接入是成功的。缺哪个就回去补哪块的配置。6. 实战中踩过的坑与排查链路6.1 技能装了但 agent 不调用一次完整的排查我遇到过最典型的问题技能明明装好了skills list也能看到但 agent 就是不用。当时我以为是 CLI 的问题折腾了半天最后发现根子在触发描述。排查链路是这样的。第一步确认技能真的被加载了——跑skills list在列表里。第二步确认技能文件没语法错误——跑skills validate通过。第三步看 agent 的日志发现它压根没看到这个技能。第四步检查技能元数据的触发描述发现我写的是用于处理代码相关任务——太宽泛了agent 无法判断什么时候该用。改成当用户要求重构函数、且提供了明确的输入输出说明时触发之后问题解决。这个坑的教训是技能不被调用九成是触发描述的问题而不是安装的问题。排查时从描述是否具体入手比从安装是否成功入手效率高得多。6.2 agent 陷入死循环测试永远跑不过第二个坑更折磨人。agent 写了个实现测试跑不过它改还跑不过再改来回十几轮token 烧了一堆问题还在。根因通常是测试本身有问题或者需求本身有矛盾。agent 不知道是测试错了它默认测试是对的于是拼命改实现去迁就一个错误的测试当然永远过不了。我的处理办法是一旦发现 agent 连续三轮以上没进展立刻打断人工检查测试。十有八九是测试写错了或者需求里有互相矛盾的条件。别让 agent 在错误的方向上死磕及时介入比让它自己撞墙划算。6.3 技能之间的隐性依赖导致的连锁失败第三个坑比较隐蔽。我有两个技能A 负责生成代码B 负责格式化代码。单独用都没问题但 A 生成的代码格式不符合 B 的预期导致 B 一跑就报错。这种隐性依赖光看单个技能的配置是发现不了的。解决办法是在技能元数据里显式声明依赖和接口约定A 的输出格式必须满足什么规范B 的输入期望什么格式两边对齐。或者更省事的办法——把 A 和 B 合并成一个技能让格式规范在内部统一。能合并的依赖就别拆成两个技能这是我踩了几次坑之后的结论。6.4 上下文超限长任务跑到一半失忆第四个坑和模型能力有关。任务一长agent 的上下文塞满了它就开始失忆——前面定的约束忘了前面写的测试忘了甚至前面确认过的需求也忘了。对策是把长任务拆成短任务每个短任务独立可验证。比如重构一个大模块不要一次性交给 agent而是拆成重构函数 A重构函数 B这样的小任务每个任务完成后确认结果再进下一个。这样既避免了上下文超限也让每一步都可控。提示如果你发现 agent 开始重复之前已经做过的事或者问一些你已经回答过的问题基本就是上下文快满了。这时候主动拆任务比等它彻底乱套再收拾要好。7. 我对 agent-skills 这套思路的真实看法用了一段时间之后我最大的体会是agent-skills 的价值不在于它提供了多少现成技能而在于它逼着你把怎么干活这件事想清楚。以前我们用 AI是我有个模糊的想法你来猜我想要什么。现在用 agent-skills是我把任务拆成明确的步骤、约束和验证标准你来执行。这个转变看着小实际很大——它把 AI 从灵感来源变成了可靠执行者。而可靠恰恰是工程场景里最稀缺的东西。另一个体会是技能是要养的不是配一次就完事。你会在使用中不断发现新的边界情况、新的失败模式然后回头去补技能定义。这个过程跟维护代码库一模一样需要持续投入。指望配一套技能就一劳永逸那是不现实的。最后分享一个我自己的小习惯每当我发现 agent 在某类任务上反复出错我不会急着骂模型笨而是先问自己——我有没有把这类任务的技能定义清楚十次里有八次问题出在我这边而不是模型那边。把技能补上问题往往就消失了。这个习惯帮我省了很多无谓的折腾也让我对怎么跟 AI 协作这件事理解得越来越深。
返回列表