技术 AI CodingAgent工程化

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,描述四件事:

  1. 触发条件:什么情况下该用我(以及什么情况下不该);
  2. 步骤:按什么顺序做什么,每步的输入输出;
  3. 产物约定:产出物放哪、叫什么、长什么样;
  4. 边界与红线:哪些操作禁止、哪些情况必须停下来问人。
markdown
---
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,它自己不做任何事,只负责选型:

text
/using-ai-testing-skills

或者直接说:“不知道从哪开始,帮我选测试 skill。”

路由 Skill 的职责是:读任务描述 → 从 Skill 清单里选出该加载哪几个、按什么顺序 → 只把选中的加载进上下文。这是一个”元 Skill”,但它决定了整个体系能不能规模化。判断一个团队的 Skill 体系是否成熟,先看有没有这一层。

三、编排:把 Skill 串成流水线,并给一个统一出口

单点 Skill 解决”一件事怎么做”,编排解决”一串事怎么收尾”。一个典型的测试流水线编排:

text
请按标准流水线:
1) 根据我附的需求出用例与追溯矩阵
2) 用环境变量切到 TEST_ENV=test
3) 并行:接口 @api-smoke、相关后端单测+覆盖率、UI @smoke
4) 汇总 platform-report 并给门禁结论
需求:@xxx.md
BASE_URL / API_BASE_URL:……

这里有两个设计点值得抄:

产物目录有约定。 所有中间产物落到统一结构,人和 CI 都知道去哪找:

text
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 的甜区是:高频、多步、有明确产物、且容易做错顺序的事。测试流水线、发布检查、故障排查、文档生成,都在这类里。

七、落地清单

如果今天要开始,按这个顺序:

  1. 先写路由 Skill,哪怕下面只挂两个 Skill;
  2. 挑一个最痛的多步流程写第一个业务 Skill,四要素齐:触发、步骤、产物、红线;
  3. 给产物定目录约定,并写死”无实跑证据不得标通过”;
  4. 把环境依赖写成前置条件表,把密钥规则写成红线;
  5. 维护一份自检清单:每个目录都有 SKILL.md、name 与目录名一致、路由能枚举到全部 Skill。

做完这五步,你和 AI 助手之间就不再是”每次重新教”,而是”按手册执行”。这才是团队级产出和个人玩具之间的分水岭。