给 Agent 加能力,最常见的坑是"一个插件需求里混着五种职责":提醒检查清单、读取团队规范、执行发布命令、拦截危险参数、一键安装——如果全塞进一个高权限插件,改一句提示词也要重发代码;全写进 Markdown,真正危险的命令又只能依赖模型"记得不要做"。Pi v0.82.1 把这些职责拆成 Prompt Template、Skill、Tool、Extension 与 Package 五层。选型主线只有一句:用能够形成确定性闭环的最低权限层实现能力;只有缺少执行、生命周期或分发边界时才向上升级。
五种职责拆解
Agent 扩展改变的不是同一个对象:
| 形态 | 改变什么 |
|---|---|
| Prompt Template | 用户提交的任务文本 |
| Skill | 模型按需读取的知识、步骤和配套资源 |
| Tool | 具有 Schema、执行器和结果的结构化动作 |
| Extension | Runtime 的事件、策略、上下文或界面 |
| Package | 安装、锁定、过滤和分发上述资源 |
这不是功能强弱排行:Package 本身不会凭空增加运行机制;Skill 目录可带脚本,但脚本是否执行仍取决于模型和可用 Tool;Extension 注册的 Tool 则由 Runtime 直接承载。选型前先问五个问题:谁触发?需要什么权限?必须在哪个生命周期生效?正文是否应常驻上下文?能力要不要跨项目安装和更新?
四类机制的边界
Prompt Template:把重复意图做成显式入口
定义是 Markdown 片段,用户输入 /name 后文件内容经参数替换展开成普通 Prompt,再进入 Agent Loop。支持位置参数、默认值、切片以及 description、argument-hint 等元数据。适合"用户明确知道现在要做什么"的任务:审查暂存区、生成变更日志、按固定格式调查故障。
与把所有流程塞进 AGENTS 相比,Template 只在触发时占用上下文,来源容易审查。但它没有强制力:不能在 Tool 执行前检查真实参数,不能监听 Session,也不能保证模型逐项完成检查。若要求是"任何写入生产环境的命令都必须被拦截",继续润色 Prompt 不会获得 Runtime 保证。
Skill:把专业工作流做成渐进披露资源
Skill 是包含 SKILL.md 的目录,可带 scripts、references 与 assets。加载过程:启动时扫描名称与描述,把能力索引放进 System Prompt;任务匹配后模型再读取完整 SKILL.md——几十个低频流程不必全部常驻 Context。适合数据库迁移、PDF 处理、部署诊断等需要详细步骤和资料的工作。
两个容易被忽略的边界:
- 官方文档明确提醒,模型不一定总会自动读取匹配 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 和消息等事件。它能完成 Markdown 无法保证的事情:
- 在危险 Tool 真正执行前阻断或修改参数;
- 每次模型调用前裁剪或注入 Context;
- 对 Session 切换、Fork、Compaction 做决策;
- 把审计状态显示在 UI,而不塞进模型上下文;
- 把企业系统封装为结构化 Tool 或 Provider。
代价同样直接:Extension 能改变模型看到的内容,也能在宿主进程中执行代码(Package 中的 Extension 具有完整系统访问能力)。因此"写成 Extension 更可靠"只对确定性成立,不对安全性成立——它必须接受源码审计、权限隔离、事件回归和依赖治理。
Package:解决分发,不替代内部资源的边界
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 | 管理员/项目设置 | 分发确定性 | 依赖、更新与来源风险 |
实际决策从最低层向上走:
只是复用任务措辞? → Template
需要按需知识和配套文件? → Skill
需要结构化参数、取消和结果? → Tool
需要在模型之外强制策略或监听生命周期? → Extension
需要安装、锁版和团队共享? → 再用 Package 包装
“再用 Package 包装"很重要:Package 与前四项不是互斥选项,它是交付维度。
四个场景如何避免过度设计
- 固定发布检查清单:从 Template 开始。只有某项检查必须自动采集证据时,再把采集动作做成 Tool;只有所有发布动作都必须经过门禁时,才增加 Extension 拦截。
- 数据库迁移:通常用 Skill 承载步骤、回滚条件和参考资料,用 Tool 封装迁移系统的只读检查或提交动作。把凭据与执行逻辑直接放进 Skill 脚本,会让模型行动和权限边界难以分开。
- “禁止修改 .env 和 .git/”:不能只写 Skill——Skill 可以解释原因,真正的强制保护应在 Tool Gate、Extension 或操作系统权限层完成。Extension 也不是最终 Sandbox,敏感凭据和生产网络仍应在宿主层隔离。
- 团队共享工作流:最后才需要 Package。锁定来源和版本,只启用所需资源,并为每类资源保留独立审核结果。不要让"方便安装"变成"一次信任所有代码、指令和依赖”。
把分层落实为可验证的工程合同
自研 Harness 可以直接借用这套职责分离,但要把对象变成可验收合同:
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 安全、某个 Skill 一定被触发。把未知项保留下来,恰好也是分层扩展最重要的工程价值:每一层都能用自己的证据证明,而不是靠"插件能运行"替全部对象背书。