☰
agent-skills实战:用TDD和skills CLI构建可复用AI编码技能
2026/10/7 22:11:33 网站建设 项目流程

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. 实操过程:从零搭一个可用的 skill

4.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 编写第一个 skill:pytest-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-review+pytest-tdd+conventional-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 时反复提。把它们写进 skill,agent 在生成代码时就会自动遵守。

我做过一个实验:把五条最常被 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 大概率也会在这里出问题。手动走一遍能筛掉大部分设计缺陷,比事后调试省事得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询