Skill 创建者最佳实践
从真实的专业知识出发
在创建 Skill 时,一个常见的陷阱是在不提供特定领域上下文的情况下要求 LLM 生成 Skill——仅仅依赖 LLM 的通用训练知识。这会导致产生模糊、通用的流程(“适当地处理错误”、“遵循身份验证的最佳实践”),而不是那些能让 Skill 真正发挥价值的特定 API 模式、边缘情况和项目约定。
有效的 Skills 建立在真实的专业知识之上。关键在于将特定领域的上下文输入到创建过程中。
从实际操作任务中提取
在与 Agent 的对话中完成一个真实任务,并在此过程中提供上下文、纠正和偏好。然后将可复用的模式提取为一个 Skill。请注意以下几点:
- 行之有效的步骤 —— 导向成功的操作序列
- 你做出的纠正 —— 你引导 Agent 调整方法的地方(例如,“使用库 X 而不是 Y”,“检查边缘情况 Z”)
- 输入/输出格式 —— 数据输入和输出时的样子
- 你提供的上下文 —— Agent 尚未知晓的特定于项目的事实、约定或约束
从现有项目产物中综合
当你拥有大量现有知识时,你可以将其输入给 LLM 并要求它综合出一个 Skill。从你团队实际的事件报告和运行手册中综合出的数据管道 Skill,将优于从通用的“数据工程最佳实践”文章中综合出的 Skill,因为它捕获了你的模式(schemas)、故障模式和恢复程序。关键在于特定于项目的材料,而不是通用的参考资料。
优秀的源材料包括:
- 内部文档、运行手册和样式指南
- API 规范、模式(schemas)和配置文件
- 代码审查评论和问题跟踪器(捕获反复出现的关注点和审查者的期望)
- 版本控制历史,特别是补丁和修复(通过实际更改的内容揭示模式)
- 真实的故障案例及其解决方案
通过真实执行进行完善
Skill 的初稿通常需要完善。在真实任务中运行该 Skill,然后将结果——所有结果,而不仅仅是失败的结果——反馈到创建过程中。问问自己:是什么触发了误报?遗漏了什么?可以删减什么?
即使只进行一次“执行-修改”的循环,也能显著提高质量,而复杂的领域通常会从多次循环中受益。
阅读 Agent 的执行轨迹,而不仅仅是最终输出。如果 Agent 在无用的步骤上浪费时间,常见原因包括指令过于模糊(Agent 在找到有效方法之前尝试了多种方法)、指令不适用于当前任务(Agent 仍然遵循了它们),或者提供了太多选项而没有明确的默认值。
有关更结构化的迭代方法(包括测试用例、断言和评分),请参阅 评估 Skill 输出质量。
明智地使用上下文
一旦 Skill 被激活,其完整的 SKILL.md 主体将与对话历史、系统上下文和其他活动的 Skills 一起加载到 Agent 的上下文窗口中。你的 Skill 中的每一个 token 都在与该窗口中的所有其他内容争夺 Agent 的注意力。
补充 Agent 缺乏的,省略它已知的
专注于如果没有你的 Skill,Agent 不会知道的内容:特定于项目的约定、特定于领域的程序、不明显的边缘情况,以及要使用的特定工具或 API。你不需要解释什么是 PDF、HTTP 是如何工作的,或者数据库迁移是做什么的。
<!-- 过于冗长 —— Agent 已经知道什么是 PDF -->
## 提取 PDF 文本
PDF(便携式文档格式)文件是一种包含文本、图像和其他内容的常见文件格式。
要从 PDF 中提取文本,你需要使用一个库。推荐使用 pdfplumber,因为它能很好地处理大多数情况。
<!-- 更好 —— 直接切入 Agent 自身不知道的内容 -->
## 提取 PDF 文本
使用 pdfplumber 进行文本提取。对于扫描文档,退而使用带有 pytesseract 的 pdf2image。
```python
import pdfplumber
with pdfplumber.open("file.pdf") as pdf:
text = pdf.pages[0].extract_text()
```
对每一部分内容问问自己:“如果没有这条指令,Agent 会弄错吗?”如果答案是否定的,就删掉它。如果你不确定,就测试一下。如果 Agent 在没有该 Skill 的情况下已经能很好地处理整个任务,那么该 Skill 可能并没有增加价值。有关如何系统地测试这一点,请参阅 评估 Skill 输出质量。
设计连贯的单元
决定一个 Skill 应该涵盖什么,就像决定一个函数应该做什么一样:你希望它封装一个连贯的工作单元,并能与其他 Skills 很好地组合。范围过窄的 Skills 会迫使单个任务加载多个 Skills,从而带来开销和指令冲突的风险。范围过宽的 Skills 则变得难以精确激活。一个用于查询数据库并格式化结果的 Skill 可能是一个连贯的单元,而一个同时涵盖数据库管理的 Skill 可能试图做太多事情。
追求适度的细节
过于全面的 Skills 可能会弊大于利——Agent 会难以提取相关内容,并可能因为不适用于当前任务的指令而走上无用的路径。带有有效示例的简明、逐步的指导往往优于详尽的文档。当你发现自己涵盖了每一个边缘情况时,请考虑是否大多数情况最好由 Agent 自行判断处理。
使用渐进式披露构建大型 Skills
规范 建议将 SKILL.md 保持在 500 行和 5,000 个 tokens 以内——仅包含 Agent 每次运行所需的核心指令。当一个 Skill 确实需要更多内容时,请将详细的参考材料移动到 references/ 或类似目录中的单独文件里。
关键在于告诉 Agent 何时加载每个文件。“如果 API 返回非 200 状态码,请阅读 references/api-errors.md”比通用的“有关详细信息,请参阅 references/”更有用。这使得 Agent 能够按需加载上下文,而不是预先加载,这正是 渐进式披露 的设计初衷。
校准控制力度
并非 Skill 的每个部分都需要相同程度的规定性。请将指令的明确程度与任务的脆弱性相匹配。
将明确程度与脆弱性相匹配
给予 Agent 自由度:当多种方法都有效且任务容许差异时。对于灵活的指令,解释原因可能比死板的指示更有效——理解指令背后目的的 Agent 能做出更好的依赖于上下文的决策。一个代码审查 Skill 可以描述要寻找什么,而无需规定确切的步骤:
## 代码审查流程
1. 检查所有数据库查询是否存在 SQL 注入(使用参数化查询)
2. 验证每个端点上的身份验证检查
3. 在并发代码路径中寻找竞争条件
4. 确认错误消息不会泄露内部细节
具有规定性:当操作很脆弱、一致性很重要,或者必须遵循特定顺序时:
## 数据库迁移
严格按照此顺序运行:
```bash
python scripts/migrate.py --verify --backup
```
不要修改命令或添加额外的标志。
大多数 Skills 都是混合的。请独立校准每个部分。
提供默认值,而不是菜单
当多种工具或方法都可行时,选择一个默认值并简要提及替代方案,而不是将它们作为平等的选项呈现。
<!-- 选项过多 -->
你可以使用 pypdf、pdfplumber、PyMuPDF 或 pdf2image...
<!-- 带有备用方案的明确默认值 -->
使用 pdfplumber 进行文本提取:
```python
import pdfplumber
```
对于需要 OCR 的扫描版 PDF,请改用带有 pytesseract 的 pdf2image。
倾向于过程而非声明
一个 Skill 应该教 Agent 如何处理一类问题,而不是为特定实例生成什么。比较一下:
<!-- 具体答案 —— 仅对这个确切的任务有用 -->
在 `customer_id` 上将 `orders` 表与 `customers` 表连接,过滤
`region = 'EMEA'` 的数据,并对 `amount` 列求和。
<!-- 可复用方法 —— 适用于任何分析查询 -->
1. 从 `references/schema.yaml` 读取模式(schema)以查找相关表
2. 使用 `_id` 外键约定连接表
3. 将用户请求中的任何过滤器作为 WHERE 子句应用
4. 根据需要聚合数字列,并格式化为 Markdown 表格
这并不意味着 Skills 不能包含具体细节——输出格式模板(参见 输出格式模板)、诸如“绝不输出 PII”之类的约束以及特定于工具的指令都很有价值。关键在于,即使个别细节是具体的,方法也应该是可泛化的。
有效指令的模式
这些是用于构建 Skill 内容的可复用技术。并非每个 Skill 都需要所有这些技术——请使用适合你任务的技术。
输出格式模板
当你需要 Agent 以特定格式生成输出时,请提供一个模板。这比用文字描述格式更可靠,因为 Agent 能很好地对具体结构进行模式匹配。简短的模板可以直接内联在 SKILL.md 中;对于较长的模板,或者仅在某些情况下需要的模板,请将它们存储在 assets/ 中,并从 SKILL.md 引用它们,以便它们仅在需要时加载。
## 报告结构
使用此模板,根据具体分析的需要调整各个部分:
```markdown
# [分析标题]
## 执行摘要
[关于主要发现的一段概述]
## 主要发现
- 带有支持数据的发现 1
- 带有支持数据的发现 2
## 建议
1. 具体的、可操作的建议
2. 具体的、可操作的建议
```
多步工作流的清单
明确的清单有助于 Agent 跟踪进度并避免跳过步骤,特别是当步骤具有依赖关系或验证关卡时。
## 表单处理工作流
进度:
- [ ] 步骤 1:分析表单(运行 `scripts/analyze_form.py`)
- [ ] 步骤 2:创建字段映射(编辑 `fields.json`)
- [ ] 步骤 3:验证映射(运行 `scripts/validate_fields.py`)
- [ ] 步骤 4:填写表单(运行 `scripts/fill_form.py`)
- [ ] 步骤 5:验证输出(运行 `scripts/verify_output.py`)
验证循环
指示 Agent 在继续之前验证自己的工作。模式是:完成工作,运行验证器(脚本、参考清单或自检),修复任何问题,并重复直到验证通过。
## 编辑工作流
1. 进行你的编辑
2. 运行验证:`python scripts/validate.py output/`
3. 如果验证失败:
- 查看错误消息
- 修复问题
- 再次运行验证
4. 仅在验证通过时才继续
参考文档也可以作为“验证器”——指示 Agent 在最终确定之前对照参考文档检查其工作。
计划-验证-执行
对于批处理或破坏性操作,让 Agent 以结构化格式创建一个中间计划,对照事实来源(source of truth)对其进行验证,然后才执行。
## PDF 表单填写
1. 提取表单字段:`python scripts/analyze_form.py input.pdf` → `form_fields.json`
(列出每个字段名称、类型以及是否必填)
2. 创建 `field_values.json`,将每个字段名称映射到其预期值
3. 验证:`python scripts/validate_fields.py form_fields.json field_values.json`
(检查表单中是否存在每个字段名称,类型是否兼容,以及
必填字段是否缺失)
4. 如果验证失败,修改 `field_values.json` 并重新验证
5. 填写表单:`python scripts/fill_form.py input.pdf field_values.json output.pdf`
关键要素是步骤 3:一个验证脚本,用于对照事实来源(form_fields.json)检查计划(field_values.json)。诸如“未找到字段 'signature_date' —— 可用字段:customer_name, order_total, signature_date_signed”之类的错误,能为 Agent 提供足够的信息来进行自我纠正。
打包可复用脚本
在 迭代 Skill 时,比较 Agent 在各个测试用例中的执行轨迹。如果你注意到 Agent 每次运行都在独立地重复发明相同的逻辑——构建图表、解析特定格式、验证输出——这就是一个信号,表明你应该编写一次经过测试的脚本并将其打包在 scripts/ 中。
有关设计和打包脚本的更多信息,请参阅 在 Skills 中使用脚本。
后续步骤
一旦你拥有了一个可用的 Skill,以下两份指南可以帮助你进一步完善它:
- 评估 Skill 输出质量 —— 设置测试用例,对结果进行评分,并系统地进行迭代。
- 优化 Skill 描述 —— 测试并改进你的 Skill 的
description字段,以便它能在正确的提示词下触发。