ᕕ( ᐛ )ᕗ Jimyag's Blog

如何编写高质量的 Agent Skill

· 1439 words · ~ 7 min read

SKILL.md 的格式不复杂:一个目录、一个入口文件,再加一些可选的脚本和参考资料。难点在内容设计。高质量 Skill 要把重复任务整理成清晰、可触发、可执行、可验证的操作手册,而不是把一大段 prompt 直接搬进文件。

先用一句话判断是否值得写成 Skill:

如果一个任务会反复出现,并且你希望 Agent 每次都按同一套方法完成,就适合写成 Skill。

一次性问题不用写 Skill。项目长期背景也不适合放进 Skill,放 AGENTS.mdCLAUDE.mdGEMINI.md 这类 instruction 文件更合适。Skill 应该面向具体任务。

Skill 解决什么问题

Skill 解决的是流程稳定性。重点不在模型是否知道某个知识点,而在它每次能不能按同一套正确方法完成任务。

它适合沉淀这些内容:

  • 一组稳定步骤:例如排查 CI、审查 PR、生成周报、分析日志。
  • 一套质量标准:例如代码评审 checklist、安全检查项、文档风格。
  • 一些可复用资源:例如模板、示例、API 规范、团队内部约定。
  • 少量确定性脚本:例如解析日志、生成报告、校验格式。

它不适合承载这些内容:

  • 大而全的项目背景。
  • 随时间频繁变化的事实。
  • 没有明确输入输出的泛泛建议。
  • 可以直接用 MCP、CLI、API 完成的底层连接能力。

可以这样划边界:MCP/工具负责“能访问什么”,Skill 负责“拿到能力后怎么做”。

最小结构

一个通用 Skill 目录通常长这样:

1
2
3
4
5
6
7
8
my-skill/
├── SKILL.md
├── references/
│   └── checklist.md
├── scripts/
│   └── validate.py
└── assets/
    └── template.md

只有 SKILL.md 是必需的。references/scripts/assets/ 用来降低主文件复杂度。

SKILL.md 最小可以写成:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
---
name: pr-review
description: Review code changes for correctness, regressions, tests, and maintainability. Use when the user asks for a PR review, code review, or review of current diff.
---

# PR Review

## Workflow

1. Inspect the current diff and surrounding code.
2. Identify correctness bugs, regressions, missing tests, and maintainability risks.
3. Report findings first, ordered by severity.
4. Include file and line references for every actionable finding.
5. If no issue is found, say so and mention remaining test gaps.

## Output

Use this order:

1. Findings
2. Open questions
3. Test gaps

字段不用多,description 和正文要明确。

写好 description

description 决定 Skill 会不会被自动选中。Agent 通常先看到所有 Skill 的名字和描述,判断相关后才加载完整 SKILL.md。描述要回答两件事:

  • 这个 Skill 做什么。
  • 什么时候应该用,什么时候不该用。

差的写法:

1
description: Help with code.

好的写法:

1
description: Review Go pull requests for correctness, concurrency bugs, error handling, tests, and maintainability. Use when the user asks for Go PR review or review of current Go diff.

前者范围太大,容易误触发。后者包含任务、语言、检查范围和触发词。

如果一个 Skill 有副作用,例如发布、删除、发送消息、改生产配置,要明确限制触发方式。能配置为只允许显式调用时,就不要让它自动触发;不能配置时,也要在正文第一段写清楚必须先确认。

按需加载与副作用控制

Skill 和普通 prompt 的一个重要区别是按需加载。Agent 不应该在每次会话里都背完整工作手册。它应该先看到一个很短的索引,判断相关后再读取完整流程,需要细节时再读 supporting files。

可以把一个 Skill 拆成三层:

1
2
description  ->  SKILL.md  ->  supporting files / scripts
触发索引          执行骨架       领域细节与确定性操作

每一层的职责不同:

  • description:只回答“什么时候该用这个 Skill”。它越像触发条件,自动选择越准确;越像功能说明或流程摘要,越容易误触发或被 Agent 当成捷径。
  • SKILL.md:放任务边界、输入、输出、步骤、停止条件和验证方式。它应该是执行骨架,不应该塞满所有背景资料。
  • supporting files:放大段参考、检查清单、模板、领域规则。只有任务真的需要时才读。
  • scripts:放确定性操作,例如收集证据、解析日志、校验格式、生成文件。不要让模型用自然语言模拟本该由脚本完成的事情。

副作用要单独处理。凡是会影响外部世界的 Skill,都不应该只靠“请小心”这种文字约束。

常见副作用包括:

  • 发布、部署、回滚
  • 创建 PR、push、merge
  • 发送消息、评论、邮件
  • 删除、覆盖、迁移数据
  • 修改生产配置或权限

这类 Skill 的默认策略应该是:

  1. 能禁用自动触发就禁用,只允许用户显式调用。
  2. 执行前展示计划和影响范围。
  3. 真正执行外部动作前再次确认。
  4. 输出中明确写出做了什么、没做什么、如何回滚。

低频 Skill 也不一定值得常驻。一个实用判断:

  • 高频任务:保留自动触发,但把 description 写准。
  • 低频且有风险的任务:保留 Skill,但只手动触发。
  • 极低频任务:不要做成 Skill,放进文档,需要时再读。

这也是 Skill 治理里最容易被忽视的一点:不是所有可复用内容都应该变成 Skill。Skill 越多,触发索引越多;触发索引越吵,Agent 越容易选错。

举个例子,假设要做一个 CI 失败分析 Skill,不要这样写:

1
description: Analyze CI failures by checking GitHub Actions, reading logs, finding root causes, checking code, deciding whether flaky, and giving fixes.

这个描述把 workflow 全写进去了。Agent 可能只看 description 就开始按自己的理解执行,反而不读完整 Skill。

更好的写法是:

1
description: Use when CI, pipeline, build, or test checks fail and the user wants root-cause analysis based on logs and code evidence.

然后把完整流程放进 SKILL.md

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# CI Failure Analysis

## Inputs

- PR number, CI URL, or current branch
- Repository context

## Workflow

1. Collect failed checks.
2. Fetch logs for each failed job.
3. For each failure, find both:
   - log evidence
   - code or config evidence
4. Classify as regression, environment, or flaky.
5. Report confidence and next action.

## Stop Conditions

- If logs require credentials that are unavailable, mark the evidence as incomplete.
- Do not call a failure flaky without historical evidence.

再把检查标准拆到 supporting file:

1
2
3
4
ci-analyze/
├── SKILL.md
└── references/
    └── flaky-checklist.md

references/flaky-checklist.md 可以只在判断 flaky 时读取:

1
2
3
4
5
6
7
# Flaky Checklist

A failure can be called flaky only when:

1. The same test passed in another recent run.
2. The error matches an infrastructure or timing pattern.
3. The related code path was not recently changed.

如果日志格式复杂,再把解析逻辑做成脚本:

1
2
3
4
5
6
ci-analyze/
├── SKILL.md
├── references/
│   └── flaky-checklist.md
└── scripts/
    └── extract-failures.py

这样每层都很清楚:

  • description 负责触发。
  • SKILL.md 负责流程。
  • references/ 负责判断标准。
  • scripts/ 负责确定性解析。

副作用 Skill 也一样。比如创建 PR 是有外部副作用的,description 可以写得窄一点:

1
description: Use when the user explicitly asks to create a pull request for the current branch.

正文里要把执行门槛写清楚:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
## Safety Gate

Before creating the PR:

1. Show the target branch and base branch.
2. Show the PR title and body draft.
3. Confirm the working tree is clean.
4. Ask for confirmation unless the user already explicitly requested creation.

Do not push, create, merge, or comment on a PR unless the user explicitly asked for that action.

这个例子讲的是副作用边界:读 diff、生成草稿可以自动做;push、create、merge 必须有明确授权。

主文件要短,参考资料要分层

高质量 Skill 的主文件应该像入口索引,不应该像百科全书。

建议把 SKILL.md 控制在这几类信息内:

  • 触发后第一步做什么。
  • 输入从哪里来。
  • 输出长什么样。
  • 哪些情况必须停止或询问用户。
  • 需要更详细资料时读哪个文件。

大段内容放到独立文件:

  • checklist 放 references/review-checklist.md
  • 风格指南放 references/style-guide.md
  • 输出模板放 assets/report-template.md
  • 稳定操作放 scripts/

这样才能渐进式加载:Agent 不需要一开始就把所有资料塞进上下文,只在任务需要时读取具体文件。

五种常用设计模式

1. Tool Wrapper:封装工具或框架用法

当团队有一套固定框架约定时,可以写一个 Tool Wrapper Skill。它不用替代官方文档,只需要告诉 Agent:这个项目按哪套约定使用这个工具。

适合场景:

  • FastAPI、Gin、React、Terraform 等框架约定。
  • 内部 SDK 或 CLI 的使用方式。
  • 团队统一的错误处理、日志、测试规范。

结构建议:

1
2
3
4
5
fastapi-style/
├── SKILL.md
└── references/
    ├── conventions.md
    └── examples.md

SKILL.md 只写触发条件和总规则,具体约定放到 references/conventions.md。不要把整份框架文档复制进去,只保留项目真正不同于常识的部分。

2. Generator:稳定生成结构化产物

Generator 解决“每次生成格式都不一样”的问题。它应该提供模板、变量收集方式和验收标准。

适合场景:

  • 生成 PR 描述。
  • 生成技术方案。
  • 生成故障复盘。
  • 生成 API 文档。

结构建议:

1
2
3
4
5
6
incident-report/
├── SKILL.md
├── assets/
│   └── report-template.md
└── references/
    └── writing-style.md

关键点是:先检查输入是否完整,不完整就问;不要凭空补关键事实。

3. Reviewer:把检查标准模块化

Reviewer 适合“按标准检查”的任务。核心是把检查项从流程里拆出来,放到 checklist。

适合场景:

  • 代码审查。
  • 安全审计。
  • 文档质量检查。
  • 数据报表口径检查。

结构建议:

1
2
3
4
go-review/
├── SKILL.md
└── references/
    └── review-checklist.md

SKILL.md 负责规定审查流程和输出格式,review-checklist.md 负责列出具体标准。以后标准变化,只改 checklist,不必重写整个 Skill。

4. Inversion:先采访,再执行

Agent 容易在信息不足时直接开干。Inversion 模式反过来,要求 Agent 先收集上下文,再进入执行。

适合场景:

  • 架构设计。
  • 迁移方案。
  • 新项目规划。
  • 风险较高的自动化操作。

关键写法是加硬门槛:

1
2
3
4
5
6
7
## Gate

Do not produce the final plan until these questions are answered:

1. What is the target environment?
2. What constraints cannot be changed?
3. What rollback path is acceptable?

这种 Skill 不追求快,追求少猜。

5. Pipeline:多阶段任务强制过检查点

Pipeline 适合复杂任务:把任务拆成固定阶段,并要求每阶段完成后做检查。

适合场景:

  • 复杂文档生成。
  • 跨文件重构。
  • CI 修复闭环。
  • 数据分析报告。

结构建议:

1
2
3
4
5
6
7
## Workflow

1. Discover: collect inputs and inspect context.
2. Plan: write a short plan and identify risks.
3. Execute: make the smallest sufficient change.
4. Verify: run the relevant checks.
5. Report: summarize changes, verification, and residual risks.

Pipeline 的重点是不要让 Agent 跳过验证。凡是会产生交付物的 Skill,都应该至少有一个 Verify 阶段。

什么时候用脚本

默认优先写说明,不要一上来就写脚本。下面这些情况才适合脚本:

  • 操作需要确定性,例如解析 JSON、生成目录、检查 frontmatter。
  • 操作会重复执行,手写容易错。
  • 输出需要机器可校验。
  • 执行脚本比让模型推理更省上下文。

不适合写脚本的情况:

  • 逻辑还不稳定。
  • 主要工作是判断、取舍、写作。
  • 脚本需要复杂依赖,安装成本高于收益。

一个实用原则:如果失败会导致真实副作用,脚本必须可读、可测、可回滚。

写 Skill 时最常见的坑

1. 把 Skill 写成超长 prompt

长不是问题,没结构才是问题。Skill 应该让 Agent 快速找到下一步,而不是读完一整篇散文再自己总结。

2. description 太泛

description 太泛会导致误触发,太窄又会导致该用时不用。最好的写法是“任务 + 触发词 + 边界”。

3. 没有输入输出

没有输入输出的 Skill 往往会变成风格建议。每个 Skill 都应该能回答:

  • 输入是什么?
  • 产物是什么?
  • 成功标准是什么?

4. 没有停止条件

高风险任务必须写停止条件。例如:

  • 缺少生产环境信息时停止。
  • 要发送外部消息时先请求确认。
  • 要删除、覆盖、发布时先展示计划。

5. 混入易过期事实

版本号、价格、服务限制、API 行为都可能变化。Skill 里只放稳定原则;易变事实要让 Agent 查官方文档或本地真实配置。

从真实 Skill 里提炼的好设计

下面这些来自我自己维护的 Skill。它们不一定能直接照搬,但设计思路值得保留。

Reviewer 要控制噪音

代码审查类 Skill 最容易变成“什么都说一点”。先固定审查维度,再明确只输出高价值 findings,会稳很多。

例如 Go PR 审查可以拆成:

  • 正确性
  • 并发与安全
  • 健壮性
  • 可维护性
  • 性能
  • 文档与规范

每个维度只记录可能影响行为、稳定性、安全性或长期维护的问题。风格偏好、无证据猜测、无关建议都不要写进最终结果。

这个设计的关键在过滤规则,不在检查项数量。Reviewer Skill 必须告诉 Agent 什么不值得输出,否则它会为了显得认真而制造噪音。

Reviewer Skill 还应该把“角色边界”写清楚。一个审查 Skill 默认应该是只读的:

  • 只审查 diff 和判断问题所需的附近上下文。
  • 不修改文件。
  • 不提交 commit。
  • 不 push、不 merge。
  • 不发布评论,除非这个 Skill 的职责就是提交 review,且用户已经明确授权。

这个边界看起来普通,但很重要。审查和修复是两类任务:审查要控制判断质量,修复要控制改动范围。把两者混在一个 Skill 里,Agent 容易一边发现问题一边顺手改,最后用户反而看不清它到底 review 了什么。

大型 review 也可以拆成几条 review lane:

  • Code quality:清晰度、命名、结构、重复、错误处理、边界条件。
  • Performance:重复工作、复杂度退化、过度分配、I/O 或网络放大、热点路径浪费。
  • Security:注入、鉴权/越权、命令执行、敏感信息泄露、不安全默认值、信任边界。
  • Documentation accuracy:行为变更是否同步到文档,注释、README、示例和配置说明是否还准确。

如果运行环境支持 subagent,可以把这些 lane 分给不同 reviewer,但这不是必须条件。更重要的是,每条 lane 都要遵守同一个输出协议:只返回 noteworthy findings;没有问题就明确说没有;每个问题尽量带文件和行号;证据不足就标成“需补充上下文”。

如果这个 Skill 真的负责把 review 评论发到 GitHub 或 GitLab,还要增加一层通知卫生:

  1. 先收集所有 findings。
  2. (file, line) 合并重复或重叠问题。
  3. 只保留自己也认可的高价值问题。
  4. 一次性批量提交 review,避免每条评论触发一次通知。
  5. 默认使用非阻塞评论,不用阻塞式的 request changes,除非团队流程明确要求。
  6. 在 review body 里放一个稳定 marker,方便后续识别这次自动 review。

这类规则体现的是副作用控制:分析可以细,外部动作要少、准、可追踪。

排障类 Skill 要强制证据链

CI 分析、线上排障、测试失败定位这类 Skill,首先要防止 Agent 猜。

可以加一条硬约束:每个结论至少要同时有两类证据:

  • 日志证据:关键错误行、失败 job、失败测试名。
  • 代码或配置证据:对应文件、脚本、配置项,以及错误如何传播到失败结果。

如果缺一类证据,就只能标成“待补证据”,不能高置信度下结论。尤其是 flaky 判断,必须有历史运行、错误类型和近期代码改动三方面支撑,不能看到一次超时就说“可能是环境问题”。

这种写法会慢一点,但结论质量更高。

Generator 必须绑定事实来源

生成 PR 标题、PR body、commit message、周报、故障复盘时,Agent 很容易写出漂亮但不准确的内容。

Generator Skill 应该明确要求先读取事实来源:

  • 当前 diff
  • commit 列表
  • 变更文件
  • 测试结果
  • PR 模板
  • issue 或设计文档

然后再生成结构化输出。还要写清楚:不知道的测试结果就写“未验证”,不要伪造;模板里有字段就保留字段,不要为了省事删掉。

这类 Skill 的质量不取决于文案多漂亮,而取决于它是否忠实反映真实改动。

完成前要有验证门

很多 Agent 的坏习惯是“改完就说完成”。可以加一个简单的门槛:在宣称完成、修好、通过之前,必须先执行或说明验证。

这个设计可以作为所有 Pipeline Skill 的最后一关:

  1. 做了什么改动。
  2. 跑了什么验证。
  3. 验证是否通过。
  4. 哪些验证没跑,为什么没跑。

如果没有最新验证结果,就不要说“已完成”。只能说“已修改,尚未验证”。

Skill 是辅助,不是目的

选择 Skill 本身也需要边界。好的元 Skill 不应该让每个请求都变复杂,只需要提醒自己:

  • 用户明确点名某个 Skill 时优先使用。
  • 当前任务明显匹配某个 Skill 时再使用。
  • 简单任务直接做,不要为了走流程而走流程。
  • 一次只用真正有帮助的 Skill,不要把相关 Skill 全部堆上来。

Skill 的目标是降低重复劳动和质量波动,不是把所有请求都变成流程表演。

Tool Wrapper 要把确定性部分交给脚本

抓取 X/Twitter 内容、解析日志、生成固定格式文件,这类任务不应该主要靠自然语言推理。更稳的设计是:

  • SKILL.md 说明什么时候用、怎么调用、输出怎么看。
  • scripts/ 放可执行脚本。
  • README 或 reference 放完整参数说明。

Agent 负责选择正确工具和解释结果,脚本负责确定性执行。这比让模型临场拼接口、猜参数稳定得多。

大型参考资料要拆到 references

Postgres、Kubernetes、云服务最佳实践这类知识很大,不适合全部塞进 SKILL.md

更好的方式是主文件只做索引:

1
2
3
references/query-missing-indexes.md
references/schema-foreign-key-indexes.md
references/security-rls-performance.md

需要优化查询时读 query 相关规则;需要审 RLS 时读 security 相关规则。这样既能保留大量知识,又不会每次触发 Skill 都占满上下文。

复杂状态机要脚本化

如果一个 Skill 要维护游戏状态、牌张守恒、合法动作、胡牌判定,或者任何强一致状态机,纯文本约束通常不够。

这类 Skill 可以先用文字跑通交互,但长期应该把关键逻辑下沉到脚本:

  • 状态初始化
  • 合法动作生成
  • 规则校验
  • 结算
  • 不变量检查

SKILL.md 只保留交互流程和调用方式。确定性逻辑越多,越应该代码化。

一个可复用模板

可以从这个模板开始:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
---
name: your-skill-name
description: Do X for Y situation. Use when the user asks for A, B, or C. Do not use for D.
---

# Your Skill Name

## Purpose

Use this skill to [one clear job].

## Inputs

Before acting, identify:

1. [Required input]
2. [Required context]
3. [Constraints]

If required inputs are missing and cannot be discovered locally, ask concise questions before proceeding.

## Workflow

1. Inspect the relevant context.
2. Load additional references only when needed:
   - [references/checklist.md](references/checklist.md)
   - [assets/template.md](assets/template.md)
3. Execute the smallest sufficient workflow.
4. Verify the result.
5. Report outcome, verification, and remaining risks.

## Stop Conditions

Stop and ask before:

- Performing destructive changes.
- Sending or publishing externally visible content.
- Guessing unavailable facts that affect correctness.

## Output

Return:

1. Summary
2. Details
3. Verification
4. Follow-up risks

这个模板不要原样长期保留。真正写 Skill 时,要删掉不需要的段落,把泛化词替换成具体任务。

质量检查清单

写完后可以按这张清单自查:

  • name 是否短、小写、稳定、可读。
  • description 是否包含任务、触发场景和边界。
  • 这个 Skill 是否只做一类任务。
  • SKILL.md 是否能在 1 分钟内读懂。
  • 是否明确输入、输出、停止条件和验证方式。
  • 大段资料是否拆到了 references/assets/
  • 确定性操作是否沉淀成脚本。
  • 是否避免写入容易过期的事实。
  • 是否用 2-3 个真实 prompt 测过触发是否准确。
  • 是否观察过 Agent 实际会不会按预期读取文件和执行步骤。

结论

高质量 Skill 本质上是工程化的任务说明。它不该追求“什么都能做”,而要把一件重复任务稳定做好。

写 Skill 时优先想清楚四个问题:

  1. 什么时候触发?
  2. 具体做哪一件事?
  3. 成功结果长什么样?
  4. 如何验证没有跳步?

能回答这四个问题,再选择 Tool Wrapper、Generator、Reviewer、Inversion、Pipeline 中合适的模式,Skill 的质量通常就不会差。

参考:

#Agent Skill #SKILL.md #Codex #Claude #AI Agent #工程实践