ARTICLE DETAIL

资讯详情

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

agent-skills实战:用TDD和skills CLI构建可复用AI编码技能

agent-skills实战:用TDD和skills CLI构建可复用AI编码技能 1. 从“agent-skills”说起为什么它值得单独拿出来聊第一次看到agent-skills这个标题很多人会下意识把它当成某个开源仓库的名字或者某个 AI 工具链里的一个子模块。但如果你最近在折腾 AI coding agents尤其是 Claude Code 这类能在终端里直接读写文件、跑测试、执行命令的智能体你会发现“skills”这个词正在变成一个独立的概念层——它既不是模型本身也不是简单的 prompt 模板而是介于两者之间的一套可复用能力封装。我最初接触这个概念是因为一个很现实的问题每次让 AI coding agent 帮我处理一个稍微复杂点的任务比如“给这个模块补一组单元测试跑通后提交”我都要在对话里反复交代项目结构、测试框架、命名习惯、提交规范。下一次换个项目同样的交代又要重来一遍。这种重复劳动非常消耗耐心而且容易漏掉关键约束导致 agent 生成的东西看起来对、跑起来错。agent-skills要解决的就是这个问题。它把“在特定场景下agent 应该知道什么、按什么顺序做什么、遵守哪些约束”打包成一个可加载、可复用、可版本管理的单元。你可以把它理解成给 AI coding agent 准备的“操作手册 检查清单 工具绑定”三合一。一个 skill 可能对应“写 pytest 测试”“做代码审查”“生成数据库迁移脚本”“按团队规范提交 commit”这样的具体能力。这篇文章适合三类人看。第一类是把 Claude Code 当日常开发工具、但还没系统化整理自己工作流的开发者第二类是正在评估 AI coding agents 能不能进团队、需要一套可复制方法论的 tech lead第三类是对 skills CLI、test-driven-development 这类关键词感兴趣、想搞清楚它们怎么串起来的技术爱好者。我会从设计思路讲到实操细节再把我自己踩过的坑和排查经验摊开说尽量让你看完就能动手搭一套自己的 skill。2. 整体设计思路为什么是“技能”而不是“提示词”2.1 提示词工程的瓶颈在哪里过去两年大家调 AI coding agent 的主要手段是写 prompt。系统提示词、用户提示词、few-shot 示例本质上都是在用自然语言描述“我希望你怎么做”。这套方法在单次任务里够用但一旦进入工程化场景问题就暴露了。第一个问题是不可组合。你写了一个很长的 prompt 描述“如何写测试”又写了一个很长的 prompt 描述“如何做代码审查”当你想让 agent 先审查再补测试时两个 prompt 会互相干扰token 消耗也直线上升。第二个问题是不可验证。prompt 写得好不好全靠人工看输出结果没有单元测试没有回归检查。第三个问题是不可版本化。prompt 散落在各个对话记录、配置文件、笔记里改了一版之后旧版找不回来团队里也没法共享。agent-skills的思路是把这些自然语言约束结构化。一个 skill 通常包含几个固定部分触发条件什么时候该用这个 skill、前置检查用之前要确认什么、操作步骤按什么顺序做什么、工具绑定允许调用哪些命令或 API、验收标准怎么判断做完了。这种结构让 skill 可以被加载、卸载、组合、测试而不是一坨越写越长的文字。2.2 skills CLI 的角色让技能可管理光有 skill 的定义还不够你得有工具去管理它们。这就是skills CLI出现的原因。它做的事情类似包管理器列出可用 skills、安装某个 skill 到当前项目、更新版本、查看某个 skill 的详细内容、在 agent 启动时按需加载。我自己的习惯是把 skills 分成三层。全局层放跨项目通用的能力比如“按 conventional commits 规范提交”“用 ripgrep 搜索代码库”“生成变更摘要”。项目层放跟具体技术栈绑定的能力比如“这个 Spring Boot 项目里写集成测试的步骤”“这个 React 项目里新增页面的文件清单”。临时层放一次性任务的能力比如“把这份 CSV 转成数据库 seed 脚本”用完就删。这种分层的好处是agent 在启动时只需要加载全局层和当前项目层临时层按需注入既保证了对项目规范的理解又不会让上下文爆炸。skills CLI 的另一个价值是让 skill 可以被 review。团队里谁改了某个 skill 的操作步骤diff 一目了然比在聊天记录里翻 prompt 靠谱得多。2.3 为什么 test-driven-development 会成为核心关键词在 agent-skills 的讨论里test-driven-development出现的频率非常高这不是偶然。AI coding agent 最大的风险是“看起来对”。它生成的代码语法正确、风格漂亮但逻辑可能是错的边界条件可能没处理异常路径可能直接崩。人类开发者靠经验能嗅出不对劲agent 没有这种直觉。TDD 在这里扮演的是验证锚点的角色。一个设计良好的 skill如果涉及代码生成应该强制走“先写失败测试、再写实现、再跑测试、再重构”的流程。这样 agent 每一步都有明确的反馈信号测试从红变绿说明实现至少满足了测试描述的契约测试没变绿agent 就知道要回头改而不是继续往下编。我实测下来把 TDD 写进 skill 的验收标准之后agent 一次性生成可用代码的概率明显提升。原因很简单它不再靠“猜”来判断自己做得对不对而是有一个可执行的判据。这个判据还可以被人类审查——测试本身写得好不好比实现代码好不好审查容易得多。3. 核心细节解析一个 skill 到底由什么组成3.1 触发条件与作用域声明每个 skill 开头都应该明确回答一个问题什么时候该用我。这听起来简单但实际写的时候很容易含糊。比如“写测试”这个 skill触发条件如果只写“当需要写测试时”那 agent 几乎在任何涉及代码的场景都会想加载它造成干扰。我的做法是把触发条件写成“场景 信号”的组合。场景是任务类型信号是环境里可观察到的特征。举个例子场景用户要求为某个模块补充测试覆盖信号项目根目录存在pytest.ini或pyproject.toml中包含 pytest 配置目标模块路径下已有test_前缀文件这样 agent 在判断是否加载这个 skill 时有具体的文件系统信号可以检查而不是靠语义猜测。作用域声明则说明这个 skill 适用于哪些路径、哪些文件类型、哪些分支状态。把作用域写清楚能避免 skill 在错误的地方被激活比如把 Python 测试 skill 用到前端项目里。3.2 前置检查清单别让 agent 在错误前提下开工前置检查是我认为最容易被忽略、但收益最高的部分。人类开发者接到任务时会下意识确认几件事当前分支对不对、工作区干不干净、依赖装没装、相关服务起没起。agent 如果没有这些检查很容易在一个错误的基础上开始干活最后产出完全没法用。一个典型的 Python 测试 skill前置检查可以包括确认当前工作目录是项目根目录存在pyproject.toml或setup.py确认虚拟环境已激活python -c import pytest能正常执行确认目标模块文件存在且可读确认当前 git 分支不是main或master避免直接在主分支上改测试确认工作区没有未提交的、与本次任务无关的改动这些检查看起来琐碎但每一条都对应一种真实翻车场景。我遇到过 agent 在没激活虚拟环境的情况下跑测试结果用的是系统 Python依赖版本不对测试全挂然后它开始“修复”一个根本不存在的问题。加上前置检查之后这类问题基本消失了。3.3 操作步骤的粒度控制操作步骤写多细是个需要权衡的事。写太粗agent 自由发挥空间太大容易跑偏写太细skill 变得冗长维护成本高而且遇到稍微不同的情况就不适用。我的经验是关键决策点写细机械操作写粗。什么叫关键决策点比如“先写测试”这个决策要明确写清楚测试文件放哪、命名规则是什么、用哪个 fixture、断言风格是什么。因为这些地方一旦 agent 自己发挥就会跟项目现有风格不一致。而“运行测试命令”这种机械操作写一句“执行pytest test_file -v”就够了不需要解释 pytest 怎么用。另一个技巧是把步骤写成可勾选的清单而不是连续段落。清单形式让 agent 更容易跟踪进度也让人更容易审查 skill 是否完整。我自己的 skill 模板里操作步骤通常控制在 5 到 9 步超过 9 步就考虑拆成两个 skill。3.4 工具绑定与权限边界AI coding agent 能执行终端命令这是它强大的地方也是危险的地方。一个 skill 如果不声明工具绑定agent 可能会用你意想不到的方式完成任务。比如你让它“清理临时文件”它可能直接rm -rf一个你没预料到的目录。工具绑定要做两件事白名单和参数约束。白名单是列出这个 skill 允许调用的命令比如pytest、git diff、ruff check。参数约束是说明这些命令允许带哪些参数比如pytest只允许带测试文件路径和-v、-x这类安全参数不允许带--lf之外可能影响全局状态的选项。注意工具绑定不是万能的agent 仍然可能通过组合命令绕过限制。所以对于破坏性操作比如删除文件、强制推送、修改数据库skill 里应该明确要求 agent 先输出计划、等待人工确认而不是直接执行。3.5 验收标准怎么算“做完了”验收标准是 skill 的收口。没有验收标准agent 不知道什么时候该停人也不知道该检查什么。好的验收标准应该是可执行、可观察、可复现的。以测试 skill 为例验收标准可以写成新增测试文件能被pytest发现并执行在实现代码未修改的情况下新增测试至少有一个失败证明测试确实在测东西实现代码修改后全部新增测试通过测试覆盖率相比修改前有提升如果项目有覆盖率工具ruff check或项目使用的 linter 对新增文件无报错这些标准每一条都能用命令验证不依赖主观判断。我特别推荐“先让测试失败”这一条它能有效防止 agent 写出永远为真的空测试。4. 实操过程从零搭一个可用的 skill4.1 环境准备与 skills CLI 初始化假设你已经在用 Claude Code并且项目是一个 Python 后端服务。第一步是确认你的 agent 环境支持 skill 加载。不同版本的 CLI 行为可能有差异所以先跑一下帮助命令看看skills --help skills list如果skills list返回空说明还没有安装任何 skill。接下来在项目根目录初始化 skill 目录结构。我习惯用.agent-skills/作为项目级 skill 的存放位置跟.github/、.vscode/这类配置目录并列语义清晰。mkdir -p .agent-skills touch .agent-skills/README.md然后在 README 里写清楚这个目录的用途、skill 命名规范、以及如何加载。这一步看起来是形式主义但团队协作时非常有用——新人看到这个目录能快速理解你们的 agent 工作流。4.2 编写第一个 skillpytest-tdd我们以“用 TDD 方式为指定模块补充测试”为例写一个完整的 skill。文件名用pytest-tdd.md放在.agent-skills/下。内容结构如下--- name: pytest-tdd version: 1.0.0 scope: python triggers: - user asks to add tests for a module - project contains pytest configuration tools: - pytest - git diff - ruff check --- ## Preconditions - Working directory is project root - Virtual environment is activated - Target module file exists - Current branch is not main/master ## Steps 1. Read the target module and identify public functions/classes 2. Create or locate the corresponding test file under tests/ 3. Write failing tests for each public behavior 4. Run pytest on the new test file, confirm failures 5. Implement minimal changes if needed to make tests pass 6. Run full test suite for the module 7. Run ruff check on changed files ## Acceptance - New tests are discovered by pytest - Tests fail before implementation, pass after - No lint errors on changed files这个 skill 的关键在于第 3 步和第 4 步的顺序。很多 agent 会先写实现再补测试那样测试就变成了“描述已有行为”失去了 TDD 的验证价值。强制先写失败测试能让 agent 真正思考“这个函数应该做什么”而不是“这个函数现在做了什么”。4.3 参数计算与选择测试粒度怎么定写测试时agent 经常面临一个选择一个函数写几个测试边界条件覆盖到什么程度这个决策如果完全交给 agent结果会很不稳定。有的函数写一个 happy path 就完事有的函数写二十个测试把简单逻辑拆得稀碎。我的做法是在 skill 里加一条启发式规则每个公开函数至少覆盖三类用例——正常输入、边界输入、异常输入。正常输入是典型参数边界输入是空值、零、最大值、最小值异常输入是类型错误、缺失参数、非法状态。这条规则不追求 100% 覆盖率但能保证 agent 不会漏掉明显该测的东西。对于复杂函数再加一条如果函数包含条件分支每个分支至少一个测试。这条规则可以用代码结构分析来辅助判断agent 读一下函数体就能数出分支数量。实测下来这两条规则组合起来生成的测试集质量比“尽量多写”这种模糊指令高很多。4.4 实操现场一次完整的 skill 执行记录我拿一个真实的小项目试过这个 skill。项目里有个parse_duration函数输入类似1h30m的字符串返回秒数。我让 agent 加载pytest-tddskill然后说“给 parse_duration 补测试”。agent 的执行过程大致如下。它先读了模块文件确认parse_duration是公开函数签名是def parse_duration(s: str) - int。然后它找到tests/test_duration.py发现文件存在但为空。接着它写了四个测试1h30m返回 5400、45s返回 45、抛出 ValueError、abc抛出 ValueError。跑 pytest四个测试里前两个失败因为实现还没写后两个通过因为实现里已经有异常处理。agent 看到这个结果判断“异常路径已覆盖正常路径需要实现”。它去改了实现补上了小时和分钟的解析逻辑再跑测试全绿。最后跑 ruff没有报错。整个过程我没有干预agent 也没有跑偏。对比之前没有 skill 的时候它经常先改实现再补测试而且测试里会混入对内部辅助函数的测试粒度很乱。4.5 把 skill 接入日常流程skill 写好之后关键是让它进入日常流程而不是躺在目录里吃灰。我的做法是在项目的CLAUDE.md或类似的 agent 配置文件中声明默认加载哪些 skill。这样每次启动 agent它自动带上项目级 skill不需要我手动提醒。另外我会在 CI 里加一步检查如果 PR 修改了.agent-skills/下的文件要求至少一个人类 reviewer 批准。skill 是会影响 agent 行为的配置跟代码一样需要 review。这一步能防止有人不小心改坏了 skill 里的工具绑定导致 agent 执行危险命令。5. 常见问题与排查技巧实录5.1 skill 不生效或加载失败最常见的问题是 skill 写了但 agent 没加载。排查顺序建议从外到内先确认skills list能看到这个 skill再确认 skill 的触发条件是否匹配当前任务最后确认 agent 的配置文件里有没有排除这个 skill。我遇到过一次skill 文件放在.agent-skills/下但skills list不显示。原因是文件头部的 YAML front matter 格式错了triggers写成了字符串而不是列表。skills CLI 解析失败后静默跳过没有报错。后来我养成了习惯写完 skill 先跑skills validate file确认格式没问题再提交。5.2 agent 跳过前置检查直接开工前置检查写了但 agent 不执行这种情况通常是因为检查步骤没有被写成可执行命令。如果前置检查只是自然语言描述“确认虚拟环境已激活”agent 可能觉得“我知道不用查”。但如果写成“执行python -c import sys; print(sys.prefix)并确认输出路径包含项目目录”agent 就更可能真的去跑。我的经验是前置检查里每一条都要绑定一个可执行命令或可观察的文件状态。纯描述性的检查agent 的遵守率明显更低。5.3 测试写得太浅或太深测试粒度失控是另一个高频问题。太浅的表现是只测 happy path边界和异常完全不碰太深的表现是测试内部辅助函数、mock 过多、断言实现细节而不是行为。针对太浅我在 skill 里加了“三类用例”规则前面已经说过。针对太深我加了一条约束测试只针对公开接口不直接测试以下划线开头的函数。如果 agent 觉得某个内部函数需要测试应该通过公开接口间接覆盖。这条约束能有效减少脆弱的实现耦合测试。5.4 工具绑定被绕过前面提到工具绑定不是万能的。我实测发现agent 有时会用bash -c ...把多个命令包起来绕过白名单检查。应对方法是在 skill 里明确禁止bash -c和sh -c的嵌套调用并且把这条禁令放在工具绑定部分的最前面。另一个技巧是给危险命令加“确认门”。比如 skill 里如果需要执行git commit要求 agent 先输出 commit message 和变更文件列表等待人工确认后再执行。这个确认门不需要复杂实现在 skill 步骤里写清楚就行。5.5 常见问题速查表问题现象可能原因排查动作skill 不出现在列表中YAML 格式错误跑skills validate检查agent 不加载 skill触发条件不匹配检查任务描述是否包含触发信号前置检查被跳过检查项不可执行把描述改成命令或文件状态检查测试只覆盖 happy path缺少粒度规则在 skill 中补充三类用例要求工具白名单被绕过嵌套 shell 调用禁止bash -c嵌套加确认门skill 改动导致行为异常缺少 reviewCI 中要求 skill 变更需人工批准5.6 几个我踩过的坑第一个坑是skill 版本冲突。项目级 skill 和全局 skill 同名时不同 CLI 版本的优先级规则不一样。有的版本项目级覆盖全局有的版本反过来。我的解决办法是给项目级 skill 加前缀比如proj-pytest-tdd避免跟全局 skill 撞名。第二个坑是skill 太长导致上下文超限。我一开始想把所有测试相关的规则都塞进一个 skill结果文件超过两千字agent 加载后反而记不住重点。后来拆成pytest-tdd和pytest-fixtures两个 skill各自聚焦一个主题效果更好。第三个坑是验收标准写得太模糊。比如“测试质量良好”这种标准agent 没法判断人也没法检查。改成“新增测试在实现未修改时至少一个失败”之后可操作性立刻上来了。6. 技能组合与进阶玩法6.1 多 skill 串联审查加测试加提交单个 skill 解决单点问题多个 skill 串联能覆盖完整工作流。我常用的组合是code-reviewpytest-tddconventional-commit。流程是先让 agent 用code-reviewskill 检查当前变更输出问题列表然后针对问题用pytest-tdd补测试和修复最后用conventional-commit生成规范提交信息。串联的关键是skill 之间的接口要清晰。code-review的输出格式如果是自由文本下一个 skill 很难解析。所以我要求code-review输出结构化列表每条包含文件路径、行号、问题类型、建议动作。这样pytest-tdd可以直接读取问题列表针对性地补测试。6.2 把团队规范编码进 skill团队里总有一些“口口相传”的规范比如“service 层不直接调 repository必须经过 domain 层”“所有外部调用必须包 try-catch 并记录日志”。这些规范新人容易忘老人 review 时反复提。把它们写进 skillagent 在生成代码时就会自动遵守。我做过一个实验把五条最常被 review 提到的规范写进一个team-conventionsskill然后让 agent 生成十个新接口。结果这十条规范全部被遵守review 时关于规范的评论从平均每条 PR 三条降到零条。这个投入产出比非常高。6.3 skill 的测试与回归skill 本身也需要测试。我的做法是准备一组“黄金任务”每个任务对应一个 skill记录期望的 agent 行为。每次修改 skill 后跑一遍黄金任务看 agent 行为是否符合预期。这听起来重但黄金任务不需要自动化人工跑一遍也就十几分钟比 skill 悄悄失效导致 agent 乱来划算得多。黄金任务的设计要点是覆盖 skill 的关键决策点。比如pytest-tdd的黄金任务应该包含一个“实现已存在、需要补测试”的场景和一个“实现不存在、需要先写测试”的场景。两个场景下 agent 的行为应该不同如果它搞混了说明 skill 的触发条件或步骤描述有问题。7. 我个人的一些体会折腾 agent-skills 这段时间最大的感受是AI coding agent 的上限不取决于模型多强而取决于你给它搭的脚手架多稳。同一个模型没有 skill 的时候像个聪明但毛躁的实习生有了 skill 之后像个熟悉项目规范的老手。差别不在智力在约束和流程。另一个体会是写 skill 的过程其实是在逼自己把隐性知识显性化。很多规范你平时觉得“大家都知道”真写下来才发现自己也没想清楚。这个过程对团队知识沉淀的价值可能比 agent 本身还大。最后分享一个小技巧skill 写完之后先别急着让 agent 用自己按步骤手动走一遍。如果某一步你自己都觉得别扭或者说不清楚agent 大概率也会在这里出问题。手动走一遍能筛掉大部分设计缺陷比事后调试省事得多。
返回列表