第 02 模块 · 1 节

理解技能与工作原理

《Pi 进阶实战》02 自定义技能 Skills · 本节时长 32 分钟

贯穿项目入门课你写的 md-tools 是一堆脚本加说明。这一节开始,我们要把它「技能化」——让它成为一个 Pi 按需加载、专门干 markdown 处理的能力包。理解技能的工作原理,是封装的第一步。

技能是什么

官方定义很准:技能(Skill)是自包含的能力包,agent 按需加载。 一个技能提供针对特定任务的专门工作流、安装说明、辅助脚本和参考文档。

对比一下你的 md-tools

md-tools 的零散做法 技能化之后
脚本散落 + 口头交代用法 一个目录 + SKILL.md + 脚本/文档
每次都要重新解释怎么做 按需加载,自带完整工作流
跟项目耦合 可复用、可共享、可跨项目

一句话:技能把「怎么做」固化成一个包,需要时 Pi 自己来取。

贯穿项目我们最终要把 md-tools 的三个命令、安全预览规则、用法说明,统统收进一个 Skill 包里。以后任何项目里 Pi 遇到 markdown 处理需求,就能自动加载这个技能来干。

技能是怎么工作的

官方文档把技能的运行机制讲得很清楚,四步:

  1. 启动时扫描:Pi 启动时扫描技能位置,提取每个技能的名字和描述
  2. 进系统提示词:可用技能以 XML 格式写进系统提示词
  3. 按需加载:当任务匹配时,agent 用 read 读取完整的 SKILL.md(注意:模型不一定总自动读,可用提示或 /skill:name 强制)
  4. 照做执行: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 讲的项目信任。


落地练习:确认你的技能能被发现

先别急着写完整技能,验证一下「发现」机制:

  1. ~/.pi/agent/skills/ 建一个测试目录 md-tools-demo/,放一个极简 SKILL.md(下一节细讲,这里先放名字和描述即可)
  2. 启动 pi,看 TUI 顶部或 /skill: 补全里是否能列出它
  3. pi --no-skills 启动一次,对比「开了 / 关了」技能发现的行为差异

怎么判断做对了?——启动后能在技能列表里看到 md-tools-demo--no-skills 后它消失。

卡住了怎么办? 看不到 → 确认放进了被扫描的目录、SKILL.md 文件在。不加载 → 若是 .pi/skills/,先确认项目已信任。不想每次手动 → 用 /skill:name 显式加载。


常见坑:以为技能是「一劳永逸」

最常见的误解是:写好技能,Pi 就会自动调用它。文档明确提醒:模型不一定每次都自动读取 SKILL.md

所以别赌自动加载。要么在技能描述里写得很精准(提高命中率),要么用 /skill:name 或提示词强制它加载。技能是「准备好、可调用」,不等于「无条件自动生效」。


小结

  1. 技能是自包含、按需加载的能力包
  2. 工作流程:扫描描述 → 进系统提示词 → 按需读 SKILL.md → 照做执行
  3. 渐进式披露:描述常驻、指令按需,省 token
  4. 加载位置分全局、项目(需信任)、包、设置、CLI
  5. 别赌自动加载,必要时用 /skill:name 强制

下一节,我们拆开一个真正的技能——SKILL.md 的结构和 frontmatter。