第八话里,工具接入终于有了统一的边界。
Agent 想查天气,可以调用 MCP Server;想读数据库,也可以通过同一套协议发现和调用工具。工具来自另一个进程、另一种语言,甚至另一个团队时,调用方不必再为每一项能力重写适配代码。
可一个任务通常不只缺一个工具。
让 Agent 检查一篇文章,它也许找得到文件检查工具,却不知道应先看 frontmatter 还是标题;它也许发现了错误,却不知道能否直接改原文;它也许完成了几步操作,却没有明确的完成判定。工具越来越多,“应该怎样把事情做完整”反而更值得被固定下来。
先说结论:
MCP 解决“Agent 能调用什么”,Skill 解决“Agent 应该按什么方法完成任务”。
Skill 不是把 Prompt 写得更长。它把一套经过思考的方法拆成能被发现、按需加载、执行和验证的资源。
一、工具暴露动作,Skill 组织方法
假设我们有一个 Markdown 检查工具。它能接收文件路径、返回检查结果,也许还支持修复参数。这些信息足以描述一个动作,却不能自动给出一条可靠的任务路径。
| 任务问题 | 单个工具通常能否回答 |
|---|---|
| 检查哪个文件 | 可以 |
| 先检查 frontmatter 还是标题 | 不一定 |
| 失败后是否继续 | 不一定 |
| 能否直接修改原文 | 不能替代权限约束 |
| 什么结果算任务完成 | 需要额外规则 |
这和 Java 服务里已经注册了一组接口很像:checkFrontmatter()、checkHeading()、checkLinks() 都可调用,并不等于“文章质量检查”这个业务流程已经存在。顺序、分支、验收标准和修改权限仍需要被组织起来。
关键洞察:工具把能力暴露出来,Skill 把能力组织成方法。
二、一个 Skill 到底保存了什么
人说“我会检查博客文章”时,脑中通常不只是一句提醒,还包括适用场景、检查步骤、参考标准、可以交给脚本的部分,以及失败时应如何收尾。
Agent Skills Specification 规定,一个 Skill 至少是包含 SKILL.md 的目录;scripts/、references/ 和 assets/ 都是按任务需要才加入的可选资源。真正重要的不是目录长相,而是把原本藏在人脑中的做法,拆成可审阅、可替换的职责。
图中有一个容易被忽略的顺序:先用 name + description 判断这个 Skill 是否相关;匹配后才加载 SKILL.md;执行时再按需要读取参考资料、调用脚本或复用资产。目录的作用不是堆文件,而是让不同类型的知识在恰当的时机进入任务。
一个过于抽象的写法往往没有可执行性:
# Markdown 质量检查
请认真、全面地检查文章。
下面这种写法才把“做事方法”落到了可操作的层面:
---
name: markdown-quality
description: Check Markdown articles for required frontmatter, one H1 title, and a closing summary.
---
1. 读取 `references/checklist.md`。
2. 运行 `scripts/validate.py <markdown-file>`。
3. 报告每条失败规则和可操作的修复建议。
4. 未经明确请求,不修改文章。
差别不在于后者更长,而在于它明确了输入、步骤、确定性工具、输出和权限边界。
三、Skill 如何被发现,又为何不必一次读完
一个 Agent 不需要在每次任务开始时,把所有 Skill 的全部说明、资料和脚本都塞进上下文。官方 Quickstart 把过程拆成发现、激活和执行:启动时先看到技能的 name 与 description;任务匹配后再读取完整 SKILL.md;真正执行时才访问需要的资源。Agent Skills Quickstart
这张图描述的是分层加载,而不是某个模型保证会做出的路由决定。description 写得太泛,匹配阶段就缺少足够线索;把无关资料全塞进入口文件,又会让每次执行背负不必要的上下文。一个好的描述更像服务注册中心里的服务名片:它不执行业务,却决定调用方能否先找到正确入口。
关键洞察:Skill 的入口要足够具体以便被发现,细节则应在真正需要时才加载。
四、动手:运行一个最小 Skill Host
这一节不模拟 LLM 推理,也不声称模型一定会选择正确 Skill。它只把一个 Skill Host 的协议边界固定下来:扫描 frontmatter、按 description 做最小匹配、加载指令、调用确定性验证脚本。
代码位于 GYA 的 c09-skill-system:
c09-skill-system/
├── main.py
├── skills/
│ └── markdown-quality/
│ ├── SKILL.md
│ ├── references/checklist.md
│ └── scripts/validate.py
└── samples/
├── good.md
└── bad.md
运行环境只有 Python 3.9+,不依赖第三方包,也不需要 API Key:
git clone https://github.com/renxin2024/GYA.git
cd GYA/c09-skill-system
python3 main.py
2026-08-22 在 Python 3.9.6 上的实际输出如下:
[discover] markdown-quality
[match] markdown-quality
[load] SKILL.md + references/checklist.md
[validate] good.md -> PASS: frontmatter=ok h1=1 summary=ok
[validate] bad.md -> FAIL: frontmatter must be delimited by ---; missing closing section: ## 总结
[validate] passed=1 failed=1 (expected)
[result] status=PASS
这里最后的 status=PASS 不表示两份样例都合格。它表示 Host 的验收条件被满足:合格样例通过,故意损坏的样例被拦截。把“验证器工作正常”和“被验证对象合格”分开,是写 Skill 时很重要的工程习惯。
如果运行结果不同,先按下面顺序排查:
- 确认当前目录是
GYA/c09-skill-system,否则main.py找不到相对路径下的 Skill 和样例。 - 确认使用 Python 3.9+;本 demo 使用了 Python 3.9 开始支持的内置泛型类型标注。
- 检查
skills/markdown-quality/SKILL.md是否保留了references/checklist.md这一引用;demo 会把缺少该引用视为无效 Skill。
五、哪些工作交给模型,哪些交给脚本
Skill 不等于“把所有步骤都交给脚本”。模型仍然适合开放判断,例如观点是否清楚、语气是否自然、解释是否遗漏读者前提。脚本更适合结果只有明确对错的事情。
| 工作 | 更适合的职责方 | 原因 |
|---|---|---|
| 判断文章观点是否清楚 | 模型 | 需要语义理解与上下文判断 |
| 判断语气是否自然 | 模型 | 需要综合语言和读者语境 |
| 统计 H1 数量 | 脚本 | 可得到稳定的确定性结果 |
| 检查 JSON 能否解析 | 脚本 | 成功或失败有明确判定 |
| 检查文件是否存在 | 脚本 | 不需要模型猜测 |
| 删除文件、发送消息、部署 | 权限系统与人工审批 | 正确性不等于被授权 |
模型处理语义,脚本锁住不应漂移的事实,权限系统控制不可逆影响。Skill 的价值正是在任务层把这三类职责串成一条可检查的方法,而不是把其中任何一类神化成万能方案。
六、Prompt、Memory、MCP、Skill 各自解决什么
这几个词经常同时出现在 Agent 架构里,但它们回答的问题不同。
| 能力 | 保存或提供什么 | 主要回答的问题 | 不能替代什么 |
|---|---|---|---|
| Prompt | 当前任务的即时指令与上下文 | “这次希望我怎样回答?” | 可复用工作流与长期事实 |
| Memory | 过去的事实、偏好或经验 | “上次我们决定了什么?” | 工具接入和任务方法 |
| MCP | 可发现、可调用的工具与资源 | “现在能做什么?” | 步骤、验收和权限策略 |
| Skill | 完成一类任务的方法与边界 | “这件事应该怎样完成?” | 模型推理、外部工具本身和授权 |
在一个真实任务里,Memory 可以补充用户偏好,MCP 可以提供读写外部系统的工具,Skill 可以规定检查流程,Agent Loop 负责推进步骤,脚本负责验证局部结果。它们相互协作,但不应互相冒充。
七、从 demo 到生产,Skill 还要补什么
把 SKILL.md 写出来只是起点。一个错误的 Skill 可能让 Agent 更稳定地执行错误流程,所以生产环境至少还要补上几件事:
- 用真实样例检验它是否会在该触发时被发现;
- 用故意失败的样例确认验证器真的能拦住错误;
- 为规则变化保留版本和原因;
- 将写文件、发消息、发布、部署等高影响动作放在明确的权限边界后;
- 记录执行轨迹,把重复失败沉淀为下一版规则。
这些是从本文 demo 推导出的工程实践,不代表这个几十行的示例已经具备完整生产能力。它的职责只有一个:让“发现—加载—执行—验证”的边界变得可见、可运行、可讨论。
结尾:方法也应成为可复用的能力
第八话解决了工具如何标准化接入;第九话继续回答工具接入之后的事:怎样把经过验证的做法保存下来,让下一次任务不必从零猜测。
当 Agent 既能调用工具,又能复用方法时,新的追问自然出现:这些推理和行动方式又是怎样一步步演化出来的?下一篇,我们沿着 CoT、ReAct、Toolformer、Reflexion、Voyager 到 SWE-Agent 的线索继续往前看。
理解检验
- 如果一个 Skill 只有
SKILL.md,没有脚本和参考资料,它仍然可以成立吗?为什么? - 为什么“验证器通过”和“被验证对象通过”不能混为一谈?
- 当一个任务需要读取用户偏好、调用文件工具、并检查输出格式时,Memory、MCP、Skill 和脚本各自承担什么职责?
参考资料
- Agent Skills Specification:Skill 的最小目录、frontmatter、可选资源与渐进加载约定。
- Agent Skills Quickstart:发现、激活和执行的最小示例。
- GYA 第九话 demo:本文配套的最小 Skill Host;本文运行记录验证日期为 2026-08-22。

留言
欢迎分享你的想法。评论提交后会在审核通过后显示。