M01. 全景:Pi 为什么适合拿来学习#
学习 Agent 时,最容易陷入两个极端:只会调用模型的 demo,或者一上来就啃一个庞大框架。Pi 适合做中间的那座桥。它有可直接使用的编码 Agent,也把模型抽象、循环、工具、事件和会话拆成可以逐层阅读的代码。
1. 先建立三个观察角度#
Pi 同时是三种东西:
- 一个终端产品:启动后可以读文件、改文件、执行命令,并把过程呈现在终端里。
- 一份 Agent 教材:核心运行机制没有被大量业务平台代码淹没,适合顺着类型和事件追踪。
- 一套可嵌入的 SDK:你可以只使用模型层,也可以使用 Agent 核心或完整的 coding-agent 会话能力。
这三个身份不是宣传口号,而是源码组织方式的结果。终端产品需要 TUI 和会话;SDK 需要稳定的层间接口;教材价值来自每一层都能解释“输入是什么、输出是什么、谁拥有状态”。
2. 一次任务到底经过什么#
把“请检查这个项目”拆开,大致是:
用户 prompt
→ 会话构建当前上下文
→ 模型流式返回文本或 tool call
→ 工具验证并执行
→ tool result 回到消息历史
→ Loop 根据 stopReason 决定继续或结束
→ 事件被 UI、扩展和持久化层消费后续章节会分别打开每个方框。这里先记住一条主线:模型不直接改世界,Loop 也不直接理解业务;工具是动作边界,消息是数据边界,事件是观察与控制边界,会话是恢复边界。
3. 四个核心包的阅读地图#
| 包 | 解决的问题 | 阅读入口 |
|---|---|---|
pi-ai | 把不同供应商翻译成统一模型接口 | model、context、stream |
pi-agent-core | 驱动模型与工具之间的循环 | Agent、agent-loop |
pi-coding-agent | 组装编码工具、会话、扩展和 SDK | AgentSession、SessionManager |
pi-tui | 在终端中渲染文本和交互组件 | 组件、差分渲染、输入 |
前三个包像一条依赖链,pi-tui 则是平行的终端 UI 库。读源码时不要从最复杂的 CLI 入口开始;先从 pi-ai 的类型开始,再到 Loop,再看产品层如何接上持久化和 UI。
4. 这套设计刻意没有替你决定什么#
Pi 没有把所有 Agent 产品功能都硬编码成默认流程。计划、审批、子 Agent、外部服务集成等能力可以通过扩展或宿主应用加入。这种“少内置一些”的策略有代价:你必须自己做权限、恢复和观测。但它也让学习者能看清哪些是 Agent 的最小公约数,哪些只是某个产品的选择。
5. 推荐的源码阅读顺序#
第一阶段:沿一条消息走完
先读 M02–M06,回答“一个 prompt 怎样变成一次工具调用”。不要在第一遍试图记住每个类型字段;只追踪 Context、AgentMessage、tool call 和 tool result 的流向。
第二阶段:看系统如何被观察和维护
再读 M07–M10,回答“运行中的状态怎样被外部看到,历史太长怎么办,重启后怎么恢复”。这一步会把事件、上下文、压缩和会话树串成同一条生命周期。
第三阶段:开始改造
最后读 M11–M14,学习如何注册新工具、嵌入 headless session、插入运行时控制,以及为生产环境补齐安全和回归边界。
6. 你应该带走的学习方法#
- 先找类型和调用边界,再看具体实现。
- 每读一个模块,都写出它的输入、输出和持有的状态。
- 追踪失败路径:模型错误、工具错误、取消和压缩失败往往比成功路径更能说明设计。
- 把“产品行为”与“核心机制”分开。TUI 怎么显示,不等于 Loop 怎么运行。
- 对会变化的模型名、事件字段和扩展 API,永远回到官方文档核对。
7. 贯穿全系列的不变量#
后续阅读可以始终用四条不变量校验理解:模型层不依赖会话层;工具调用必须经过可验证的边界;事件用于传播状态而不是替代状态;会话历史只通过当前路径进入上下文。只要某个设计破坏其中一条,就需要说明这是有意的产品取舍,而不是顺手把职责混在一起。