找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2443

积分

0

好友

329

主题
发表于 昨天 23:57 | 查看: 5| 回复: 0

欢迎阅读「从零开始写好 Skill」系列——上一个系列我们用 7 篇文章拆解了 Agent 的骨架,这个系列教你给 Agent 写“工作手册”。

开场:看到结构 ≠ 会写结构

上一篇,我们看到了 wespy-fetcher 的 SKILL.md,知道了它分成几个部分,也感受到了“有 Skill vs 没 Skill”的巨大差距。

但“看到”和“会写”是两回事。

同样是写描述,为什么有的 Skill 一触即发,有的却被 Agent 视而不见?同样是写操作步骤,为什么有的让 Agent 一步到位,有的却让 Agent 反复出错?

这篇我们就拿 wespy-fetcher 的真实 SKILL.md 开刀,逐段拆解。这次的重点不再是“这段是什么”——上一篇已经讲过了。这次我们聚焦于:这段怎么写才有效,写错了会怎样

一、先看全貌:一个 Skill 的四层骨架

让我们先把 wespy-fetcher 的 SKILL.md 完整地看一遍,不加批注,感受它的原貌:

---
name: wespy-fetcher
description: 获取并转换微信公众号/网页文章为 Markdown 的封装 Skill,
  完整支持 WeSpy 的单篇抓取、微信专辑批量下载、专辑列表获取、
  HTML/JSON/Markdown 多格式输出。
  Use when user asks to 抓取微信公众号文章、公众号专辑批量下载、
  URL 转 Markdown、保存微信文章、mp.weixin.qq.com to markdown.
---
# WeSpy Fetcher
封装 tianchangNorth/WeSpy 的完整能力。

## 功能范围(与 WeSpy 对齐)

- 单篇文章抓取(微信公众号 / 通用网页 / 掘金)
- 微信专辑文章列表获取(--album-only)
- 微信专辑批量下载(--max-articles)
- 多格式输出(Markdown 默认,支持 HTML / JSON / 全部)

## 使用

脚本位置:scripts/wespy_cli.py

# 单篇文章(默认输出 markdown)
python3 scripts/wespy_cli.py "https://mp.weixin.qq.com/s/xxxxx"

# 专辑批量下载
python3 scripts/wespy_cli.py "https://mp.weixin.qq.com/mp/appmsgalbum?..." --max-articles 20

## 实现说明

- 优先使用本地源码路径 ~/Documents/QNSZ/project/WeSpy
- 若本地不存在则自动执行 git clone 到该目录
- 通过导入 wespy.main.main 直接调用上游 CLI,保持行为一致

这份文件虽然不长,却有着清晰的四层结构。Agent 读取它的过程,就像面试一样,是分层递进的:

第一层:头部(YAML frontmatter)—— 简历筛选
Agent 启动时扫描所有 Skill 的 description,判断“这个任务该不该用这个 Skill”。绝大多数 Skill 在这一步就被跳过了。如果你的 description 写得不好,Agent 根本不会往下读。

第二层:概述(标题 + 功能范围)—— 电话面试
通过了第一层筛选,Agent 会快速读一下概述,确认能力范围是否匹配。“这个 Skill 能处理专辑批量下载吗?”——扫一眼功能范围列表就知道了。

第三层:操作指南(使用方式、命令、参数)—— 入职培训
确认要用这个 Skill 了,Agent 开始读具体的操作步骤。“脚本在哪?怎么调用?参数怎么传?”——这一层给出所有执行细节。

第四层:补充说明(实现细节、依赖、兜底逻辑)—— 应急手册
执行过程中遇到问题了,Agent 会来查阅这一层。“WeSpy 没装怎么办?”——补充说明会告诉它应该自动 clone。

请记住这个分层逻辑,它直接决定了你在写 SKILL.md 时,每一段应该放什么、不应该放什么。高质量的技术文档正是建立在这种清晰的逻辑结构之上。

二、头部:description 是触发器,不是摘要

头部的 YAML frontmatter 是整个 Skill 最关键的部分。这几行如果写错了,后面的内容再好也没用——因为 Agent 根本读不到后面。

让我们再仔细审视一下 wespy-fetcherdescription

description:
获取并转换微信公众号/网页文章为Markdown的封装Skill,
完整支持WeSpy的单篇抓取、微信专辑批量下载、专辑列表获取、
HTML/JSON/Markdown多格式输出。
Use when user asks to 抓取微信公众号文章、公众号专辑批量下载、
URL转Markdown、保存微信文章、mp.weixin.qq.com to markdown.

这段 description 做对了三件事:

第一,前半段是能力声明——“我能做什么”。
“获取并转换微信公众号/网页文章为 Markdown”,一句话讲清楚核心能力。Agent 扫到这里就明白:这是一个处理公众号文章的 Skill,不是处理视频或 PDF 的。

第二,后半段是触发词列表——“用户怎么说时该想到我”。
“Use when user asks to” 后面跟了一串关键词:抓取微信公众号文章、公众号专辑批量下载、URL 转 Markdown、保存微信文章、mp.weixin.qq.com to markdown。

这些不是给人看的,是给 Agent 看的。用户说“帮我抓取这篇公众号”,Agent 会用“抓取”和“公众号”去匹配所有 Skill 的 description,一旦命中“抓取微信公众号文章”,就会加载这个 Skill。

第三,覆盖了用户的多种说法。
同一件事,用户可能有不同的表达方式。有人说“抓取”,有人说“下载”,有人说“保存”,有人甚至直接丢一个 mp.weixin.qq.com 的链接。好的 description 会把这些变体都列上。

现在来看一个反面教材。假如 description 写成这样:

description: 一个用于处理微信文章的工具。

问题在哪里?
“处理”这个词太模糊了——是指抓取、翻译、排版还是总结?Agent 无法判断这个 Skill 是否匹配当前任务。触发词也太少,用户说“帮我下载这篇公众号文章”时,“下载”和“处理”可能匹配不上。

再看另一个极端——写得太长:

description: 这是一个非常强大的工具,可以帮助你从微信公众号平台上
获取任意文章的完整内容,包括文字、图片和格式信息,它使用了
先进的爬虫技术来绕过微信的反爬机制,支持多种输出格式,
并且可以批量处理微信专辑中的所有文章......

问题在于:Agent 扫描 description 时需要快速判断,不是来读长篇大论的。冗长的描述反而可能增加误匹配的风险,而且真正有用的触发词会被淹没在废话里。

description 的写作公式:
一句话能力声明 + "Use when user asks to" + 用户可能说的各种关键词

简洁、精准、覆盖变体。做到这三点就够了。

三、概述:划边界,不是做广告

通过了 description 的筛选,Agent 开始阅读概述部分。wespy-fetcher 的概述只有一句话:

封装 tianchangNorth/WeSpy 的完整能力。

这句话的价值不在于它具体说了什么,而在于它清晰地划定了边界。它明确告诉 Agent:这个 Skill 的能力范围完全等同于 WeSpy 的能力范围,不多也不少。这样一来,Agent 就不会试图用它去完成 WeSpy 做不到的事情。

接着是“功能范围”列表:

- 单篇文章抓取(微信公众号 / 通用网页 / 掘金)
- 微信专辑文章列表获取(--album-only)
- 微信专辑批量下载(--max-articles)
- 多格式输出(Markdown 默认,支持 HTML / JSON / 全部)

这部分的作用是让 Agent 快速进行能力匹配。用户说“帮我批量下载这个专辑”,Agent 扫一眼功能范围,看到“微信专辑批量下载”,确认匹配,就会继续往下读操作步骤。如果用户说的是“帮我把这篇文章翻译成英文”,Agent 扫一眼发现没有“翻译”相关功能,就会跳过这个 Skill,去寻找其他合适的 Skill。

这里有一个常见的坑需要注意:在概述里塞进太多操作细节
比如有人在功能范围里这样写:

- 单篇文章抓取(使用 python3 scripts/wespy_cli.py 命令,
  需要先确保 WeSpy 已安装在 ~/Documents/QNSZ/project/WeSpy 目录,
  如果没有安装会自动 git clone...)

这样写的问题是:Agent 在概述阶段只需要判断“能不能做”,还不需要知道“具体怎么做”。操作细节应该放在下一层。在概述阶段塞入太多信息,反而会干扰 Agent 的匹配判断。

概述的写作原则:说清楚能做什么、不能做什么,其他的一概不说。

四、操作指南:Agent 的执行剧本

确认要使用这个 Skill 后,Agent 就会进入操作指南部分。这是 Skill 的核心——Agent 拿到具体任务后,将严格遵循这里给出的步骤来执行。

wespy-fetcher 的操作指南长这样:

## 使用

脚本位置:scripts/wespy_cli.py

# 单篇文章(默认输出 markdown)
python3 scripts/wespy_cli.py "https://mp.weixin.qq.com/s/xxxxx"

# 专辑批量下载
python3 scripts/wespy_cli.py "https://mp.weixin.qq.com/mp/appmsgalbum?..." --max-articles 20

注意它做对了什么:它提供了多个具体场景的命令示例,而不是只给一个笼统的通用命令。

“单篇文章”和“专辑批量下载”是两个不同的使用场景,用户的需求可能是其中任何一个。Agent 看到这些具体示例,就能根据用户的实际需求选择最匹配的命令,而不是每次都生搬硬套同一个命令。

如果操作指南只写成这样:

## 使用
python3 scripts/wespy_cli.py [URL] [OPTIONS]

那么 Agent 就得自己猜:当用户需要批量下载时,OPTIONS 该填什么?是 --max-articles 还是 --batch--album-only 又是什么意思?猜错了就会导致执行失败。

操作指南的第一原则:给具体场景的示例,不要给抽象的通用模板。

不过,这里需要指出一个重要的前提:wespy-fetcher 之所以采用“命令示例”这种写法,是因为它本质上是一个工具封装——将一个已有的命令行工具包装成 Skill,教会 Agent 如何调用它。

但并非所有 Skill 都是工具封装。不同类型的 Skill,操作指南的写法也完全不同:

  • 如果你的 Skill 是一个生成器(比如“生成技术报告”),操作指南应该写成:加载模板 → 向用户收集信息 → 填充模板 → 输出文档。
  • 如果你的 Skill 是一个审查器(比如“代码审查”),操作指南应该写成:加载审查清单 → 逐条检查用户代码 → 按严重程度分组 → 输出结构化报告。
  • 如果你的 Skill 是一个流水线(比如“从代码生成 API 文档”),操作指南应该写成:步骤1 → 检查点(用户确认)→ 步骤2 → 检查点 → 步骤3。
  • 如果你的 Skill 是一个采访模式(比如“项目规划”),操作指南应该写成:按顺序提问 → 等待用户回答 → 收集完信息后再综合输出。不允许 Agent 在收集完所有必要信息之前就开始行动。

操作指南的写法取决于你的 Skill 属于哪种类型,没有放之四海皆准的格式。 这些类型我们会在后续文章中详细展开。这里先建立这样一个认知:当你评估一个 Skill 的操作指南时,首先要判断它属于哪种类型,然后再评估它写得好不好。

五、补充说明:你以为不重要的部分,其实最防坑

让我们看看 wespy-fetcher 的“实现说明”:

- 优先使用本地源码路径 ~/Documents/QNSZ/project/WeSpy
- 若本地不存在则自动执行 git clone 到该目录
- 通过导入 wespy.main.main 直接调用上游 CLI,保持行为一致

很多人写 Skill 时,会把精力主要花在 description 和操作指南上,补充说明部分则随便写两句,甚至干脆不写。这是一个很大的误区。

设想一下这个场景:Agent 按照操作指南开始执行,调用 python3 scripts/wespy_cli.py,结果发现 WeSpy 根本没安装。怎么办?

如果没有补充说明,Agent 可能会有以下几种反应:

  • 直接报错:“WeSpy 未安装,请手动安装后重试”——这就回到了上一篇提到的“甩锅”状态。
  • 自己猜测安装方式:比如执行 pip install wespy——但如果猜错了,可能会安装一个完全不相关的包。
  • 去网上搜索安装方法——既浪费时间,又可能搜到过时或错误的信息。

但有了上面这三行补充说明,Agent 就知道:先检查 ~/Documents/QNSZ/project/WeSpy 这个路径,如果存在就直接使用;如果不存在,就自动执行 git clone 到这个目录。流程形成了一个闭环,不会在执行中卡死。

这就是补充说明的核心价值:把 Agent 执行过程中可能遇到的“岔路口”提前堵死。

什么是“岔路口”?就是那些需要 Agent 自行判断、但又很可能判断失误的地方:

  • 依赖不存在怎么办?
  • 网络超时怎么办?
  • 输入格式不符合预期怎么办?
  • 输出目录不存在怎么办?
  • 同名文件已经存在,是覆盖还是跳过?

每一个你曾经踩过的“坑”,都应该沉淀到补充说明里。一个 Skill 之所以会变得越来越“聪明”、越来越好用,正是因为它将过去遇到的问题和解决方案都记录在了这里。 这其实也是优秀开源实战项目文档的共通特点。

六、纠正一个简化:Skill 不只是一个文件

在上一篇中,为了降低理解门槛,我们说“Skill 就是一个 Markdown 文件”。这个说法帮助你建立了最初的认知,但从严格意义上讲,它不够准确。

Skill 本质上是一个文件夹,SKILL.md 仅仅是它的入口文件。

一个完整的 Skill 文件夹通常包含以下结构:

wespy-fetcher/
├── SKILL.md           ← 入口文件,Agent 首先读这个
├── scripts/
│   └── wespy_cli.py   ← 可执行脚本,Agent 调用它来完成任务
├── references/        ← 参考资料(API 文档、编码规范等)
└── assets/            ← 模板、示例输出、配置文件等
  • SKILL.md 是大脑——告诉 Agent 该做什么。
  • scripts/ 是手脚——提供实际执行任务所需的脚本。
  • references/ 是参考书——存放 Agent 在执行过程中可能需要查阅的背景知识。
  • assets/ 是工具箱——存放模板、配置等辅助资源。

Agent 并不是读完 SKILL.md 就凭空开始干活——它会探索整个文件夹,在需要的时候读取对应的文件。例如,wespy-fetcher 的操作指南里指明了 scripts/wespy_cli.py,Agent 在执行时就会去 scripts/ 目录下寻找这个脚本。

这引出一个重要的实践原则:SKILL.md 本身应该保持精简,建议将行数控制在 500 行以内。 超出这个范围的内容,应该拆分到子文件中,然后在 SKILL.md 里用相对路径进行引用。

为什么要这么做?因为 Agent 的上下文窗口是有限的。如果你把一个长达 3000 行的 API 文档全部塞进 SKILL.md,那么 Agent 每次加载这个 Skill 时都会消耗大量的上下文空间,留给执行其他任务的空间就所剩无几了。

更好的做法是:在 SKILL.md 里写明“详细的 API 规范请参见 references/api.md”。这样,Agent 只有在真正需要查阅 API 时,才会去加载那个特定的文件。这就是所谓的渐进式揭示——按需加载,而不是一次性把所有信息都塞进去。

七、一个检查清单:你的 SKILL.md 写对了吗?

理论拆解完毕,现在给你一份可以直接带走的检查清单。下次写完一个 SKILL.md 后,可以对照着逐一核对:

头部(description):

  • [ ] 写的是触发条件,而非功能摘要。
  • [ ] 包含 “Use when user asks to” 或类似的触发词引导句。
  • [ ] 覆盖了用户可能的多种表达方式(同一件事的不同说法)。
  • [ ] 长度适中,通常不超过 5 行。

概述:

  • [ ] 用一句话说清楚这个 Skill 的能力边界。
  • [ ] 功能范围列表只罗列“能做什么”,不包含具体的操作细节。

操作指南:

  • [ ] 给出了针对具体场景的命令或步骤示例。
  • [ ] 为不同的使用场景提供了不同的示例(不仅仅是一个通用模板)。
  • [ ] 写法与 Skill 的类型相匹配(例如:工具封装、生成器、审查器、流水线、采访模式)。

补充说明:

  • [ ] 覆盖了依赖缺失时的兜底方案。
  • [ ] 覆盖了常见的错误场景及其处理方式。
  • [ ] 将过去踩过的“坑”和解决方案都沉淀在了这里。

整体结构:

  • [ ] SKILL.md 文件本身控制在 500 行以内。
  • [ ] 超出部分的内容已合理拆分到 references/scripts/assets/ 等子目录中。
  • [ ] 四层结构清晰明了:头部 → 概述 → 操作指南 → 补充说明。

下一篇预告

现在,你已经知道了一个好 Skill 应该长什么样,也拥有了一份实用的检查清单。但是,纸上得来终觉浅——读一百个别人的 Skill,也不如自己动手从零开始写一个。

下一篇,我们将从一个真实的需求出发,手把手教你编写一个 Skill。你将看到一个完整的迭代过程:第一版写得很粗糙,Agent 使用时错误百出;然后我们一步步修改、踩坑、补充,直到第三版终于变得稳定好用。这个“从烂到好”的实践过程,远比直接看一个完美的成品更有价值。


「从零开始写好 Skill」系列是「从零开始理解 Agent」系列的姊妹篇。如果你对人工智能 Agent 的基础原理还不太熟悉,建议先从 第一篇:Agent 的底层原理 开始阅读,这将帮助你更好地理解 Skill 在整个 Agent 体系中的作用。




上一篇:生产级云原生大模型推理:Kthena与vLLM-Ascend的编排调度实践
下一篇:小米汽车2025年营收破千亿,财报解析业务增长与挑战
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-26 02:16 , Processed in 0.649227 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表