π Pi Agent Study

01 使用入口学习记录

本节目标

本节目标是先把 pi 的入口链路跑通,不急着深入所有源码。重点理解一次用户输入如何从 CLI 进入会话层,再进入 agent 执行层,最后由 agent loop 产生模型输出、工具调用和事件流。

我们怎么学的

已确认的主链路

pi 命令
-> packages/coding-agent/src/cli.ts
-> packages/coding-agent/src/main.ts
-> runPrintMode / InteractiveMode / runRpcMode
-> AgentSession.prompt()
-> Agent.prompt()
-> runAgentLoop()
-> runLoop()
-> streamAssistantResponse()
-> executeToolCalls()
-> agent_end

关键源码位置

第一次运行 Pi 看什么

建议第一遍用 JSON mode:

pi --mode json -p "Read README.md and summarize it"

观察重点:

CLI mode 分发图

print、json、interactive、RPC、SDK 是不同输入输出外壳,不是不同 agent 核心。

flowchart TD
  CLI[pi CLI / SDK / RPC entry] --> Main[main.ts mode dispatch]
  Main --> Print[print mode]
  Main --> Json[json mode]
  Main --> Interactive[interactive mode]
  Main --> Rpc[RPC mode]
  Print --> Session[AgentSession.prompt]
  Json --> Session
  Interactive --> Session
  Rpc --> Session
  Session --> Agent[Agent.prompt]
  Agent --> Loop[runAgentLoop / runLoop]

判断方式:

一次 prompt 的事件时序图

sequenceDiagram
  participant User
  participant CLI
  participant AgentSession
  participant Agent
  participant Loop as runLoop
  participant Provider
  User->>CLI: pi --mode json -p ...
  CLI->>AgentSession: prompt(message)
  AgentSession->>Agent: prompt(messages)
  Agent->>Loop: runAgentLoop(context, config)
  Loop->>Provider: streamAssistantResponse(context)
  Provider-->>Loop: text/thinking/toolCall events
  Loop-->>AgentSession: agent events
  AgentSession-->>CLI: JSON lines

我们形成的职责边界

AgentSession

AgentSession 是产品会话层。它负责把用户输入变成 agent 可执行的消息,并处理 CLI/TUI/RPC 共用的产品逻辑。

它关心:

Agent

Agent 是执行层状态机。它不关心 CLI 怎么输入,也不关心 session 文件怎么保存。

它关心:

agent-loop

agent-loop 是核心执行函数。它负责一轮或多轮模型调用和工具执行。

它关心:

关键理解

1. AgentSession.prompt() 不直接请求模型

我们认为它主要做输入进入 agent 前的预处理和调度。

它会:

最终才进入底层 agent.prompt()

2. Agent.prompt() 不是模型调用

Agent.prompt() 启动的是一次 agent run。

它会先构造:

然后交给 runAgentLoop()

3. runLoop() 有两层 while

内层 while 处理当前连续推理链:

外层 while 处理 agent 准备停下之后的 follow-up:

4. pi agent 是事件驱动循环

本节最终结论:

一次 prompt 会触发持续的事件流,并在 runLoop 里反复执行
“模型生成、工具调用、工具结果回填、继续生成”,
直到没有工具、steering 或 follow-up 才结束。

这就是为什么它不是普通的一问一答。

实操观察

我们建议用 JSON mode 观察事件流:

pi --mode json -p "Read README.md and summarize it"

你实际看到的前半段事件包括:

session
agent_start
turn_start
message_start(user)
message_end(user)
message_start(assistant)
message_update(thinking_start)
message_update(thinking_end)

这些事件对应源码中的:

如果模型实际调用工具,还会继续看到:

message_update(toolcall_start / toolcall_delta / toolcall_end)
tool_execution_start
tool_execution_end
toolResult
turn_end
agent_end

这些事件的初学者读法:

关键闭环:

message_update(toolCall 增量)
-> 完整 assistant message
-> tool_execution_start/end
-> toolResult 回填到 Context.messages
-> 下一轮模型调用继续推理

本节完成度

已完成:

未展开,后续章节继续:

下一节方向

下一节进入 02 模型接口:理解 tool calling

目标是读懂:

Source: 01-entry-runtime-notes.md