Agent Skill 工程化:把 AI 编程助手的流程固化为可复用的作战手册
Skill 不是更长的 prompt,不是 system prompt,更不是 MCP Server。MCP 是工具箱,Skill 是作战手册。这篇讲清楚它的结构、路由、编排与质量门禁,以及什么时候根本不该写。
同一个 AI 编程助手,两个团队用出完全不同的结果:一个团队让它”跑一遍测试流水线,出报告和门禁结论”,它真的能按固定顺序产出用例、执行、汇总;另一个团队每次都要重新解释一遍”我们是怎么做测试的”,解释到第三轮上下文就乱了。
差别不在模型,在流程有没有被固化。固化下来的那个东西,叫 Skill。
一、Skill 是什么,不是什么
先划清边界。Skill 不是:
- 不是一段更长的 prompt。prompt 是对一次对话的指令,Skill 是对一类任务的长期约定;
- 不是 system prompt。system prompt 全局生效、永远占上下文;Skill 按需加载,不用就不占;
- 不是 MCP Server。MCP 给 Agent 提供”能力”(工具、数据、资源),Skill 给 Agent 提供”打法”(什么时候用哪个能力、按什么顺序、产出什么、什么算完成)。
一句话:MCP 是工具箱,Skill 是作战手册。手册不替代扳手,它告诉你在哪种故障下先拿哪把扳手、拧完要记录什么。
一个 Skill 的物理形态很朴素:一个目录,里面一份 SKILL.md,描述四件事:
- 触发条件:什么情况下该用我(以及什么情况下不该);
- 步骤:按什么顺序做什么,每步的输入输出;
- 产物约定:产出物放哪、叫什么、长什么样;
- 边界与红线:哪些操作禁止、哪些情况必须停下来问人。
---
name: debugging-flaky-ui-tests
description: 排查偶发失败的 UI 用例。当用例在 CI 上
间歇性失败、怀疑硬等待或竞态时使用。
---
# Flaky 用例排查
## 触发
- 同一用例在 CI 上失败率 > 0 且本地复现不稳定
- 失败信息含 timeout / element not found / detached
## 步骤
1. 拉取失败 run 的 trace 与截图,先定位失败步骤,不要先改代码
2. 按清单逐项检查:硬等待 sleep、缺少 web-first 断言、
共享状态、动画未关闭、时区/ locale 依赖
3. 给出修复 diff 与"为什么这会 flaky"的一句话结论
## 红线
- 禁止用增加 timeout 的方式"修" flaky
- 禁止删除断言让用例变绿注意 description 的写法:它不是给人看的简介,是给路由模型看的触发器。写”排查 flaky”没用,写”当用例在 CI 上间歇性失败、怀疑硬等待或竞态时使用”才有用——触发条件越具体,误加载越少。
二、第一个要写的 Skill 是”路由”
新手最常见的错误:把十个 Skill 一次性全塞给 Agent。上下文立刻膨胀,模型开始在各套流程之间串味,产出质量断崖式下跌。
正确做法是先写一个路由 Skill,它自己不做任何事,只负责选型:
/using-ai-testing-skills或者直接说:“不知道从哪开始,帮我选测试 skill。”
路由 Skill 的职责是:读任务描述 → 从 Skill 清单里选出该加载哪几个、按什么顺序 → 只把选中的加载进上下文。这是一个”元 Skill”,但它决定了整个体系能不能规模化。判断一个团队的 Skill 体系是否成熟,先看有没有这一层。
三、编排:把 Skill 串成流水线,并给一个统一出口
单点 Skill 解决”一件事怎么做”,编排解决”一串事怎么收尾”。一个典型的测试流水线编排:
请按标准流水线:
1) 根据我附的需求出用例与追溯矩阵
2) 用环境变量切到 TEST_ENV=test
3) 并行:接口 @api-smoke、相关后端单测+覆盖率、UI @smoke
4) 汇总 platform-report 并给门禁结论
需求:@xxx.md
BASE_URL / API_BASE_URL:……这里有两个设计点值得抄:
产物目录有约定。 所有中间产物落到统一结构,人和 CI 都知道去哪找:
test-artifacts/<YYYYMMDD-HHMM-env>/
cases/ # 需求转用例
env.md # 环境与标签说明
api/ # 接口结果
unit/ # 单测 + 覆盖率摘要/HTML 链接
ui/ # Playwright 报告/截图/trace
exploratory/ # 探索性测试
summary/platform-report.md # 统一报告(门禁结论)没有约定的产物等于没有产物:三天后没人知道那份截图属于哪次运行。
门禁结论只认实跑证据。 这条是我见过最有价值的一条规则,原文大意是:没有实跑证据(命令输出、报告文件)时,总评只能写”部分完成”或”失败”,不能标”通过”。
AI 助手有一个天然倾向:把”我写了用例”说成”我验证了功能”。门禁规则把这两件事在产物层面切开——用例是 cases/ 下的文件,验证是 ui/ 下的 trace 和报告,汇总报告里的”通过”必须能指到后者。这一条能挡掉 AI 测试里绝大部分的自我感动。
四、边界与红线要写进 Skill,不要靠口头叮嘱
“别在生产环境跑破坏性用例”这种话,说一次没用,写进 Skill 才每次都生效:
| 项 | 规则 |
|---|---|
@smoke(API+UI) | 必须全过 |
| 本次相关后端单测 | 必须过 |
| 覆盖率阈值 | 有约定才强制,否则只汇报 |
prod + @destructive | 不得执行 |
| 探索性测试 | 默认不挡合并 |
同理,密钥管理也要写死:环境变量、本地 .env.*、CI Secrets,仓库里只提交 env.example。Skill 里写明”只提交模板”,比在 PR 里反复打回便宜得多。
还有一个容易被忽略的边界:探索性测试的”全部功能”要定义清楚。让 Agent “把站点全部功能测一遍”,它会去点删除按钮。合理的定义是”当前角色可见且安全可点的入口”,破坏性操作只记录不执行。把这句话写进 Skill,探索性测试才敢用。
五、Skill 与运行时的分工,别搞混
一个高频误解:以为写了 Skill,Agent 就会自己打开浏览器跑测试。
不会。Skill 只指导 Agent;实跑依赖本机的 Playwright / MCP / Computer Use,或者 CI。 Skill 里写”用 role 定位、web-first 断言”,是告诉 Agent 生成什么样的脚本;脚本能不能跑、在哪跑,是运行时的事。
把这个分工想清楚,很多”Skill 不生效”的问题就消失了:不是手册错了,是手册假设的运行时(比如 Playwright 没装、API_BASE_URL 没配)不存在。所以成熟的 Skill 会带一节”前置条件”,把运行时依赖列成表:
| 能力 | 需要什么 |
|---|---|
| 写用例 / 出文档 | 无,有需求文本即可 |
| UI 自动化实跑 | Node + Playwright(或 MCP / Computer Use) |
| 后端单测+覆盖率 | Maven/Gradle 或 pytest/Jest,且项目可编译 |
| 接口自动化 | API_BASE_URL + 登录方式或 Token |
| 多环境切换 | 本地 .env.* 或 CI Secrets |
六、什么时候不该写 Skill
最后泼一点冷水。以下情况写 Skill 是负收益:
- 一次性任务。流程只用一次,写手册的成本高于直接对话;
- 流程本身还没稳定。团队自己都没想清楚步骤,固化下来只会把混乱制度化;
- 纯知识类内容。“我们的编码规范”更适合放进 rules / 约定文档,它需要全局生效,而不是按需加载;
- 能用代码保证的。能用 lint、CI 门禁、模板脚本强制的事,不要指望 Agent 自觉读手册。
Skill 的甜区是:高频、多步、有明确产物、且容易做错顺序的事。测试流水线、发布检查、故障排查、文档生成,都在这类里。
七、落地清单
如果今天要开始,按这个顺序:
- 先写路由 Skill,哪怕下面只挂两个 Skill;
- 挑一个最痛的多步流程写第一个业务 Skill,四要素齐:触发、步骤、产物、红线;
- 给产物定目录约定,并写死”无实跑证据不得标通过”;
- 把环境依赖写成前置条件表,把密钥规则写成红线;
- 维护一份自检清单:每个目录都有
SKILL.md、name与目录名一致、路由能枚举到全部 Skill。
做完这五步,你和 AI 助手之间就不再是”每次重新教”,而是”按手册执行”。这才是团队级产出和个人玩具之间的分水岭。