pi System Prompt 构成详解
pi 的 system prompt 采用分层拼装机制,启动时按固定顺序叠放各层,最终拼接为发送给 LLM 的完整系统提示。
拼装顺序
┌─────────────────────────────────────────────┐
│ ① 基础系统提示 (pi 内置) │
│ 角色、工具说明、行为准则、文档路径 │
│ ↓ 可被替换 │
│ ② SYSTEM.md (如存在) │
│ 完全替换①,而非追加 │
│ ~/.pi/agent/SYSTEM.md 或 .pi/SYSTEM.md │
│ ↓ │
│ ③ APPEND_SYSTEM.md (如存在) │
│ 追加在②之后 │
│ ↓ │
│ ④ 上下文文件 │
│ AGENTS.md / CLAUDE.md 全部拼接 │
│ 来源:全局 + 沿目录树向上收集 │
│ ↓ │
│ ⑤ 技能列表 (XML) │
│ 仅名称 + 描述,遵循 Agent Skills 规范 │
│ ↓ │
│ ⑥ 最终 System Prompt → 发送给 LLM │
└─────────────────────────────────────────────┘
工具 Schema 不在 system prompt 中
工具定义(read、write、edit、bash 及扩展注册的自定义工具)作为 API 请求的 tools 参数单独传递,不进入 system prompt 正文。system prompt 中只包含工具的简要描述说明。
各层详解
① 基础系统提示
pi 内置的角色定义块,包含:
- 角色陈述:
You are an expert coding assistant operating inside pi... - 工具概述:列出可用工具名及功能简介
- 行为准则:如何使用工具(用 bash 替代 cat/sed、用 read 查看文件、用 edit 做精确修改等)
- pi 文档路径:指向 pi 自身文档的绝对路径(供 agent 需要时查阅)
- 项目上下文容器:空
<project_context>标签,后续层内容填入其中
② SYSTEM.md — 完整替换
如果 ~/.pi/agent/SYSTEM.md 或 .pi/SYSTEM.md 存在,会彻底接管系统提示,基础提示被丢弃。
CLI 等价:--system-prompt <text>
适用场景:想要完全自定义 agent 角色和行为时。
③ APPEND_SYSTEM.md — 追加
在系统提示末尾追加内容(不论基础提示是否被 SYSTEM.md 替换)。
CLI 等价:--append-system-prompt <text>
适用场景:添加通用指令、输出格式要求等,不影响核心角色。
④ 上下文文件 — 全部拼接
pi 从 ~/.pi/agent/AGENTS.md 开始,沿着工作目录向上遍历(直到文件系统根或 git 仓库根),逐级收集沿途的 AGENTS.md 和 CLAUDE.md。所有找到的文件全部拼接(不是层级覆盖),包裹在 <project_context> 标签内。
拼接顺序(从上到下):
~/.pi/agent/AGENTS.md ← 全局行为规范
祖先目录/AGENTS.md ← 中间目录可能有也可能无
项目根/AGENTS.md ← 项目特定指令
实际案例:一个典型的配置可能包含两层上下文文件:
| 层级 | 内容 |
|---|---|
| 全局 | 行为准则(Think Before Coding、Simplicity First、Surgical Changes、Goal-Driven Execution)、工具偏好(uv/uvx、bun/bunx) |
| 项目 | 技能修改规则(只在 ./skills/ 中修改,不要在 ~/.pi/agent/skills/ 或 ~/.agents/ 中修改) |
两者拼接后同时注入,agent 同时遵守全局规范和项目规则。
禁用:--no-context-files / -nc
⑤ 技能列表 — 渐进式披露
pi 扫描所有技能位置,提取每个技能的 name 和 description(来自 SKILL.md 的 YAML frontmatter),以 XML 格式注入系统提示:
<available_skills>
<skill>
<name>librarian</name>
<description>Research open-source libraries with evidence-backed answers
and GitHub permalinks...</description>
<location>.../librarian/SKILL.md</location>
</skill>
<skill>
<name>pi-subagents</name>
<description>Delegate work to builtin or custom subagents with
single-agent, chain, parallel, async, forked-context...</description>
<location>.../pi-subagents/SKILL.md</location>
</skill>
</available_skills>
关键设计:只注入名称和描述,不注入完整技能内容。完整 SKILL.md 由 agent 按需通过 read 工具加载。这是渐进式披露——用最小上下文成本让 agent 知道"有什么可用",需要时才获取详情。
调用方式:
- 自动:agent 根据任务描述匹配并
read加载 - 手动:
/skill:name强制加载
技能来源优先级(低→高):
~/.pi/agent/skills/~/.agents/skills/.pi/skills/(项目).agents/skills/(项目及祖先目录)- pi 扩展包中的
skills/ - CLI
--skill <path>
扩展对 System Prompt 的影响
扩展注册的工具会出现在工具的简要描述中(第①层),但工具的完整 schema(参数定义等)不进入 system prompt,而是放在 API 请求的 tools 参数中。
扩展注册的技能会出现在技能 XML 中(第⑤层)。
pi 包的安装来源决定其技能注入的路径:
- npm 包:
~/.pi/agent/npm/node_modules/<包>/skills/ - git 包:
~/.pi/agent/git/<仓库>/skills/ - 项目级:
.pi/npm/或.pi/git/
查看实际 System Prompt
可以通过自定义扩展在交互式会话中查看拼装完成的 system prompt。
一个典型实现:
- 监听
before_agent_start事件,获取event.systemPrompt(这是拼接完成、即将发送的最终版本) - 注册命令(如
/system-prompt),以全屏 TUI overlay 展示 - 对内容做语法染色:章节标题加粗高亮、XML 标签弱化、技能名称强调
事件回调获取的 systemPrompt 与 ctx.getSystemPrompt() 的区别:前者是事件触发时已拼装完成的快照,后者是实时调用构建。
设计理念总结
| 原则 | 体现 |
|---|---|
| 分层拼接 | 多源上下文文件全部合并,不做层级覆盖 |
| 可选替换 | SYSTEM.md 可完全接管,不想接管就追加 |
| 渐进式披露 | 技能仅名称入 prompt,内容按需加载 |
| 工具分离 | 工具 schema 不进 system prompt,减少上下文占用 |
| 扩展驱动 | 基础提示极简,能力通过扩展/技能/包注入 |
总 Token 估算
一个典型的中等复杂度环境(全局 AGENTS.md + 项目 AGENTS.md + 2-3 个技能 + 若干扩展工具),system prompt 大约占用 4000-5500 token,在主流模型的 context window 中占比极小。