一个高质量的 Skill 应该长什么样

好 Skill 不是"写了就行",是"Agent 读完就能干活"。


目录


Skill 是什么

你让 AI 帮你做代码审查。它看了一段代码,给出了几条通用建议:“变量命名可以更清晰”、“建议加单元测试”、“考虑异常处理”。说得都对,但没什么用——它不知道你项目的规范:Service 层禁止直接调用 Mapper、Controller 不允许写业务逻辑、所有接口必须返回统一的 Result<T> 格式。

你补充了这些背景知识,AI 的审查结果立刻好了很多。但下次开新对话,你又得重新说一遍。

Skill 解决的就是这个问题。

Skill 是一份给 AI Agent 看的"专家手册"。你把特定领域的知识、流程、约束写成 Agent 能理解的结构化文档,Agent 遇到相关任务时自动加载这份手册。不需要你每次重复输入背景知识。

具体来说,一个 Skill 就是文件系统上的一个文件夹,里面有一个主文件(SKILL.md)和一些可选的参考资料。Agent 根据主文件里的描述信息判断"这个任务跟哪个 Skill 有关",然后自动读取对应的指令。

一句话:Skill = 让 Agent 从"通用助手"变成"领域专家"的知识载体。


什么场景该用 Skill

不是所有任务都需要写 Skill。判断标准很简单:你是否在反复给 AI 补充同样的背景知识?

适合用 Skill 的场景

重复性的专业任务。 代码审查、PDF 处理、API 文档生成、数据库迁移——这些任务每次的流程差不多,但涉及特定工具、规范或约定。写一次 Skill,以后每次都不用重复说明。

项目特定的知识。 业务规则(“订单状态只能从 CREATED 到 PAID,不能跳过”)、架构约定(“所有数据库操作必须在 Repository 层”)、代码规范(“接口命名用 RESTful 风格”)。这些知识不存在于任何公开文档里,只存在于你的项目中。

多步骤的复杂流程。 部署流程(构建 → 测试 → 打包 → 推送 → 部署 → 验证)、数据迁移(备份 → 改表 → 回填 → 校验)、测试策略(单测 → 集成测试 → E2E)。步骤多、顺序重要、容易遗漏。

不需要 Skill 的场景

一次性的简单任务。 “帮我写个 Hello World”、“这个 JSON 格式对不对”——Agent 本身就能搞定,不需要额外知识。

Agent 本身就能做好的事。 通用的编程问题、算法题、正则表达式——这些是 Agent 的基础能力,写 Skill 反而是浪费上下文窗口。

一句话:如果你发现自己在反复给 AI 补充同样的背景知识,就该写个 Skill。


Skill 长什么样:组成部分

一个 Skill 就是文件系统上的一个文件夹。最简单的 Skill 只需要一个文件,完整的 Skill 可能长这样:

code-review/
├── SKILL.md              # 必须:主文件
├── agents/
│   └── openai.yaml       # 可选:UI 展示元数据
├── references/            # 可选:详细参考文档
│   ├── naming-rules.md    #   命名规范
│   ├── layer-rules.md     #   分层规范
│   └── api-standards.md   #   API 设计规范
├── scripts/               # 可选:自动化脚本
│   └── lint_check.py      #   自动检查脚本
└── assets/                # 可选:模板等资源
    └── review-template.md #   审查报告模板

SKILL.md 的两部分

每个 Skill 的核心是 SKILL.md 文件,它由两部分组成:

Frontmatter(YAML 头部):用 --- 包裹的元数据,包含 namedescription 两个字段。这两个字段是 Agent 判断"要不要用这个 Skill"的唯一依据——Agent 在决定是否触发时只看这段元数据,不会读正文。

---
name: code-review
description: >
  按照项目规范进行代码审查,检查分层架构、命名规范、
  异常处理和 API 设计。当用户要求审查代码、检查 PR、
  或询问代码质量时使用。不用于代码格式化或 lint 检查。
---

Body(Markdown 正文):Frontmatter 之后的所有内容。只有当 Skill 被触发后才会加载。这里是你的指令正文——告诉 Agent 怎么完成任务。

渐进式披露:三级加载

这里有一个关键设计:Skill 的内容不是一次性全部加载的,而是分三级按需加载。这个机制叫渐进式披露——在合适的时机给 Agent 合适的信息,既节省上下文窗口(Agent 一次能处理的文字量是有限的),又避免信息过载。

层级 何时加载 大小 内容
元数据(description) 始终可见 ~100 字 Agent 用来判断要不要触发
主文件正文(SKILL.md body) 触发时加载 ≤3000 字 Agent 用来理解任务、制定方案
引用详情(references/) Agent 判断需要时 按需 具体的规范、API 定义、流程细节

这意味着:如果你把所有知识都塞进 SKILL.md 的正文里,每次触发都会消耗大量上下文窗口。把详细内容拆到 references/ 里,Agent 只在需要时才去读,效率高得多。

一句话:Skill 不是一个大文件,是分层的知识结构。


description:Skill 的门面

description 是整个 Skill 最关键的字段。它决定了 Agent 什么时候调用这个 Skill——写得好,Agent 能精准识别需要它的场景;写得差,要么该触发不触发,要么不该触发乱触发。

好 description 需要回答三个问题:做什么、什么时候用、什么时候不用。

Before / After

烂 description:

description: 处理 PDF 文件

问题:太宽泛。"处理"是读取还是编辑?是提取文本还是转格式?Agent 不知道什么时候该触发这个 Skill。

好 description:

description: >
  读取、创建、编辑 PDF 文件,支持文本提取、页面渲染、
  格式转换。当用户需要处理 .pdf 文件时使用,包括查看内容、
  修改格式、合并拆分、添加水印等场景。不用于纯文本文件
  (.txt / .md)的处理。

改进:明确了能力范围(读取、创建、编辑)、触发场景(.pdf 文件)、反面条件(不用于纯文本)。

反面条件的价值

写清楚"什么时候不用"比写清楚"什么时候用"更能减少误触发。

比如一个"API 文档生成"Skill,如果你只写"生成 API 文档",Agent 在用户问"这个 API 怎么调用"时也可能触发——但用户要的是使用说明,不是生成文档。加上"不用于 API 使用教程或接口调试",误触发率会明显下降。

一句话:description 是给 Agent 看的路由规则,不是给人看的产品介绍。 不要写成营销文案,要写成精准的触发条件。


主文件:Agent 读完就能干活

主文件是 Skill 被触发后 Agent 第一个读到的内容。它需要回答一个问题:Agent 读完这份文件后,能不能直接开始干活?

好主文件的结构通常包含四个部分。

1. 使用顺序

告诉 Agent “先看什么、再看什么”。不是所有 references 都需要读——Agent 需要根据当前任务选择性地加载。

## 使用顺序
- 先看 `references/naming-rules.md`,确认命名规范
- 再看 `references/layer-rules.md`,确认分层约束
- 改 API 时才看 `references/api-standards.md`

2. 关键入口

直接列出代码文件的完整路径。Agent 不需要自己去搜索——你告诉它入口在哪,它直接打开。

## 关键入口
- `src/main/java/com/example/controller/UserController.java`
- `src/main/java/com/example/service/UserService.java`
- `src/main/java/com/example/repository/UserRepository.java`

3. 必守约束

不能碰的红线。这部分非常重要,下一节单独展开。

4. 参考资料

指向 references/ 目录下的文件列表。Agent 在需要时按需读取。

Before / After

烂主文件:

# 代码审查 Skill

代码审查(Code Review)是软件开发中的重要环节,目的是
发现代码中的潜在问题,提高代码质量。好的代码审查应该关注
可读性、可维护性、性能和安全性……

常见的代码问题包括:命名不规范、缺少异常处理、硬编码、
重复代码、过度耦合……

问题:Agent 读完知道了"代码审查是什么",但不知道"在这个项目里怎么做"。这些概念性的知识 Agent 本来就知道,不需要你教。

好主文件:

# code-review

## 使用顺序
- 先看 `references/layer-rules.md`,确认分层约束
- 再看 `references/naming-rules.md`,确认命名规范
- 改 API 时才看 `references/api-standards.md`

## 关键入口
- Controller 层:`src/main/java/com/example/controller/`
- Service 层:`src/main/java/com/example/service/`
- Repository 层:`src/main/java/com/example/repository/`

## 必守约束
- Controller 不允许写业务逻辑,只能做参数校验和路由
- Service 层禁止直接调用 Mapper,必须通过 Repository
- 所有接口返回 `Result<T>`,不要裸返 POJO
- 异常统一在 GlobalExceptionHandler 处理,不要在业务代码里 try-catch

## 参考资料
- `references/layer-rules.md`
- `references/naming-rules.md`
- `references/api-standards.md`

改进:Agent 读完就知道去哪、看什么、哪些红线不能碰。不需要你再补充任何背景知识。

一句话:主文件是操作手册,不是百科全书。 Agent 不需要你解释业务概念,它需要你告诉它"改哪里、怎么改、不能改什么"。


约束怎么写:解释 Why,不堆 MUST

约束是 Skill 里最重要的部分。它告诉 Agent 哪些红线不能碰——但怎么写约束,效果差距很大。

堆命令 vs 解释原因

烂约束:

- 必须使用 HNSW 索引
- 绝不能在 Controller 里写业务逻辑
- 所有查询必须分页

Agent 会严格遵守这些命令。但问题是:当场景变化时,它不知道什么时候可以变通。“必须使用 HNSW”——如果数据量很小、写入很频繁呢?IVFFlat 可能更合适。但你写了"必须",Agent 就不敢换。

好约束:

- HNSW 在查询密集场景下延迟更低。RAG 的写入频率远低于
  查询频率,所以默认选 HNSW。如果数据量小且写入频繁,
  可以考虑 IVFFlat。

- Controller 的职责是接收请求、校验参数、返回响应。
  业务逻辑放 Controller 会导致:1)无法复用;2)无法
  做单元测试;3)改业务需求时要同时改 Controller 和 Service。

- 不分页的查询在数据量增长后会拖垮数据库。所有列表查询
  默认分页,上限 100 条。

改进:Agent 理解了背后的原因,能在场景变化时自己判断。你给它理由,它能推导出 How。

口语化 vs 格式化

约束的语气也很重要。格式化的规范文档读起来像法律条文,Agent 能理解但执行时容易僵化。口语化的表述更容易被正确执行。

格式化:

sessionId 是会话主键语义,历史查询必须做归属校验。

口语化:

sessionId 是会话的身份证。查历史记录时必须确认是这个用户的,
不能让 A 看到 B 的对话。

口语化版本多了一个类比(“身份证”)和一个具体的错误场景(“A 看到 B 的对话”),Agent 更容易理解约束的实际含义和违反后果。

一句话:给 Agent 理由比给它命令更有效。 当你发现自己在写"ALWAYS"和"NEVER"的时候,停下来想想能不能换个方式解释清楚背后的原因。


反模式清单

写 Skill 时常见的五个反模式,每个都有简单的修正方法。

反模式一:description 写成产品介绍。

❌ "这是一个强大的代码审查工具,支持多种语言,提供智能建议。"
✅ "按照项目规范审查代码,检查分层、命名、异常处理。
    当用户要求审查代码或检查 PR 时使用。不用于代码格式化。"

description 是路由规则,不是广告词。写触发条件和反面条件。

反模式二:主文件写成文档。

❌ 大段解释"什么是代码审查"、"为什么要做代码审查"
✅ 直接告诉 Agent:看哪个文件、改哪个函数、遵守哪些约束

Agent 本来就知道代码审查是什么。它不知道的是你项目的规范。

反模式三:约束堆 MUST / NEVER。

❌ "必须使用 HNSW 索引"
✅ "HNSW 查询更快,RAG 场景写少读多,所以选 HNSW"

解释 Why,让 Agent 能在场景变化时自己判断。

反模式四:所有知识塞一个文件。

❌ 一个 5000 字的 SKILL.md,所有规范平铺在里面
✅ SKILL.md 2000 字 + 3 个 reference 文件,按需加载

拆 references,让 Agent 只读需要的部分。上下文窗口是公共资源,不要浪费。

反模式五:没有关键入口路径。

❌ "代码在 src/main/java 目录下"
✅ "src/main/java/com/example/controller/UserController.java"

列出具体文件的完整路径。Agent 不需要自己去搜索,你告诉它入口在哪,它直接打开。


总结:好 Skill 的检查清单

写完一个 Skill 后,用这个清单自查:

  • description 包含触发条件和反面条件——Agent 能准确判断什么时候用、什么时候不用
  • 主文件是操作手册,不是百科全书——Agent 读完能直接干活,不需要你补充背景
  • 约束解释了 Why,不只是堆 MUST——Agent 理解原因,能在场景变化时自己判断
  • 关键入口有完整路径——Agent 不需要搜索,直接定位到文件
  • 详细内容拆到了 references/——Agent 按需加载,不浪费上下文窗口
  • 主文件不超过 3000 字——超过就该拆了
  • 口语化表述,不写法律条文——Agent 更容易正确执行

好 Skill 是改出来的,不是一次写好的。先写一个能用的版本,然后在真实任务中迭代打磨——看 Agent 哪里卡住了、哪里理解错了、哪里做了无用功,针对性地改进。每改一轮,Skill 就上一个台阶。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐