给 Pi 增加能力时,应该写 Prompt、Skill、Tool 还是 Extension?
团队想统一发布流程,于是有人提议"写一个插件":它要提醒检查清单、读取团队规范、 执行发布命令、拦截危险参数,还要让每个人一键安装。听起来只是一个需求,实际上混合了 五种职责。如果全部塞进一个高权限插件,改一句提示词也要重发代码;如果全部写进 Markdown,真正危险的命令又只能依赖模型"记得不要做"。
Pi v0.82.1 把这些职责拆成 Prompt Template、Skill、Tool、Extension 与 Package。 本文的主线不是介绍五个名词,而是回答一个工程决策:用能够形成确定性闭环的最低 权限层实现能力;只有缺少执行、生命周期或分发边界时才向上升级。

一、先把一个"插件需求"拆成五种变化
Agent 扩展可能改变的不是同一个对象:
text
Prompt Template:改变用户提交的任务文本
Skill:提供模型按需读取的知识、步骤和配套资源
Tool:提供具有 Schema、执行器和结果的结构化动作
Extension:改变 Runtime 的事件、策略、上下文或界面
Package:安装、锁定、过滤和分发上述资源
这不是功能强弱排行。Package 本身不会凭空增加一种运行机制;Skill 目录可以附带脚本, 但脚本是否执行仍取决于模型和可用 Tool;Extension 注册的 Tool 则由 Runtime 直接承载。
因此选型前先问五个问题:谁触发?需要什么权限?必须在哪个生命周期生效?正文是否应 常驻上下文?能力要不要跨项目安装和更新?

二、Prompt Template:把重复意图做成显式入口
固定文档把 Prompt Template 定义为 Markdown 片段。用户输入 /name 后,文件内容经过 参数替换,展开成普通 Prompt,再进入 Agent Loop。它支持位置参数、默认值、切片以及 description、argument-hint 等元数据。
它适合"用户明确知道现在要做什么"的任务:审查暂存区、生成变更日志、按固定格式调查 故障。相比把所有流程塞进 AGENTS,Template 只在触发时占用上下文,来源也容易审查。
但它没有强制力。Template 不能在 Tool 执行前检查真实参数,不能监听 Session,也不能 保证模型逐项完成检查。若要求是"任何写入生产环境的命令都必须被拦截",继续润色 Prompt 并不会获得 Runtime 保证。

三、Skill:把专业工作流做成渐进披露资源
Skill 是包含 SKILL.md 的目录,还可以带 scripts、references 与 assets。固定文档描述 的加载过程是:启动时扫描名称与描述,把能力索引放进 System Prompt;任务匹配后,模型 再读取完整 SKILL.md。这使几十个低频流程不必全部常驻 Context。
它适合数据库迁移、PDF 处理、部署诊断等需要详细步骤和资料的工作。与 Template 相比, Skill 可由模型根据描述选择,也能通过 /skill:name 强制载入;与 Extension 相比,它的 核心仍是指令与资源组织,不会直接注册 Runtime Hook。
这里有两个容易被忽略的边界:
- 官方文档明确提醒,模型不一定总会自动读取匹配 Skill;"被发现"不是"被执行"。
- Skill 可以指示模型运行随附脚本,因此"不是 TypeScript 插件"不等于没有供应链风险。
所以 Skill 的验收至少分为发现、正文读取、脚本调用和结果验证四层,不能只看到它出现在 能力列表里就宣称流程已生效。

四、Tool:当动作需要结构化参数与可控执行
Tool 经常被误认为独立的安装形态。在 Pi 中,自定义 Tool 通常由 Extension 通过 registerTool() 注册;概念上仍应单独讨论,因为它承担的是动作合同。
一个 Tool 至少要定义名称、描述、参数 Schema 与执行器,还可处理取消信号、增量更新、 结果渲染和 Prompt Guidelines。它比"让模型拼一条 Shell 命令"多出三种确定性:参数可 校验,执行生命周期可观察,结果可结构化返回。
如果能力只是"按照这份步骤做代码审查",Skill 足够;如果能力是"用 project、env、 revision 三个字段调用部署系统,并返回 deployment_id",就应提供 Tool。反过来,不能 因为 Tool 更像工程代码,就把所有知识都压进 Tool 描述,那会重新制造上下文膨胀。
五、Extension:只有 Runtime 必须介入时才升级
Extension 是在 Pi 进程内执行的 TypeScript 模块。固定文档显示,它可以注册 Tool、 Command、快捷键、Flag 与 Provider,也可以处理 before_agent_start、context、 tool_call、Session 和消息等事件。
这让 Extension 能完成 Markdown 无法保证的事情:
- 在危险 Tool 真正执行前阻断或修改参数;
- 每次模型调用前裁剪或注入 Context;
- 对 Session 切换、Fork、Compaction 做决策;
- 将审计状态显示在 UI,而不塞进模型上下文;
- 把企业系统封装为结构化 Tool 或 Provider。
代价同样直接。Extension 能改变模型看到的内容,也能在宿主进程中执行代码。官方 Packages 文档明确说明 Package 中的 Extension 具有完整系统访问能力。因此,"写成 Extension 更可靠"只对确定性成立,不对安全性成立;它必须接受源码审计、权限隔离、 事件回归和依赖治理。

六、Package:解决分发,不替代内部资源的边界
Pi Package 可以从 npm、Git 或本地路径安装,并通过 package.json 的 pi 字段或约定 目录声明 Extensions、Skills、Prompt Templates 与 Themes。版本或 Git Ref 可以固定, Settings 还可以过滤实际加载的资源。
Package 因而解决的是一组交付问题:来源、版本、依赖、安装位置、启用范围与更新。它不 会把 Extension 降权,也不会把 Skill 变成确定执行。过滤某个 Extension 只能减少加载面, 不能为已加载代码创建 Sandbox;固定版本只能保证内容一致,不能证明内容可信。
一个团队发布包可以同时包含发布 Template、操作 Skill、审计 Tool 和拦截 Extension。 审核时仍要逐类判断,而不能因为它们来自同一个 Package 就共享一条"已安装通过"。

七、用五维矩阵完成选型
| 需求 | 首选 | 触发主体 | 需要的确定性 | 主要风险 |
|---|---|---|---|---|
| 重复的审查或发布指令 | Prompt Template | 用户 | 低,允许模型解释 | 提示注入、步骤遗漏 |
| 按需专业流程与资料 | Skill | 模型或用户 | 中,需单独验执行 | 恶意指令、脚本供应链 |
| 稳定调用业务动作 | Tool | 模型 | 高,参数和结果结构化 | 执行权限、接口副作用 |
| 拦截命令或监听生命周期 | Extension | Runtime | 高,必须强制 | 任意代码、上下文篡改 |
| 跨团队安装上述资源 | Package | 管理员/项目设置 | 分发确定性 | 依赖、更新与来源风险 |
实际决策可以从最低层向上走:
text
只是复用任务措辞? → Template
需要按需知识和配套文件? → Skill
需要结构化参数、取消和结果? → Tool
需要在模型之外强制策略或监听生命周期? → Extension
需要安装、锁版和团队共享? → 再用 Package 包装
"再用 Package 包装"很重要:Package 与前四项不是互斥选项,它是交付维度。

八、四个场景如何避免过度设计
固定发布检查清单应从 Template 开始。只有当某项检查必须自动采集证据时,再把采集动作 做成 Tool;只有当所有发布动作都必须经过门禁时,才增加 Extension 拦截。
数据库迁移通常用 Skill 承载步骤、回滚条件和参考资料,用 Tool 封装迁移系统的只读检查 或提交动作。把凭据与执行逻辑直接放进 Skill 脚本,会让模型行动和权限边界难以分开。
"禁止修改 .env 和 .git/"不能只写 Skill。Skill 可以解释原因,真正的强制保护应在 Tool Gate、Extension 或操作系统权限层完成。Extension 也不是最终 Sandbox,敏感凭据和 生产网络仍应在宿主层隔离。
团队共享工作流最后才需要 Package:锁定来源和版本,只启用所需资源,并为每类资源保留 独立审核结果。不要让"方便安装"变成"一次信任所有代码、指令和依赖"。

九、把分层落实为可验证的工程合同
自研 Harness 可以直接借用这套职责分离,但要把对象变成可验收合同:
yaml
capability: release
intent:
type: prompt_template
owner_triggered: true
knowledge:
type: skill
disclosure: on_demand
action:
type: tool
schema_version: v2
policy:
type: extension_hook
enforced_at: before_tool_execute
distribution:
type: package
source: pinned
相应测试也应拆开:Template 做参数展开快照;Skill 做发现、读取与脚本边界测试;Tool 做 Schema、取消、幂等与副作用测试;Extension 做事件顺序、阻断和 Context Diff;Package 做来源、锁版、过滤与依赖清单验证。
更简单的替代方案永远应被保留:如果操作系统只读权限就能阻止写入,就不要先实现复杂 Hook;如果一页模板足以稳定完成任务,就不要引入可执行 Package。最小权限实现通常也 是最容易回滚、审计和迁移的实现。

十、事实边界与版本漂移
本文锁定 Pi v0.82.1 / b4f2936。截至 2026-08-11,远端 Tag 已出现 v0.84.1,所以 字段、加载位置和事件集合在使用前仍需按目标版本刷新。本文没有安装第三方 Package、 没有运行真实 Extension,也没有测量模型自动选择 Skill 的成功率。
能确认的是固定文档所定义的机制与权限边界;不能确认的是某个团队 Package 安全、某个 Skill 一定被触发,或示例在你的 Runtime 中已通过。把这三类未知项保留下来,恰好也是 分层扩展最重要的工程价值:每一层都能用自己的证据证明,而不是靠"插件能运行"替全部 对象背书。