Skip to main content

Pi 的设计哲学:核心极简、行为外置的 4 包架构(含延伸:为何这是理解 Agent Harness 的最佳学习样本)

· 14 min read

Pi 用一句话定义自己:核心要小,行为由扩展装配。本篇先看它最上层的哲学,再落到 4 个 npm 包的源码目录里。

  1. 核心极简:默认不内置 MCP、sub-agent、plan mode、to-do、权限弹窗
  2. Harness ≠ 模型:LLM 是发动机、Harness 是车辆系统——这一层直接决定成本与效果
  3. 两条路径:产品派(Claude Code / Codex)成品房 vs 框架派(Pi)毛坯房
  4. 双层扩展:Skill 改方法,Extension 改 Agent 自身运行方式
  5. 4 个 npm 包:pi-ai / pi-agent-core / pi-coding-agent / pi-tui,单向依赖
  6. 透明可读 → 自改造:Pi 自己读自己的扩展文档、自己写代码修改 Extension
  7. 同模型实测:同模型同任务,Pi / CC token 比 51%、耗时 ~80%
  8. 核心只做四件事:加载扩展、跑 agent 循环、读写 session 文件、提供 TUI

记忆点:Pi 卖的不是「帮你做好了一切」,而是「给你一块可改装的底盘」——也是一个「让你能看到 Agent 怎么跑的透明壳」。


设计哲学与包架构:Minimal Core

Pi 给出的答案是「核心极简、行为由扩展装配」,跟 Claude Code 那种「核心大而全、扩展只是补丁」的设计路线完全相反。本篇先看最上层的哲学、再落到 4 个 npm 包,最后补一段延伸——为什么这套极简是研究 Agent Harness 的最佳学习样本。

一句话定位

官方 README 给出的定义是:

Pi is a minimal terminal coding harness. It is designed to stay small at the core while being extended through TypeScript extensions, skills, prompt templates, themes, and pi packages.

关键词是 stay small at the core——核心要小、不能膨胀,所有「工作流级别的能力」都外移到扩展层。这是一个有意识的产品决策:默认不内置 MCP、不内置 sub-agent、不内置 plan mode、不内置 to-dos、不内置后台 bash、不内置权限弹窗——这些都可以作为扩展、或者借助容器/tmux 等外部工具实现。

Pi 核心只做四件事:

  • 加载扩展(extensions、skills、prompts、themes)
  • 跑 agent 循环
  • 读写 session 文件
  • 提供 TUI

其他——包括权限弹窗、plan mode、sub-agent、消息队列——全部由扩展层按需装配。

Harness ≠ 模型——为什么这层包装值得研究

很多人评估 Agent 时只看「用的哪个模型」,结论就是「Claude Code 用的是 Opus 4.5,所以它强」。这判断只对了一半。

更精确的拆解是这样的:

LLM(模型)是发动机;Harness 是发动机外面那一整套车辆系统——它负责组织上下文、提供工具、执行模型发起的操作、再把结果返回给模型。

每次 Agent 调用模型时送进去的内容里,包含:

  • 系统提示词
  • 工具定义
  • 项目规则
  • 历史消息
  • 过往工具返回结果

这些内容越多,多轮执行里反复进入上下文的 token 就越多,无关上下文拉长还会拖累模型的注意力。这意味着 Harness 的设计会 直接影响成本和效果,不是「穿在外面的透明壳」。

Pi 走的是把这个壳 做小、做透 的路线:默认 4 个工具(read / write / edit / bash)、系统提示词不到 1000 token、核心代码完全开源。这种「什么都不敢内置」的姿态让它成为一个 活的教学样本——打开它,就能看到 Agent 内部的循环。

跟其他 Coding Agent 的差异

维度PiClaude CodeOpenCode
核心大小极简,行为由扩展装配大而全,功能内置中等,模块化
MCP不内置(可作扩展)内置内置
Sub-Agent不内置(可作扩展)内置 Coordinator内置
权限系统不内置(靠容器化)内置多层权限内置
Plan Mode不内置内置内置
扩展机制TypeScript 模块 + 生命周期事件 + UIHooks + Skills + PluginsHooks
会话存储JSONL 树形结构,可分支JSONL 线性 + 内部状态JSONL
多 Provider内置统一抽象层主推 Anthropic内置
上手门槛高——需要自己组装扩展低——即开即用
演进方向保持极简越来越厚

最值得记住的是 安全模型 那一行:Pi 没有任何进程级沙箱,文档明确说「这是故意的」。详细分析见 Pi 的 Provider 抽象与安全模型 那篇。

两条相反的路径:成品房 vs 毛坯房

把视野放大一步,会发现 Agent 领域目前主要有 两条相反的路径

维度产品派框架派
代表Claude Code / CodexPi / opencode
默认能力多工具、安全机制、默认规则极少工具、零默认规则
用户上手即开即用需要自己组装
演进方向越来越厚保持极简
适合谁大多数人直接干活想搞懂 Agent 怎么跑的人

评论区对这种差异有个精辟概括——「明白了,毛坯房」。Pi 像毛坯房,自己加 Skill 自己加 Extension;Claude Code / Codex 像精装房,拎包入住,但想拆一面墙就难了。

两条路不矛盾,是为不同需求设计的。

如果你只关心完成手上的活,产品派更省心;如果你想理解 Agent 内部的运行时,框架派是更合适的入口。Pi 不试图覆盖所有人,它赌的是「搞懂 Agent 内部怎么跑」这件事有一个清晰的、最小的入口。

双层扩展机制:Skill 改方法,Extension 改 Agent 自己

Pi 的扩展机制分两层,但职责完全不同——这是它 最适合当学习样本 的结构原因:

Skill——按需加载的专业说明书。比如 REMOTION 视频制作 Skill,会告诉 Agent 怎么分析脚本、怎么设计分镜、怎么生成视频、怎么在最后验证结果。Agent 不遇到这类任务就不加载,对上下文零干扰。

Extension——通过代码接入 Pi 的运行过程,改变 它怎么接收输入、调用工具、显示状态、输出结果。可以:

  • 增删工具
  • 接入外部服务
  • 改终端界面
  • 给危险命令加权限确认
  • 加新交互方式(语音、IM、Webhook 等)

要改动系统提示、改造工具集合、换交互形态,写一个 Extension 就行。

简单概括:Skill 是 Agent 的方法论,Extension 是 Agent 的器官。

理解这两层的区别,再去看 Claude Code / Codex 上的 Skills、Slash Commands、Hooks、Harness 设置,就不会混在一起——它们其实是同一个 Harness 设计哲学的不同实现。

4 个 npm 包

仓库顶层是 monorepo(pi-mono),核心代码拆成 4 个 npm 包:

包名路径职责
@earendil-works/pi-aipackages/ai统一多 provider LLM API
@earendil-works/pi-agent-corepackages/agentAgent runtime,工具调用 + 状态管理
@earendil-works/pi-coding-agentpackages/coding-agent交互式 coding agent CLI
@earendil-works/pi-tuipackages/tui终端 UI 库,差分渲染

依赖方向是单向的:

pi-ai 是最底层——纯 LLM 适配层,没有任何 agent 概念;pi-agent-core 在它之上引入 agent 循环和工具调用;pi-tui 是独立的 UI 库,被 pi-coding-agent 用来渲染交互界面;最上层的 pi-coding-agent 把前面三者缝合成 CLI 产品。

这种分层的好处是按需引入:你只想在自己的应用里嵌入一个对话界面?引 pi-ai。你想搭一个非交互式 agent?引 pi-agent-core。你想直接拿 CLI 用?引 pi-coding-agent。每一层都是独立 npm 包,没有「整套大而全」的强耦合

源码目录导航

packages/coding-agent/ 是大部分用户最关心的包。进入后关键目录是:

packages/coding-agent/
├── docs/ # 文档源文件
├── examples/
│ └── extensions/ # 扩展示例
├── src/
│ ├── cli/ # CLI 入口、命令解析
│ ├── core/
│ │ ├── session-manager.ts # SessionManager(树形)
│ │ ├── messages.ts # 扩展消息类型
│ │ ├── compaction/ # 压缩与分支摘要
│ │ │ ├── compaction.ts
│ │ │ ├── branch-summarization.ts
│ │ │ └── utils.ts
│ │ ├── extensions/ # 扩展运行时 + 类型
│ │ └── ... # 工具、auth、model registry
│ ├── modes/ # 运行模式(interactive / rpc / json / print)
│ └── index.ts # createAgentSession 等 SDK 入口
├── package.json
└── npm-shrinkwrap.json

后续文章会用到的关键文件位置:

功能源文件
SessionManagersrc/core/session-manager.ts
扩展消息类型src/core/messages.ts
自动压缩src/core/compaction/compaction.ts
分支摘要src/core/compaction/branch-summarization.ts
扩展事件类型src/core/extensions/types.ts
自定义 compaction 示例examples/extensions/custom-compaction.ts
自定义 provider 示例examples/extensions/custom-provider-gitlab-duo/
基础消息类型packages/ai/src/types.ts
AgentMessage 联合类型packages/agent/src/types.ts
Provider env 映射packages/ai/src/env-api-keys.ts

为什么是 Minimal Core

读源码时很容易感觉 Pi 故意「什么都不做」:没有权限弹窗、没有 plan mode、没有内置 to-do——这些 Claude Code 都默认有。但这背后是有意为之的产品判断,四条理由同时成立才把它推到「核心极简」这一端。

第一,把决策权推给扩展层。 工作流级别的偏好(要不要 plan mode?要不要 to-do?消息队列是 steer 还是 followUp?)本质上是不同团队、不同场景下的不同选择。Pi 选择不替你做决定——你要 plan mode,写一个扩展;你要后台 bash,写一个扩展;你要权限弹窗,写一个扩展。

第二,让核心保持可读、可演进。 Claude Code 的 prompts.ts 911 行、main.tsx 785KB 单文件,是「大而全」的代价——任何修改都要触碰核心。Pi 的核心保持极简,意味着扩展可以独立版本化、独立废弃、独立替换,核心不需要承担所有兼容责任

第三,匹配 Pi 自身的安全哲学。 「无沙箱」的设计如果加上内置权限弹窗,会给人「agent 是受控的」错觉,反而危险。把隔离责任彻底推给 OS / 容器 / 虚拟机,让用户清楚意识到这是无保护的进程——这才跟「明确告知无安全边界」的安全模型一致。

第四,保留透明可读、才能支持自改造。 Pi 把代码写小、把 hook 全部显式化,是因为它要让 Agent 自己也能读懂自己的扩展文档、并写代码改自己。这是下一节要展开的「元能力」前提——核心一旦变厚,Agent 也读不透自己,更谈不上自改造。

极简的代价必须正视

新用户第一次跑 pi,看到的只是一个最小可用的 CLI;想要 plan mode、想要 to-do、想要 IDE 集成、想要权限弹窗,都得自己去装扩展或者写扩展。上手门槛比 Claude Code 高一截——这是「可改装的底盘」必然要付的代价。

Pi 的元能力:自改造

Pi 最反常识的一点是:不用亲手写 Extension 代码

告诉 Pi 想增加什么功能(比如「加一个中文语音交互,我说完 Pi 自动听、写、念结果」),Pi 会自己读自己的扩展文档、按规范生成或修改 Extension、改完重载立刻可测。

整个循环在终端里就能跑完:

  1. 自然语言描述要什么
  2. Pi 阅读扩展文档,按规范生成 Extension 代码
  3. 重载,验证
  4. 不满意继续描述,Pi 继续改

这件事看起来是花活,背后指向一个 值得重视的结论

当 Agent 能阅读自己的运行时文档并改造自身运行时,它已经具备了一定程度的「元能力」。理解这条边界,对评估下一代 Agent 的能力上限非常关键。

而把这件事 做得很透明 的,目前只有 Pi 这一类极简 Harness——你能在终端里看到 Pi 在读文档、在调工具、在 diff 文件、在写代码。其他 Agent 大多把这些内部过程打包进黑盒了。

Pi 不是「唯一一个值得用的 Agent」——它是最 透明 的一个。透明了,才能学得会。

极简不是玄学:同模型实测对比

极简不只停在哲学,也有数据支撑。同一个 REMOTION 视频制作任务、相同模型、相同思考强度下:

维度PiClaude CodePi / CC
平均 token(含缓存)2.82M5.52M51%
平均耗时8.75 min11 min~80%
视频效果极少元素堆叠偶尔堆叠Pi 更稳

底层模型、任务都不变,只换 Harness,token 就砍掉近一半。测试样本有限不能外推所有任务,但它 实证了 Harness 真在影响成本 这一直觉。

极简带来的取舍必须正视

Pi 默认没有任何权限确认机制——删除文件、执行高危命令、访问敏感路径都不会拦截。初次使用必须先装一套权限保护扩展,把边界画清楚。这点是必须自己补的。

学 Pi 之后,看 Claude Code / Codex 不一样

把 Pi 内部循环捋清楚,再去看其他 Agent,会发现 所有 Agent 本质都在重复同一个循环

用户输入 → 组织上下文 → 模型决策 → 工具执行 → 结果回填 → 循环判断

Claude Code / Codex 把这个循环里很多环节做成了默认规则——安全策略、MCP server、Sessions、Sub-agent、权限弹窗——你看到的是一个厚重的成品。但只要把每一层都「拆解到 Pi 这个层级」,就会明白:

  • Skills 是 Skill 的工程化版本
  • Slash Commands / Hooks 是 Extension 的命令 / 事件子集
  • Sub-agent 是通过 Extension 实现的角色拆分
  • MCP server 在 Pi 里要靠 Extension 自己接入
理解了 Pi 这一层,再去用 Claude Code / Codex / opencode / Claude Agent SDK 都不会瞎试。

什么时候学 Pi、什么时候直接用成品

目标推荐路径
只想让手上的活跑起来Claude Code / Codex,开箱即用
想搞懂 Agent 内部怎么跑Pi 是首选学习样本
需要深度定制、改写 Agent 自身Pi + Extension
嵌入到自己的应用 / 自动化流程Pi SDK
默认安全机制、权限边界Claude Code / Codex(内置更厚)

学 Pi 不影响用 Claude Code / Codex。Pi 是 理解 Agent 的脚手架,成品的生产效率还得靠成熟产品。两条路并行走,是当前 Agent 时代比较稳的姿态。

References

  1. 有了 Claude Code 和 Codex,Pi Agent 为什么依然值得关注? —— YangAgent, 哔哩哔哩, 2026-07-13
  2. Pi Agent 官网
  3. Pi Agent GitHub 仓库

下一篇讲 Session 设计。Pi 把「会话」这件事做成了 JSONL 树形结构,而不是 Claude Code 那种近似线性的内部状态。这是 Pi 最核心的数据结构创新,也是后续所有能力(分支、回滚、压缩)的基础。