跳转到内容

Pi 1.3.0:学习路线

这门课的目标:不是背 Pi 的 API,也不是通读每一行源码,而是建立一套能迁移到任何 Agent 项目的完整心智模型——知道一个 Agent 为什么这样分层、上下文如何流动、工具如何被安全执行、系统如何扩展和演进。

适合谁:会一点 TypeScript、能在命令行运行项目,但还没有系统理解 Agent 的读者。

源码目录:$PI_SRC,固定在 v1.3.0(71023aec)。 开发区:$PI_DEV,跟上游开发线时使用;阶段 1–8 不需要改这里。 总览:先读介绍与整体架构,把本清单当路线图,再按阶段读详解。


一、先建立总图:Agent 到底是什么

跳转到“一、先建立总图:Agent 到底是什么”

一句话:Agent 是一个会“反复做决定”的程序。 它把用户目标、历史记录、系统提示和工具说明交给模型;模型决定是回答,还是调用工具;工具结果回到上下文后,模型再决定下一步,直到任务完成。

用户或程序
│
▼
入口层:TUI / print / JSON / RPC / SDK
│ 输入和输出
▼
应用层:会话编排、工具、扩展、资源、模型选择
│ 把“这次要做什么”整理成一次运行
▼
引擎层:循环(问模型 ↔ 执行工具)
│ 统一格式的请求
▼
模型供应商:Anthropic / OpenAI / Google / …

旁边还有一份持续写入的会话账本。它记录发生过什么;下一次请求前,系统会从当前活动分支重建一份“模型可见的对话历史”,也就是投影。

任何 coding agent 都可以拆成七块。学习 Pi,就是看这七块如何互相配合:

功能块 要回答的问题 Pi 中的主要位置 对应阶段
循环 何时问模型、执行工具、继续或停止? packages/agent 2
上下文 每次到底给模型看什么? 会话树、投影、压缩、系统提示词 3
工具 模型能对世界做什么?如何校验和执行? packages/coding-agent/src/core/tools 4
模型接入 如何统一不同厂商的 API 和凭据? packages/ai 5
扩展 新能力如何在不改核心的情况下长出来? 扩展、技能、MCP、codemode 6
界面 同一引擎如何同时服务人、脚本和程序? TUI / print / JSON / RPC / SDK 7
工程 如何让改动可靠、可测试、可发布? 测试、check、构建、发布流程 8

三条贯穿全系统的纵线

跳转到“三条贯穿全系统的纵线”

除了七块,还要一直带着这三个问题:

  1. 事件是怎么流动的? 模型增量、工具状态、消息落盘都通过事件通知外部;界面只是事件的消费者。
  2. 信任边界在哪里? 工具和扩展以 Pi 进程的系统权限运行;项目信任和容器决定“它能碰什么”。
  3. 成本从哪里来? 历史、工具结果、技能说明都会占上下文;压缩、截断和懒加载都是在控制成本和质量。

二、整门课只围绕一条主线:一次请求的旅程

跳转到“二、整门课只围绕一条主线:一次请求的旅程”

后面每一章都在拆这条线中的一段:

输入
→ 入口层交给 AgentSession
→ 检查命令、展开模板、排队、认证
→ 准备一次运行:压缩检查、扩展钩子、起始消息
→ Agent 循环:重建上下文 → 请求模型 → 执行工具 → 再请求
→ 消息与工具结果写入会话树
→ agent_end:底层循环结束
→ agent_settled:没有自动工作,真正空闲

你需要能随时回答四个问题:

  1. 这次请求从哪里进来? 界面、脚本还是外部程序?
  2. 模型这次看到什么? 当前活动分支经过压缩和投影后得到的内容。
  3. 模型做了什么? 只回答,还是调用工具?工具结果如何回到上下文?
  4. 系统何时真正停止? agent_end 和 agent_settled 不是一回事。

能沿着这条线解释每个部件,才算真正理解 Agent;只记住文件名不算。


三、怎么学:每章都走同一个五步循环

跳转到“三、怎么学:每章都走同一个五步循环”

第 1 步:先用自己的话回答本章问题

跳转到“第 1 步:先用自己的话回答本章问题”

比如阶段 3 的问题不是“会话文件有哪些字段”,而是:

模型本身不记事,Pi 为什么还能连续对话?每次到底发什么给它?

先写下你的直觉答案,再去读材料。带着问题读,比从目录开始读有效得多。

每一章至少产出一张图:请求流、循环状态机、树与投影、工具生命周期、扩展点、接口选型。图不必漂亮,但必须能让你不看代码讲出关系。

第 3 步:到代码里验证

跳转到“第 3 步:到代码里验证”

只追本章相关的路径,不要从仓库根目录开始通读。每个概念都要落到一个具体对象或函数:

  • 循环:runLoop、turn_start、turn_end
  • 上下文:会话 entry、活动分支、压缩、投影、convertToLlm
  • 工具:工具定义、参数校验、执行、结果回填
  • 模型:Model、StreamFunction、provider 适配器
  • 扩展:贡献点、事件钩子、资源加载
  • 界面:事件流、JSONL、RPC、SDK

第 4 步:做一个小实验

跳转到“第 4 步:做一个小实验”

每章都要有一个能跑或能验证的动作:用 JSON 看一次事件、写一个最小循环、从会话树推导一次上下文、写一个工具、配一个模型、写一个扩展、跑一次接口、改一个测试。

合上文档,用 3–5 分钟讲给“三个月后的自己”听。讲不清的地方,就是下一轮要回去补的地方。

学习的敌人不是难,而是只读不验证、只记名词不建模型、只跟着步骤走却不问为什么。 这门课用“问题 → 图 → 代码 → 实验 → 复述”反复拆掉这三个坏习惯。


四、阶段路线:每一阶段只解决一个大问题

跳转到“四、阶段路线:每一阶段只解决一个大问题”

阶段 0 · 先让系统真实跑起来【准备】

跳转到“阶段 0 · 先让系统真实跑起来【准备】”

问题:源码版能不能在本机完整工作? 你要得到:能运行交互模式和非交互模式;知道版本、模型数据和基本目录。 产出:一次成功的 -p 任务,一次成功的交互对话。 为什么先做:没有真实行为,后面的所有概念都会变成纸上谈兵。

阶段 1 · 系统地图:一条请求如何穿过 Pi【核心】

跳转到“阶段 1 · 系统地图:一条请求如何穿过 Pi【核心】”

问题:Pi 有哪些层?谁把输入交给谁?事件如何返回? 你要得到:能用一张图讲清「界面 → AgentSession → 循环 → 模型/工具 → 会话账本」。 产出:包依赖图 + 请求时序图 + 一段 JSON 事件观察记录。 关键区别:agent 是循环引擎,coding-agent 是完整产品;AgentSession 管运行,SessionManager 管账本。

阶段 2 · 循环:Agent 如何从一次回答变成多轮行动【核心】

跳转到“阶段 2 · 循环:Agent 如何从一次回答变成多轮行动【核心】”

问题:turn 的边界在哪里?有工具结果时为什么自动继续?中途插话和停止怎么处理? 你要得到:画出包含 steer、follow-up、abort 的循环状态机;写出一个最小 agent loop。 产出:状态机图 + 最小循环代码 + 两条事件轨迹的对照。 核心认识:模型请求无状态;工具结果必须作为新消息回到上下文,循环才有“下一步”。

阶段 3 · 上下文:模型每次到底看到什么【核心】

跳转到“阶段 3 · 上下文:模型每次到底看到什么【核心】”

问题:对话如何存成树?压缩、投影和模型消息是什么关系? 你要得到:能从一棵会话树推导出下一次请求的上下文,并解释为什么压缩不删除原文。 产出:一份「会话树 → 活动分支 → 压缩 → 投影 → 模型消息」的推导练习。 关键区别:会话树保存事实,压缩记录一段摘要,投影是每次请求临时生成的可视历史。

阶段 4 · 工具:模型如何影响真实世界【核心】

跳转到“阶段 4 · 工具:模型如何影响真实世界【核心】”

问题:工具如何暴露、校验、执行和回填?怎样防止一次工具调用毁掉工作区? 你要得到:讲清工具生命周期;理解参数校验、执行方式、输出截断、结果回填和人类可观测性的分工。 产出:一个可用的自定义工具 + 一份工具风险清单。 核心认识:工具是 Agent 的手脚,也是最大的风险边界;错误应成为可回填的结果,而不是让会话崩溃。

阶段 5 · 模型接入:如何把不同厂商变成一套接口【进阶】

跳转到“阶段 5 · 模型接入:如何把不同厂商变成一套接口【进阶】”

问题:OpenAI、Anthropic、Google 的协议差异被谁吸收?模型能力、价格和凭据从哪里来? 你要得到:画清 provider → 模型目录 → 认证 → 统一流式事件的关系;能配置一个自定义模型或 provider。 产出:一张「厂商事件 → 统一事件」对照表 + 一次自定义 provider 配置。 核心认识:协议不等于厂商;很多厂商可以复用同一种 API 协议,循环不应该知道厂商细节。

阶段 6 · 扩展:能力如何在不改核心的情况下长出来【进阶】

跳转到“阶段 6 · 扩展:能力如何在不改核心的情况下长出来【进阶】”

问题:工具、命令、渲染器、技能、MCP 和 codemode 分别在哪一层扩展?什么时候该进核心,什么时候该做扩展? 你要得到:能按需求选择扩展点;理解技能按需加载、MCP 外部工具和 codemode 沙箱的定位。 产出:一个扩展或技能,并说明它为什么不应该直接改核心。 核心认识:核心稳定,能力向外生长;扩展不是“附加功能”,而是产品架构的一部分。

阶段 7 · 界面:同一引擎如何服务人、脚本和程序【进阶】

跳转到“阶段 7 · 界面:同一引擎如何服务人、脚本和程序【进阶】”

问题:TUI、print、JSON、RPC、SDK 有什么区别?什么时候该用哪一种? 你要得到:能根据“人看、脚本取结果、程序看过程、程序双向控制、进程内嵌入”做选型。 产出:一个 JSON 事件处理脚本 + 一个 SDK 或 RPC 最小客户端。 核心认识:引擎不依赖界面;所有形态共享同一套会话和事件,只是输入输出方式不同。

阶段 8 · 工程:如何让改动可信、可持续【核心】

跳转到“阶段 8 · 工程:如何让改动可信、可持续【核心】”

问题:一个 Agent 项目怎样测试、检查和发布,才能让改动不破坏原有行为? 你要得到:理解 faux provider、测试隔离、npm run check 的关卡和发布边界。 产出:一次带测试的规范小改动,或一份可复现的验证记录。 核心认识:Agent 的输出不确定,但工程系统必须确定;测试要把模型替换成可控的假实现。

阶段 9 · 综合重建:把七块组装成自己的 Agent【实战】

跳转到“阶段 9 · 综合重建:把七块组装成自己的 Agent【实战】”

问题:如果从零设计一个 Agent,你会怎样组合循环、上下文、工具、模型、接口和工程? 你要得到:不再依赖 Pi 的文件名,能独立画出自己的设计并解释取舍。 产出:一个 mini agent + 一份设计说明 + 一次可复现的端到端请求追踪。 核心认识:真正的掌握不是“看懂 Pi”,而是能把同样的结构迁移到另一个项目。


完整路线建议 6–8 周,每周 8–10 小时。时间是估算,不是考核标准;能讲清、能验证比赶进度重要。

周次 主线 阶段
第 1 周 跑起来 → 系统地图 → 循环 0、1、2
第 2 周 循环收尾 → 上下文 2、3
第 3 周 工具 4
第 4 周 模型接入 → 扩展 5、6
第 5 周 界面与集成 7
第 5–6 周(穿插) 工程化 8
第 6–8 周 综合实战与毕业验收 9
  • 最小路线:0 → 1 → 2 → 3 → 4 → 8 → 9。先获得独立写出最小 Agent 的能力。
  • 完整路线:0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 → 9。适合想系统掌握平台化能力的人。
  • 生产化路线:在完整路线基础上重点加强 4、6、8,并读选修区的 telemetry、durable、env。

如果时间不够,不要跳过阶段 1–4 的“理解 + 小实验”;可以暂时不深挖 TUI 内部、chord 和 durable。


六、最终毕业设计:做一个 mini agent

跳转到“六、最终毕业设计:做一个 mini agent”

阶段 9 的核心不是再做几道散题,而是把前面的知识重新组装。最低要求如下:

  • 一个循环:支持模型回复、工具调用、工具结果回到上下文、自然停止和中止;
  • 一份会话记录:至少能保存消息、工具结果和一次压缩摘要;能解释树/分支/活动路径;
  • 一次上下文投影:能从活动路径生成模型消息,压缩后仍保留原文;
  • 两个工具:一个只读工具、一个会产生副作用的工具,并说明校验和风险;
  • 一个模型适配:至少接入一个 provider,能处理流式文本和错误;
  • 一个界面:CLI 或 JSON 事件输出,至少能从外部观察执行过程;
  • 一份追踪记录:导出一次完整请求的事件序列,能解释消息、工具和停止原因;
  • 一组测试:用假模型测循环、工具和错误路径;
  • 一份设计说明:画出七块结构,解释三个关键取舍。

如果你能不看 Pi 源码完成这套设计,并解释为什么每个部件存在,这门课的目标就达到了。


术语 一句话解释
Agent 由模型反复做决定、调用工具并维护上下文的程序
Run 从一次输入开始,到系统确认没有自动工作为止的一整段执行
Turn 一次模型回复及其要求的工具执行,是循环中的一轮
Session 一次可持续对话的持久化记录,本质上是一棵 entry 树
Entry 会话文件中的一条记录,有 id 和 parentId
Branch 从根节点到某个叶子的连续路径;一个会话可以有多条
Leaf 当前活动分支的末端,决定下一次从哪里继续
Projection 从活动分支计算出的、模型可见的对话历史
Compaction 把旧历史概括成摘要并追加到树中的操作
Context 本次请求真正发给模型的全部内容
Tool call 模型请求执行一个工具及其参数
Provider 某家模型厂商或某种模型服务的接入实现
Extension 在进程内注册工具、命令、钩子、渲染等能力的模块
Event 执行过程中的状态通知,如增量文本、工具开始/结束、消息落盘

文档 作用
介绍与整体架构 先读的总览:七块、分层、请求旅程、设计取舍
阶段 0 环境搭建与两种基础用法
阶段 1 包依赖、实体词、请求全生命周期
阶段 2 循环、turn、steering / follow-up / abort、最小循环
阶段 3 会话树、投影、压缩、系统提示词、分支
阶段 4 工具生命周期、安全、截断、回填、自定义工具
阶段 5 模型接入、provider、凭据、模型目录
阶段 6 扩展、技能、MCP、codemode、打包
阶段 7 TUI、print、JSON、RPC、SDK 与集成
阶段 8 测试、检查流水线、构建和发布
阶段 9 完整 mini agent、测试、设计说明与毕业验收
选修区 telemetry、durable、env、chord、evals 的按需入口

使用顺序:总览读两遍 → 当前阶段清单 → 阶段详解 → 做实验 → 回到总图复述。不要从文档目录顺序硬读所有源码。


源码目录固定在 $PI_SRC。在 PowerShell 中:

终端窗口
cd $PI_SRC
npm install --ignore-scripts
npm run hydrate:model-data
.\pi-test.ps1 --version
.\pi-test.ps1 -p "总结这个仓库的目录结构"
.\pi-test.ps1

观察事件流时:

终端窗口
.\pi-test.ps1 --mode json "读一下 package.json 的前 20 行"

需要 JSONL 事件时,优先把它重定向到文件,再逐行解析;不要用普通文本日志污染 stdout 事件流。


  • 阶段 0:能运行两种形态,知道学习区版本
  • 阶段 1:能脱稿画系统图和请求时序图
  • 阶段 2:能写出最小循环并解释三个插口
  • 阶段 3:能从会话树推导一次模型上下文
  • 阶段 4:能写出并验证一个自定义工具
  • 阶段 5:能配置一个模型适配并解释统一事件
  • 阶段 6:能写一个扩展或技能并说明其边界
  • 阶段 7:能选择并跑通一种外部集成形态
  • 阶段 8:能完成一次带测试的规范改动
  • 阶段 9:能独立设计和解释一个 mini agent

基于 Pi v1.3.0(71023aec,2026-10-15)重写 · 学习区路径已按当前目录校正