md-tools 是一堆脚本加说明。这一节开始,我们要把它「技能化」——让它成为一个 Pi 按需加载、专门干 markdown 处理的能力包。理解技能的工作原理,是封装的第一步。技能是什么
官方定义很准:技能(Skill)是自包含的能力包,agent 按需加载。 一个技能提供针对特定任务的专门工作流、安装说明、辅助脚本和参考文档。
对比一下你的 md-tools:
| md-tools 的零散做法 | 技能化之后 |
|---|---|
| 脚本散落 + 口头交代用法 | 一个目录 + SKILL.md + 脚本/文档 |
| 每次都要重新解释怎么做 | 按需加载,自带完整工作流 |
| 跟项目耦合 | 可复用、可共享、可跨项目 |
一句话:技能把「怎么做」固化成一个包,需要时 Pi 自己来取。
md-tools 的三个命令、安全预览规则、用法说明,统统收进一个 Skill 包里。以后任何项目里 Pi 遇到 markdown 处理需求,就能自动加载这个技能来干。技能是怎么工作的
官方文档把技能的运行机制讲得很清楚,四步:
- 启动时扫描:Pi 启动时扫描技能位置,提取每个技能的名字和描述
- 进系统提示词:可用技能以 XML 格式写进系统提示词
- 按需加载:当任务匹配时,agent 用
read读取完整的SKILL.md(注意:模型不一定总自动读,可用提示或/skill:name强制) - 照做执行:agent 按技能里的指令执行,用相对路径引用脚本和资源
关键是最后这步的「相对路径」:技能目录里的脚本、参考文档,用相对路径引用,这样整个包搬到哪都能跑。
渐进式披露:为什么技能能省上下文
技能有个核心设计叫渐进式披露(progressive disclosure):
只有技能的描述一直在上下文中;完整的指令按需才加载。
这非常省 token。Pi 不会把所有技能的内容全塞进提示词,只放一段简短描述。真正要用某个技能时,才把它的完整 SKILL.md 读进来。技能越多,这个设计越值钱。
技能加载的位置
官方列了一长串技能来源,分全局、项目、包等几类:
| 类别 | 位置 |
|---|---|
| 全局 | ~/.pi/agent/skills/ |
| 全局(共享) | ~/.agents/skills/ |
| 项目(需信任) | .pi/skills/ |
| 项目(祖先目录) | .agents/skills/(从 cwd 向上到 git 根) |
| 包 | 包的 skills/ 目录或 pi.skills |
| 设置 | settings.json 里的 skills 数组 |
| CLI | --skill(可重复) |
.pi/skills/ 属于项目级,要等项目被信任后才加载——正好接上 M01 讲的项目信任。
落地练习:确认你的技能能被发现
先别急着写完整技能,验证一下「发现」机制:
- 在
~/.pi/agent/skills/建一个测试目录md-tools-demo/,放一个极简SKILL.md(下一节细讲,这里先放名字和描述即可) - 启动 pi,看 TUI 顶部或
/skill:补全里是否能列出它 - 用
pi --no-skills启动一次,对比「开了 / 关了」技能发现的行为差异
怎么判断做对了?——启动后能在技能列表里看到
md-tools-demo;--no-skills后它消失。
卡住了怎么办? 看不到 → 确认放进了被扫描的目录、SKILL.md 文件在。不加载 → 若是 .pi/skills/,先确认项目已信任。不想每次手动 → 用 /skill:name 显式加载。
常见坑:以为技能是「一劳永逸」
最常见的误解是:写好技能,Pi 就会自动调用它。文档明确提醒:模型不一定每次都自动读取 SKILL.md。
所以别赌自动加载。要么在技能描述里写得很精准(提高命中率),要么用 /skill:name 或提示词强制它加载。技能是「准备好、可调用」,不等于「无条件自动生效」。
小结
- 技能是自包含、按需加载的能力包
- 工作流程:扫描描述 → 进系统提示词 → 按需读 SKILL.md → 照做执行
- 渐进式披露:描述常驻、指令按需,省 token
- 加载位置分全局、项目(需信任)、包、设置、CLI
- 别赌自动加载,必要时用
/skill:name强制
下一节,我们拆开一个真正的技能——SKILL.md 的结构和 frontmatter。