news 2026/10/20 2:17:39

Agent Skills 系列 04:SKILL.md 指令写法,从能用变成好用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills 系列 04:SKILL.md 指令写法,从能用变成好用

1. 为什么你的 SKILL.md 能跑通却总是不稳定

很多人第一次把 Agent Skills 跑起来的时候,心情是激动的:模型能读文件、能按步骤执行、能吐出结果。但用上两三天,问题就来了——同一个任务,今天输出一张规整的表格,明天变成三段散文;今天老老实实只读不改,明天顺手把源文件覆盖了;你用中文写的 Skill,它偏偏回你一整段英文。

这不是模型抽风,而是 SKILL.md 的指令写法没到位。Agent Skills 的正文本质上是一份给模型看的“工作说明书”,它不像代码那样有编译器帮你兜底,模型对指令的理解是概率性的。你写得越模糊、越依赖模型“猜”,输出的方差就越大。

我试过把同一个接口文档审查任务写成两个版本的 SKILL.md:第一版是典型的“能用”写法,通篇“你应该”“建议”“尽量”,输出格式只写了一句“给出审查结论”;第二版按祈使句、解释 why、固定格式、声明边界重写。用同一批 20 个接口文档跑对比,第一版的格式合规率大概六成出头,第二版稳定在九成以上,而且第二版在遇到格式错乱的文档时会主动提示“未识别到接口定义”,而不是硬编一份看起来像模像样的报告。

这篇文章面向已经能跑通 Agent Skills 的开发者,聚焦 SKILL.md 里指令写法的优化路径。核心就四件事:把建议句改成祈使句、用解释意图代替堆砌 MUST、用具体示例对齐预期、把输出格式和边界条件写死。每一节都给可复制的模板和改写对照,最后给一个完整的 SKILL.md 和一套验证动作,你可以直接拿去对比改写前后的输出稳定性。

先明确一个判断标准:什么叫“好用”?我的定义是三条——同一任务多次执行,结构一致;遇到异常输入,行为可预期;跨人使用,输出能被下游程序直接消费。只要有一条不满足,就说明指令写法还有优化空间。

2. 祈使句与解释 why:指令语气的两个关键改写

2.1 把建议句全部换成祈使句

官方规范里明确要求指令使用祈使句(imperative form),原因很直接:直接命令比委婉建议更清晰。这是最容易改、收益最直接的一条。

看一组对照。模糊写法用的是建议语气,模型会把它当成可选步骤:

<!-- 模糊:建议语气,模型可能选择性执行 --> 你应该先读取输入文件。 然后你可能会想解析里面的数据。 之后做一下校验会比较好。

清晰写法全部使用祈使句,每一步都是明确动作:

<!-- 清晰:全部使用祈使句 --> 读取输入文件。 解析文件中的数据。 校验解析结果。 若校验失败,输出错误行号与原因。

差别不只是语气。建议句会让模型认为这是可选步骤,在复杂任务里最容易被省略的就是这些“可以”“建议”开头的句子;祈使句则明确了步骤的存在。一个自查方法:把 SKILL.md 里所有指令句扫一遍,凡是出现“可以”“建议”“尽量”“最好”的地方,都在削弱指令强度。该强制的强制,该可选的显式标注为可选。

2.2 解释 why,而不是堆 MUST

这是最反直觉的一条。很多人以为 MUST、NEVER、ALWAYS 堆得越多,输出越稳。实际相反:只下命令不解释原因,模型遇到边界情况时会机械套模板,反而僵化。

官方给出的正反例对比很典型。反例只下命令:

<!-- 反例:只下命令,不解释原因 --> # 报告结构 必须使用以下模板,不得偏离: # [标题] ## 执行摘要 ## 关键发现 ## 建议

正例说明为什么这样组织:

<!-- 正例:说明为什么这样组织 --> # 报告结构 按以下结构组织报告,便于读者快速定位结论: - 标题:概括结论本身,而不是描述主题 - 执行摘要:让只读这一段的人也能拿到完整判断 - 关键发现:按重要性排序,每条附证据 - 建议:可执行的动作,避免空泛表述

正例里没有任何 MUST,但每条都给了理由。模型理解了意图后,遇到边界情况能自行判断,而不是机械套模板。官方在 skill-creator 里把这点总结得更直接:尽量避免大量僵硬的 MUST,改用讲道理的方式,并让 Skill 保持通用而非过度贴合某个例子。

实践建议:只在两种情况下使用强制语气——涉及安全或不可逆操作(如“禁止直接修改生产数据”),以及规范的硬性约束(如“name 必须是小写加连字符”)。其余场景优先解释原因。

2.3 用具体示例对齐预期

示例比抽象描述更能澄清预期。以提交信息生成为例:

## 提交信息格式 遵循 conventional commits 规范。 示例 1: 输入:添加了基于 JWT 的用户认证 输出:feat(auth): 实现基于 JWT 的身份认证 示例 2: 输入:修复了日期差一天的问题 输出:fix(calendar): 修正时区偏移计算 示例 3: 输入:更新了 README 的安装步骤 输出:docs(readme): 补充安装说明

三个示例覆盖三种类型(新功能、修复、文档),模型能归纳出“类型前缀 + 范围 + 描述”的模式,比一句“遵循规范”有效得多。示例数量控制在 2 到 3 个,优先选边界情况而不是典型情况——典型情况模型本来就能处理对,边界情况才是需要对齐的地方。冗余示例既占上下文,又可能让模型把示例细节当成必须遵守的规则。

3. 可复制的 SKILL.md 配置模板与输出格式约束

这一节给可直接落地的配置片段。Agent Skills 的 SKILL.md 采用 YAML frontmatter + Markdown 正文的结构,frontmatter 里的 name 和 description 决定触发,正文决定执行质量。

3.1 frontmatter 与触发词配置

--- name: api-doc-reviewer description: 审查接口文档的完整性,检查参数说明、错误码、示例与边界条件是否齐全。在审查 API 文档、接口定义、OpenAPI 文件时使用。触发词:接口文档审查、API 文档检查、接口定义评审、api doc review。 ---

name 用小写加连字符,description 里同时列中英触发词,这样中英文提问都能命中。description 要写清楚“做什么”和“什么时候用”,模型靠它判断是否加载这个 Skill。

3.2 固定输出格式:表格与模板两种粒度

输出格式不定义,每次产出结构就会不同,下游使用会很痛苦。格式定义有两种粒度,按需选择。

表格形式,适合字段固定的清单类输出:

## 输出格式 | 字段 | 说明 | | --- | --- | | 严重级别 | P0 / P1 / P2 | | 服务 | 报错的服务名 | | 错误模式 | 归一化后的错误消息 | | 出现次数 | 聚合计数 | | 建议动作 | 具体的下一步 |

模板形式,适合有固定结构的文档类输出:

## 输出格式 按以下模板输出,无内容的章节保留标题并标注「无」: # <问题标题> ## 现象 <观察到的具体表现,附日志或数据> ## 原因 <根本原因分析> ## 方案 <具体动作,可执行> ## 验证 <如何确认问题已解决> ## 边界 <不适用的场景>

模板里的“无内容的章节保留标题并标注无”是个实用细节:明确空值如何处理,避免模型自行删减结构。官方在最佳实践里也提到“清晰定义结构”,并建议为输出提供明确约定——这在团队协作场景里尤其重要,因为同一份 Skill 会被多人使用,输出结构不一致会导致下游处理困难。

3.3 约束与边界:定义不许做什么

约束部分是很多 Skill 缺失的一环。它回答三类问题:不许做什么、不确定时怎么办、异常输入如何处理。

## 约束 - 只读取和分析,不修改任何源文件。 - 涉及删除、覆盖、发布等不可逆操作时,先输出将要执行的动作并等待确认。 - 无法从输入中判断结论时,标记为「需要更多信息」,不臆测。 - 输出使用中文,代码标识符、路径、错误码保持原样。 - 若解析失败行数大于 0,先提示输入格式可能不匹配,不直接下结论。

五条约束分别对应五种风险:误改文件、不可逆操作、编造结论、语言漂移、静默失败。后两条最容易被忽略,也最容易在生产中出问题。官方在安全章节提出“缺乏意外原则”(Principle of Lack of Surprise):Skill 的行为应当符合使用者预期,涉及风险操作时要明确提示适用范围。一个判断约束是否写到位的方法:设想输入是一份格式完全不符合预期的文件,你的 Skill 会怎么反应?如果答案不确定,说明约束缺了异常处理。

3.4 语言控制:中文 Skill 最容易踩的坑

用中文写的 Skill,输出却是英文,这是中文场景下的高频问题。原因不难理解:Skill 正文里往往混有英文术语、英文代码注释、英文示例产物,模型生成时会被这些内容带偏。语言如果没有显式约束,模型会依据上下文中占多数的语言来决定输出语言。

解决办法是在约束里显式声明输出语言,并划清例外范围:

## 约束 - 所有输出使用中文,包括标题、问题描述、建议与总结。 - 以下内容保持原文,不翻译:代码、命令、文件路径、错误码、标识符、第三方库名称、错误消息原文。 - 引用日志或报错时,先原样引用,再另起一行用中文说明含义。

三条规则分别解决:主体语言、例外范围、混合场景的处理方式。第三条规定尤其有用——它避免了“中文说明里夹着英文报错”这种两头不靠的输出。如果 Skill 需要同时支持中英文用户,可以在 description 中列中英触发词,在正文中按输入语言自适应:

## 约束 - 输出语言与用户提问语言保持一致。 - 若用户使用中文提问,输出全中文;使用英文提问则输出英文。 - 代码与标识符不翻译。

4. 完整 SKILL.md 示例与验证请求

4.1 一个完整的 SKILL.md

把前面几节的写法应用到一个完整示例上,场景是接口文档审查:

--- name: api-doc-reviewer description: 审查接口文档的完整性,检查参数说明、错误码、示例与边界条件是否齐全。在审查 API 文档、接口定义、OpenAPI 文件时使用。触发词:接口文档审查、API 文档检查、接口定义评审、api doc review。 --- # 接口文档审查 ## 执行步骤 1. 读取目标文档,识别其中的接口定义块。 2. 逐个接口检查以下四项,缺失项记入问题清单: - 参数说明:每个参数是否有类型、是否必填、取值范围 - 错误码:是否列出失败场景及其含义 - 请求与响应示例:是否给出可直接使用的示例 - 边界条件:分页上限、字段长度、并发限制等 3. 读取 `references/review-checklist.md` 获取完整的检查项与判定标准。 4. 按输出格式给出结论。 ## 输出格式 | 接口 | 问题类型 | 所在位置 | 问题描述 | 修改建议 | | --- | --- | --- | --- | --- | 按问题严重程度排序:先列参数与错误码缺失,再列示例与边界条件缺失。 ## 示例 输入:一个只写了 URL 和请求方法、没有参数说明的接口定义 输出: | 接口 | 问题类型 | 所在位置 | 问题描述 | 修改建议 | | --- | --- | --- | --- | --- | | POST /api/order | 参数说明缺失 | 第 12 行 | 未说明任何请求参数的必填性与取值范围 | 补充每个参数的类型、是否必填、取值约束 | ## 约束 - 只审查并输出报告,不修改原文档。 - 文档中的接口定义无法识别时,说明识别失败的位置,不猜测接口含义。 - 输出使用中文,接口路径、参数名、错误码保持原样。 - 若文档未包含任何接口定义,直接说明未找到接口定义,不输出空表格。

这份 SKILL.md 体现了全部要点:执行步骤全部为祈使句;输出格式中说明排序理由;给出一个完整的输入输出对照;表格结构固定到列;四条约束覆盖不可逆操作、识别失败、语言、空输入;显式指定中文输出与原样保留范围。

4.2 验证请求:对比改写前后的稳定性

改写完不能凭感觉说“好像稳了”,要有可量化的验证动作。我的做法是准备一组固定测试集,用同一任务跑改写前后两个版本,统计两个指标:输出稳定性(多次执行结构是否一致)和格式合规率(输出是否符合定义的表格列与排序)。

验证用的请求可以这样构造,把同一份文档分别喂给两个版本的 Skill:

请使用 api-doc-reviewer 审查以下接口文档,按输出格式给出问题清单。 文档内容: POST /api/order GET /api/order/{id}

跑 5 次,记录每次输出的列数、排序、是否出现空表格。改写前的版本常见问题是列顺序漂移、把“无问题”写成一段话而不是空表格;改写后的版本列顺序固定,遇到无接口定义时直接输出“未找到接口定义”。

如果你想把验证过程做成可复现的脚本,可以把 Skill 目录挂到工作区,用命令行触发:

# 列出当前可用的 skills,确认 api-doc-reviewer 已被识别 ls .agent/skills/ # 查看 Skill 的 frontmatter 是否被正确解析 head -n 5 .agent/skills/api-doc-reviewer/SKILL.md

确认加载正常后,用同一份测试文档连续触发 5 次,把输出贴进表格对比。格式合规率低于 90% 就回去检查输出格式和约束两节,通常是空值处理和排序规则没写清楚。

5. 常见报错与排查对照

改写 SKILL.md 的过程中,报错大多不是代码错误,而是行为不符合预期。下面按真实遇到的报错和现象整理排查路径。

5.1 输出格式漂移:列顺序每次不同

现象:同一任务多次执行,表格列顺序、字段名不一致。原因:输出格式只写了“给出表格”,没固定列。排查:检查输出格式一节是否用 Markdown 表格把列名写死,是否说明了排序规则。修复:把列名和排序规则写进输出格式,并补一条“无内容的章节保留标题并标注无”。

5.2 静默失败:输入格式不符却输出“未发现问题”

现象:喂一份格式错乱的文档,Skill 输出“未发现问题”。原因:约束只写了正常路径,没有异常输入处理。排查:检查约束里是否有“解析失败行数大于 0 时先提示格式问题”。修复:补上异常处理约束,明确“不直接下结论”。

5.3 语言漂移:中文 Skill 输出英文

现象:正文全中文,输出结果夹杂英文甚至整段英文。原因:正文中的英文术语、代码与示例产物带偏了输出语言。排查:检查约束里是否显式声明输出语言,是否划清不翻译范围。修复:按 3.4 节的三条规则补全语言约束。

5.4 步骤被跳过:复杂任务只执行了前两步

现象:多步任务里后面的校验、输出步骤被省略。原因:步骤用了建议句,“可以”“建议”削弱了指令强度。排查:扫描正文里的“可以”“建议”“尽量”“最好”。修复:必须执行的改祈使句,可选的显式标注为可选。

5.5 示例僵化:换个场景输出就套用示例细节

现象:模型把示例里的具体项目数据当成必须遵守的规则。原因:示例过多且雷同,或示例贴合了单个案例。排查:数一下示例数量,是否超过 3 个且类型重复。修复:保留 2 到 3 个覆盖不同情况的示例,细节用占位符表示。

5.6 约束与步骤重复

现象:同一要求在两处出现,后续修改时容易遗漏一处。原因:把约束当成步骤的补充说明。排查:对比执行步骤和约束两节,是否有重复条目。修复:步骤只写做什么,约束只写边界与禁止项,职责分离。

排查时如果涉及模型调用层的报错,比如 401、local proxy failed、reading choices 这类,先确认接入配置是否正确。Base URL、API Key、Model ID 三件套要写全,缺一个都会在请求阶段失败。配置入口在控制台的 API Keys 页面,接入文档里有各语言的完整示例。模型对话页面可以先用最小请求验证连通性,确认模型能正常返回再回到 Skill 调试。

6. 把指令写法沉淀成可复用的检查清单

写到这里,SKILL.md 从“能用”到“好用”的路径已经比较清楚了。最后给一份可以直接贴在团队文档里的检查清单,每次新增或修改 Skill 时过一遍:

指令语气:所有必须执行的步骤用祈使句,扫描并清除“可以”“建议”“尽量”“最好”。

解释意图:只在安全与硬性规范处使用 MUST,其余规则说明“为什么这样组织”。

示例控制:保留 2 到 3 个覆盖不同情况的示例,优先选边界情况,细节用占位符。

输出格式:用表格或模板固定结构,说明空值如何处理,说明排序规则。

约束边界:覆盖不可逆操作、编造结论、语言漂移、静默失败四类风险。

语言控制:显式声明输出语言,划清代码与标识符不翻译的范围。

职责分离:步骤只写做什么,约束只写边界与禁止项,不重复。

验证动作:用同一任务跑改写前后各 5 次,统计格式合规率,低于 90% 回到输出格式和约束两节排查。

一个值得探讨的度:解释“为什么”能提升模型的泛化能力,但解释本身会占用上下文,且在规则很简单时反而显得啰嗦。我的经验是,涉及判断分支的规则值得展开解释,纯机械的格式要求直接下命令就够了。你可以拿手头一个已经跑通的 Skill,按这份清单改一遍,再用同一批任务对比改写前后的输出稳定性——差距通常比想象中大。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 2:15:18

把项目打包成Docker镜像,一条命令部署上线(附镜像瘦身记录)

学Docker这事我拖了大半年。 每次看教程都是"打开你的虚拟机"&#xff0c;然后我就卡在虚拟机那步——装系统半小时&#xff0c;网络配半天&#xff0c;内存一开2G没了&#xff0c;电脑风扇嗷嗷转。学个Docker跟渡劫似的&#xff0c;热情耗没了。 后来买了台云服务…

作者头像 李华
网站建设 2026/10/20 2:14:29

湖南焊接培训:从长沙辐射怀化的技能基地

引言焊接技能人才的培养&#xff0c;历来与地区产业升级和用工需求紧密相连。长沙市汇德职业培训学校旗下品牌焊将军学园&#xff0c;成立于2022年&#xff0c;总部位于长沙市雨花区高升路465号才子嘉都三期东门裙楼二楼&#xff0c;业务覆盖湖南省范围&#xff0c;怀化地区学员…

作者头像 李华
网站建设 2026/10/20 2:14:27

合同纠纷怎么破?北京商业租赁律所五强之外的十强全榜单

企业租办公室&#xff0c;租的是场地&#xff0c;更是未来几年的稳定经营预期。但现实中&#xff0c;写字楼租赁的纠纷一点也不少&#xff1a;租金递增条款有歧义、装修投入被房东终止合同、免租期后突然加价、转租被限制、退租时要求恢复原状&#xff0c;每一个都能让企业主头…

作者头像 李华
网站建设 2026/10/20 2:14:25

ORB-SLAM3 bool Tracking::TrackLocalMap()

该函数在恒速模型跟踪或参考关键帧跟踪成功之后调用,利用局部地图进一步优化当前帧位姿,并统计内点数量,最终判断跟踪是否成功。 bool Tracking::TrackLocalMap() {// We have an estimation of the camera pose and some map points tracked in the frame.// We retrieve …

作者头像 李华