SKILL.md:测试人员的AI上岗操作证与人机协作协议 1. 项目概述SKILL.md 不是文档是 Agent 的“上岗操作证”你有没有遇到过这样的场景团队里新来一位测试同学被安排接入一个刚上线的自动化测试 Agent结果对着控制台发呆——不是不会写代码而是根本不知道这个 Agent “认什么指令”、“能听懂哪些话”、“干错活了怎么喊停”。我带过的几个模拟项目X里70%的新手卡点不在技术栈而在“不知道该跟 Agent 说什么”。而 SKILL.md 这个文件就是解决这个问题的钥匙。它不是传统意义上的说明文档更像是一张贴在 Agent 脑门上的“岗位说明书操作速查卡安全边界告示牌”三合一凭证。标题里说“一个 SKILL.md 就能让 Agent 干活”这话没夸张——只要这份文件写得准、写得实、写得细哪怕测试人只懂基础 Markdown 和业务术语也能在5分钟内让 Agent 执行一次接口巡检、生成一份缺陷摘要、甚至自动比对两轮测试报告的差异项。它背后对应的是当前测试领域最实际的演进方向从“人写脚本驱动工具”转向“人用自然语言指挥智能体”。关键词里的“测试人入门必看”恰恰点中了要害——这不是给算法工程师看的模型结构图而是给每天要跑20个用例、填3份日报、还要临时救火的测试同学准备的“第一块踏脚石”。它不涉及模型训练、不依赖GPU资源、不需要调参经验唯一门槛是你得清楚自己日常到底在做什么、怎么做、哪些步骤绝对不能出错。下面我会以一个真实模拟项目X中的测试Agent为蓝本把 SKILL.md 从设计逻辑、字段含义、实操陷阱到排错心法一层层剥开给你看。2. SKILL.md 的底层设计逻辑为什么必须是 Markdown为什么必须叫这个名字2.1 它不是配置文件而是“人机协议”的最小可行载体很多人第一反应是“这不就是个 YAML 配置”或者“直接写个 JSON 不更规范”——这是典型的技术惯性思维。但 SKILL.md 的存在本质是在解决一个更底层的问题降低人和 Agent 之间的语义摩擦成本。我们拆解一下测试人的日常工作流看需求文档 → 拆用例 → 设计数据 → 执行测试 → 记录结果 → 分析差异 → 提交缺陷这些动作里90% 是用自然语言描述的比如“检查登录失败时提示是否包含‘密码错误’四个字”只有10% 是纯技术动作比如“调用 /api/v1/login 接口body 传 {‘user’:‘test’, ‘pwd’:‘123’}”。如果强制要求测试人去写 JSON Schema 或 YAML 描述“当用户说‘查下昨天失败的用例’时Agent 应该执行 SQL 查询 test_result 表并按 status‘fail’ 过滤”那等于把“翻译官”的活儿又塞回给人。而 Markdown 天然支持混合表达用#标题定义技能大类如# 接口测试用-列表写触发条件如- 当用户提到‘超时’、‘响应慢’、‘504’时用代码块bash 写真实可执行命令如bash curl -X GET http://test-api/status 用加粗强调关键约束如必须校验返回码为200否则终止执行这种混排能力让一份 SKILL.md 同时具备三种角色对测试人是“我该怎么跟它说”的口语化指南对开发人是“这个 Agent 能力边界的白纸黑字契约”对 Agent 引擎是可被规则引擎解析的结构化指令集通过正则关键词匹配上下文槽位提取实现无需大模型实时理解。提示SKILL.md 的解析逻辑通常不走 LLM 推理而是基于轻量级 NLU 模块如 Rasa NLU 或自研关键词意图树。这意味着它启动快、响应稳、成本低——这也是它能在测试环境快速落地的根本原因。2.2 “SKILL” 这个命名是刻意为之的能力锚定为什么不是 “CONFIG.md”、“AGENT.md” 或 “TASK.md”因为“SKILL”这个词直指核心它定义的是 Agent 的可复用能力单元而非一次性任务或系统配置。一个合格的 SKILL 必须满足三个硬性条件原子性一个 SKILL 只做一件事且这件事有明确输入/输出。例如“生成缺陷报告”是一个 SKILL“生成报告并邮件发送”就是两个 SKILL 的组合。可验证性每个 SKILL 必须附带至少一个# 示例对话区块且该示例必须能在本地复现比如用curl或 Postman 模拟用户提问Agent 返回预期结果。可禁用性当某项能力不稳定时只需注释掉对应# 技能名称下的整个区块无需改代码、不重启服务。我在某高校实验室带学生做模拟项目X时就用这个标准筛掉过60%的初版 SKILL.md有人把“分析性能瓶颈”写成一个 SKILL但实际包含“查CPU占用”、“看GC日志”、“比对JVM参数”三个子动作且没有明确定义哪个环节失败时如何降级。最后我们把它拆成# 查看服务器CPU占用、# 解析JVM GC日志两个独立 SKILL并在后者中加入 注意若日志路径不存在自动切换至默认路径 /var/log/jvm_gc.log的兜底说明。这种拆分不是为了炫技而是为了让测试人在排查问题时能精准定位到是哪个能力模块出了问题。2.3 文件名强制为 SKILL.md统一入口杜绝歧义有些团队尝试用test_skill.yaml或agent_capabilities.json结果在协作中出现严重混乱开发说“我按 JSON 格式实现了”测试说“我写的 Markdown 示例没生效”运维说“部署脚本只认 SKILL.md你们谁改了名字”强制命名为 SKILL.md本质是建立一种契约共识所有参与方默认这个文件就是 Agent 的“能力身份证”工具链CI/CD 脚本、本地调试器、权限校验模块都只监听这个文件名新人入职时第一份文档就是docs/SKILL.md而不是在十几个配置文件里大海捞针。实测下来采用统一命名后某公司测试团队的 Agent 接入平均耗时从3.2天缩短到0.7天。这不是因为技术变简单了而是因为“知道该看哪里”这件事本身就省掉了大量沟通成本。3. SKILL.md 的核心字段解析每一行都在回答“它能干什么、怎么干、不能干什么”3.1# 技能名称不是标题是能力ID的自然语言映射很多新手会写# 接口测试或# 缺陷管理这种宽泛名称结果导致 Agent 无法精准匹配。正确的写法必须满足名词动词限定条件三要素。例如❌# 接口测试太宽泛没说明动作和对象✅# 查询指定环境的用户信息接口状态名词用户信息接口动词查询限定指定环境✅# 生成最近3次冒烟测试的缺陷分布热力图名词冒烟测试缺陷动词生成限定最近3次热力图为什么这么较真因为 Agent 的意图识别模块本质上是把用户输入切词后与所有# 技能名称做相似度匹配。当名称越具体匹配准确率越高。我们在模拟项目X中做过对比实验使用限定词的 SKILL 名称意图识别准确率从78%提升到94%误触发率从12%降到2%以下。注意名称中禁止出现模糊词汇如“相关”、“某些”、“大概”。必须用可枚举的实体。例如# 查询生产环境订单接口的5xx错误率中“生产环境”、“订单接口”、“5xx错误率”都是可确认的实体而# 查询相关接口的错误情况则完全无法解析。3.2- 触发条件定义“什么时候该它上场”不是“它想干什么”这是最容易被写反的部分。新手常写成- Agent 需要检查接口响应时间这其实是 Agent 的内部逻辑不是触发条件。触发条件必须是用户可能说出的话且需覆盖口语化表达。正确写法示例- 用户提到‘响应慢’、‘卡顿’、‘半天没反应’等近义词- 用户输入包含‘/api/v1/order’且问题类型为‘超时’- 用户消息中同时出现‘压测’和‘TPS’两个关键词关键技巧每条触发条件后必须紧跟→符号指向该条件对应的执行动作。例如- 用户说‘看看昨天失败的用例’ → 执行 SQLSELECT * FROM test_case WHERE exec_time 2024-04-01 AND status fail这样写的好处是开发在实现时能直接照搬测试在验证时能逐条核对连产品都能看懂“用户说这句话系统到底会干什么”。3.3bash 执行命令不是伪代码是必须能粘贴运行的真命令这里踩过最大的坑是有人写# 调用登录接口然后在代码块里写curl -X POST ...但没写清楚...里到底是什么。结果测试同学复制粘贴后报错以为是 Agent 问题其实是命令本身缺参数。合格的执行命令区块必须包含完整可执行路径curl -X GET http://test-api.internal:8080/health而不是http://test-api/health显式参数值-H Authorization: Bearer ${TOKEN}中的${TOKEN}必须注明来源如“从环境变量 TOKEN 获取”预期返回格式说明在代码块下方加一行注释# 预期返回 JSON含 status 字段且值为 UP失败处理指令# 若返回码非200记录错误日志并返回‘服务不可用’。我在某跨平台系统项目中就因漏写失败处理指令导致 Agent 在测试环境 DNS 解析失败时一直重试30次才超时拖垮了整个 CI 流水线。后来我们强制要求每个 bash 区块下方必须有# 成功判定和# 失败处置两行注释。3.4# 输入约束与# 输出约束画清能力的安全边界这是 SKILL.md 最容易被忽略、却最关键的模块。没有它Agent 就像没装刹车的车。输入约束要回答三个问题数据来源是否可信如“仅接受来自 test-data-bucket/sanity/ 目录下的 CSV 文件”参数范围是否有限制如“时间范围不得超过7天否则返回‘请缩小查询窗口’”敏感操作是否需二次确认如“执行数据库清理前必须收到用户明确回复‘确认执行’”输出约束则聚焦结果交付格式是否强制如“必须输出 Markdown 表格列名为用例ID | 状态 | 响应时间 | 错误信息”敏感信息是否脱敏如“手机号显示为 138****1234身份证号全部替换为 *”长度是否受限如“摘要内容不超过200字超长部分用‘……’截断”某公司曾发生过事故Agent 根据 SKILL.md 自动生成缺陷报告但未设置输出长度约束某次日志爆炸导致生成12MB文本直接撑爆邮件服务器。后来我们加入硬性规定所有输出约束必须量化禁止出现“尽量”、“一般”、“通常”等模糊表述。3.5# 示例对话不是摆设是验证 Agent 是否“听懂人话”的黄金标尺这部分必须用真实对话格式且至少包含3个维度标准问法用户按文档提示说口语变体用户随口一说Agent 仍能识别边界试探用户故意说错Agent 应优雅拒绝示例# 示例对话 用户查下预发环境的登录接口健康状态 Agent正在检查 http://pre-api.internal/health... 状态UP 用户登录接口还活着吗 Agent正在检查 http://pre-api.internal/health... 状态UP 用户看看生产环境的订单接口 Agent抱歉当前技能仅支持预发环境请切换环境后重试关键细节每段对话必须标注用户和Agent不可省略Agent 的回复必须与# 输出约束完全一致包括标点、换行、敏感词处理边界案例必须真实存在不能编造如某次测试中用户说“登录接口挂了没”Agent 回复“已检查状态正常”这就违反了“挂了没”属于负面假设应先确认再回复。我们团队内部有个铁律任何 SKILL.md 上线前必须由三位不同背景的测试同学资深/中级/新人各自提3个变体问题全部通过才算合格。4. 实操全流程从零开始写一份可落地的 SKILL.md以“生成每日测试报告”为例4.1 第一步锁定最小可行技能MVP Skill别一上来就想做“全自动测试管家”。先问自己今天最想让 Agent 替我做的、重复性最高、且结果明确的一件事是什么在模拟项目X中我们选中了“生成每日测试报告”。它的价值点很清晰每天固定时间执行无脑重复数据源固定MySQL test_report 表 Jira API输出格式固定Markdown 报告失败影响可控顶多报告没生成不影响测试执行。于是我们定义 MVP Skill 名称# 生成指定日期的冒烟测试执行摘要报告注意“指定日期”这个限定——它把“今天”、“昨天”、“2024-04-01”等所有时间表达都收束到一个可解析的参数槽位避免后续写一堆时间转换逻辑。4.2 第二步穷举触发条件覆盖真实对话场景我们收集了测试组过去一周的真实聊天记录提炼出7种用户表达方式“出个今天的冒烟报告”“昨天的冒烟结果汇总下”“我要4月1号的测试摘要”“看看冒烟过了没”隐含“今天”“冒烟报告要带缺陷链接的”隐含“摘要”“生成冒烟测试日报”术语变体“summary for smoke test”中英文混用转化为 SKILL.md 的触发条件- 用户消息含‘冒烟’且含‘报告’、‘汇总’、‘日报’、‘summary’任一词 - 用户消息含‘过了没’、‘结果’、‘怎么样’且上下文明确指向冒烟测试 - 用户消息中包含 ISO 日期格式如 2024-04-01或相对日期如‘今天’、‘昨天’ → 提取日期参数执行报告生成流程这里的关键是把“用户语言”和“机器可解析规则”做了映射。比如“过了没”本身不是时间词但结合“冒烟”这个领域词就能触发时间槽位默认为“今天”。4.3 第三步编写可验证的执行命令链这不是单条命令而是一个微型工作流。我们拆成三步从数据库查当日冒烟结果从 Jira API 拉取关联缺陷合并生成 Markdown 报告。对应 SKILL.md 的代码块# 步骤1查数据库 mysql -h test-db.internal -u reader -p${DB_PASS} test_db -e SELECT case_id, status, response_time FROM test_result WHERE date 2024-04-01 AND type smoke; /tmp/smoke_raw.csv # 步骤2拉Jira缺陷需提前配置JIRA_TOKEN curl -H Authorization: Bearer ${JIRA_TOKEN} https://jira.internal/rest/api/3/search?jqlprojectTEST%20AND%20text~2024-04-01%20AND%20statusOpen /tmp/jira_issues.json # 步骤3生成报告调用本地Python脚本已预装 python3 /opt/agent/report_gen.py --date 2024-04-01 --input-csv /tmp/smoke_raw.csv --input-json /tmp/jira_issues.json --output-md /tmp/daily_report.md注意所有路径、参数、环境变量都必须真实存在且可访问。我们要求新成员第一次写 SKILL.md 时必须在本地终端逐行执行这些命令确保每一步都成功再写入文件。4.4 第四步定义硬性约束守住底线输入约束# 输入约束日期参数必须为有效日期格式为 YYYY-MM-DD若用户未提供日期默认为date -d yesterday %Y-%m-%d单次请求最多生成1份报告禁止批量。输出约束# 输出约束报告必须以 Markdown 表格呈现表头固定为| 用例ID | 状态 | 响应时间(ms) | 缺陷链接 |缺陷链接必须是可点击的[ISSUE-123](https://jira.internal/browse/ISSUE-123)格式若无缺陷对应单元格填—不可留空。这些约束不是拍脑袋定的。比如“最多生成1份报告”是因为某次误操作触发了循环调用Agent 自己给自己发了100份报告塞爆了测试邮箱。后来我们把它写进约束成为硬性规则。4.5 第五步编写三维度示例对话完成闭环验证我们按标准问法、口语变体、边界试探各写一个# 示例对话 用户出个今天的冒烟报告 Agent正在生成2024-04-01冒烟测试报告... 已完成。报告摘要 | 用例ID | 状态 | 响应时间(ms) | 缺陷链接 | |--------|------|--------------|----------| | SMK-001 | PASS | 124 | [ISSUE-456](https://jira.internal/browse/ISSUE-456) | | SMK-002 | FAIL | — | — | 用户冒烟过了没 Agent正在检查2024-04-01冒烟测试结果... 共执行12个用例11个PASS1个FAIL。详情见报告。 用户生成2024-13-01的报告 Agent日期格式错误2024-13-01 不是有效日期请使用 YYYY-MM-DD 格式。写完后我们用一个简易脚本模拟用户输入将输出与示例严格比对。只有字符级完全一致才算通过。4.6 第六步本地调试与灰度发布让 SKILL.md 真正“活”起来写完不等于能用。我们强制执行两步本地调试用agent-cli --skill ./SKILL.md --test命令在本地启动一个轻量 Agent 实例输入示例对话观察输出是否符合预期灰度发布先在测试组小群5人启用监控3天。重点看触发率多少次用户提问真正激活了这个 SKILL准确率激活后Agent 执行是否符合预期逃逸率用户提问未被识别转人工处理的比例。某次灰度中我们发现“冒烟过了没”的触发率只有65%排查发现是 NLU 模块对“过了没”这个短语的权重设置偏低。于是我们在触发条件里单独加了一条- 用户消息以‘过了没’结尾 → 默认日期为今天执行报告生成第二天触发率升至98%。这种基于真实数据的微调才是 SKILL.md 持续进化的核心。5. 常见问题与避坑指南那些没人告诉你的“血泪教训”5.1 问题1Agent 总是“听不懂”但示例对话明明能过现象本地测试一切正常一上线就大量误触发或不触发。根因分析90% 是环境差异导致的。我们统计过模拟项目X的23个故障案例主要分三类时间时区不一致本地调试用东八区测试环境服务器用 UTC导致date -d yesterday解析出错环境变量缺失SKILL.md 里写了${JIRA_TOKEN}但测试环境没配这个变量Agent 静默失败路径权限问题/tmp/目录在容器里是只读的 /tmp/smoke_raw.csv直接报错但 Agent 没捕获异常返回空结果。解决方案所有时间操作强制指定时区date -d yesterday -u %Y-%m-%dUTC或TZAsia/Shanghai date -d yesterday %Y-%m-%d东八区所有环境变量在 SKILL.md 顶部加# 依赖环境变量区块明确列出${JIRA_TOKEN}、${DB_PASS}等并附配置指引链接所有文件操作加前置校验# 校验/tmp可写 if ! touch /tmp/test_write echo ERROR: /tmp is not writable; exit 1; fi实操心得每次上线新 SKILL.md我都会在测试环境手动执行一遍所有# 执行命令不是看结果而是看有没有权限、路径、变量报错。这5分钟能省去后面2小时排查。5.2 问题2Agent 执行成功了但结果“不对劲”现象命令执行返回 0但生成的报告里数据是错的比如日期显示为“1970-01-01”。根因分析这是典型的“命令成功 ≠ 业务成功”。比如 MySQL 查询返回空结果集shell 仍认为成功Jira API 返回 200 但issues数组为空脚本没做判空处理。解决方案在每条执行命令后强制加业务校验# 查数据库后校验 mysql -h test-db.internal ... -e SELECT COUNT(*) FROM test_result WHERE date 2024-04-01 | grep -q 0$ echo ERROR: 无当日测试数据 exit 1 # 调API后校验 curl ... | jq .total | grep -q 0 echo ERROR: Jira未查到缺陷 exit 1我们团队约定任何 SKILL.md 的# 执行命令区块最后一行必须是业务校验且失败时exit 1。这是保证结果可信的底线。5.3 问题3多人协作时SKILL.md 被反复覆盖版本混乱现象A 同学改了触发条件B 同学改了输出格式C 同学删了示例对话最终文件变成“四不像”。根因分析把 SKILL.md 当普通文档管理没建立协作规范。解决方案推行“区块锁”机制每个# 技能名称及其子区块触发条件、执行命令等视为一个独立单元修改前必须在该区块顶部加!-- LOCKED by username on 2024-04-01 --合并 PR 时CI 脚本自动检查同一技能区块是否被多人标记 LOCKED若是则阻断合并每周由专人通常是测试组长发起SKILL.md健康度扫描用脚本检查是否所有# 技能名称都有对应# 示例对话是否所有# 执行命令都有# 成功判定注释是否存在未标记 LOCKED 的修改痕迹即“幽灵修改”。这套机制上线后某公司测试团队的 SKILL.md 误改率从35%降至2%。5.4 问题4新同学总想“一步到位”写超复杂 SKILL 导致失败率飙升现象新人写的# 全链路质量风险预测SKILL包含数据采集、模型推理、报告生成、邮件推送4个环节上线后失败率80%。根因分析违背了 SKILL 的原子性原则。一个环节失败整个链路崩盘且无法定位是哪一环。解决方案强制执行“三步拆解法”先写最核心的原子 SKILL如# 查询近7天接口错误率趋势验证通过后再写依赖它的组合 SKILL如# 生成接口稳定性周报调用上一个 SKILL最后写调度型 SKILL如# 每周一上午9点自动生成周报只负责触发不参与计算。我们有个硬性规定任何新 SKILL.md 提交PR 描述里必须写明“这是第几步”并附上前序 SKILL 的链接。这倒逼大家从最小闭环做起。5.5 问题5SKILL.md 越写越多维护成本爆炸现象半年后 SKILL.md 超过2000行新人看不懂老员工不敢改。根因分析缺乏分层治理。所有技能平铺在一个文件里没有分类、没有优先级、没有归档机制。解决方案建立三层目录结构SKILL.md主入口只保留高频、稳定、核心的5个 SKILL如# 查询接口状态、# 生成日报skills/core/存放经过3个月灰度验证、失败率1% 的核心技能如core_health_check.mdskills/experimental/存放新技能原型文件名带日期如experimental_perf_analyze_20240401.md30天无更新自动归档。同时主 SKILL.md 顶部加动态索引# 技能索引自动生成勿手动修改 - [接口健康检查](skills/core/core_health_check.md) - [冒烟测试日报](skills/core/core_smoke_report.md) - [缺陷趋势分析](skills/experimental/experimental_defect_trend_20240401.md)用 CI 脚本每天凌晨自动扫描skills/目录生成此索引。这样既保持主文件精简又不丢失能力。6. 进阶思考SKILL.md 如何从“能用”走向“好用”6.1 加入“技能健康度”元数据让能力自我进化我们在每个# 技能名称下新增一个# 健康度区块# 健康度 - 触发成功率98.2%7天滚动 - 平均响应时间1.2s - 最近失败时间2024-03-28 14:22原因Jira API 限流 - 维护者test-lead这些数据由 Agent 引擎自动采集上报每天更新。好处很明显新人一眼看出哪个技能最稳优先使用维护者能及时发现衰减趋势如成功率从99%掉到95%说明该优化了管理者可基于健康度分配资源低健康度技能优先安排重构。某次我们发现# 生成性能报告的健康度连续3天下跌排查发现是压测数据表新增了分区原 SQL 未适配。加了PARTITION关键字后成功率立刻回升。6.2 用“技能谱系图”替代线性列表看清能力关系网传统 SKILL.md 是扁平列表但实际技能间有强依赖。比如# 生成缺陷分布热力图依赖# 查询缺陷数据# 预测回归测试范围依赖# 分析代码变更和# 获取历史失败用例。我们用 Mermaid 语法注此处仅为说明实际不渲染图表用文字描述构建谱系# 技能谱系 - 核心数据获取 ├─ # 查询缺陷数据 ├─ # 查询用例执行记录 └─ # 获取代码变更列表 - 分析类技能 ├─ # 生成缺陷分布热力图依赖查询缺陷数据 └─ # 预测回归测试范围依赖查询用例执行记录 获取代码变更列表这样当# 查询缺陷数据更新时所有依赖它的技能都会收到通知自动进入待验证队列。6.3 将 SKILL.md 变成“可执行文档”一键生成测试用例这是最实用的进阶技巧。我们写了个 Python 脚本skill2test.py输入 SKILL.md自动输出Postman Collection用于接口测试Robot Framework Test Case用于自动化验收用户操作手册 PDF给非技术人员看。例如# 查询接口状态的触发条件和执行命令会被转成*** Test Cases *** Verify API Health Status [Documentation] 验证预发环境接口健康状态 ${response} Run Process curl -X GET http://pre-api.internal/health shellTrue Should Contain ${response.stdout} status: UP这意味着每一份 SKILL.md天然就是一份可运行的验收标准。测试同学不再需要“看文档写用例”而是“运行脚本生成用例”。6.4 个人体会SKILL.md 的终极价值是让测试人重新掌握“定义问题”的权力我带过的所有模拟项目X最终都发现一个规律当 SKILL.md 写得越细致测试同学在需求评审会上发言就越有底气。因为他们不再只是被动接收“请测试这个功能”而是能主动说“这个功能涉及3个新 SKILL我需要提前确认数据源权限、接口返回格式、失败兜底策略——这些写在 SKILL.md 的第5、第7、第12条。”SKILL.md 的本质是把测试人的领域知识从大脑里、聊天记录里、Excel 表格里结构化地沉淀为可执行、可验证、可传承的数字资产。它不取代测试人的思考而是把思考过程显性化、标准化、自动化。当你能用一份 Markdown 文件让一个 AI Agent 精准复现你过去三个月的手工操作时你就已经站在了测试效能革命的起点上。最后分享一个小技巧每周五下午花15分钟打开你的 SKILL.md随机选一个技能用手机语音输入它的触发条件比如“查下预发环境的登录接口健康状态”看 Agent 是否能正确响应。如果不行立刻记入下周优化清单。这个习惯坚持半年你会发现自己写的每一条触发条件都越来越接近真实用户的说话方式——而这正是人机协同最自然的状态。