07 Pi Agent Study
Advanced · SDK/RPC
07 / Advanced integration

把 Pi agent 放进别的应用

最后一节是进阶集成章节。CLI、interactive、SDK、RPC 不是四套 agent;它们都复用 AgentSession。SDK 是 Node 进程内直接嵌入,RPC 是长期 JSONL agent server。

host map same runtime
01

CLI

一个命令行宿主,负责解析参数和选择 mode。

02

Interactive

TUI 宿主,绑定 UI、快捷键和 session replacement。

03

SDK

给外部应用直接创建 AgentSession。

04

RPC

用 stdin/stdout JSONL 远程控制长期 runtime。

05

AgentSession

所有宿主复用的产品级 agent 控制器。

这节看复用边界

前六节讲内部运行;07 讲同一套能力怎么被外部应用、长期宿主和远程进程使用。

本质
典型使用者
关键文件
CLI print/json
一次性命令行宿主,跑完退出
shell 脚本、人工临时调用
main.ts
Interactive
终端 TUI 宿主,长期持有当前 session
人类在终端里多轮使用
modes/interactive
SDK
直接嵌入 Pi AgentSession
Node 应用、测试、自定义 UI
core/sdk.ts
AgentSessionRuntime
长期宿主的当前 session 管理器
interactive / RPC / 自定义长期宿主
core/agent-session-runtime.ts
Services split
先创建 cwd-bound services,再决定 session options
CLI / RPC / interactive
core/agent-session-services.ts
RPC mode
JSONL agent server
外部进程、编辑器、桌面应用
modes/rpc/rpc-mode.ts
共用核心

CLI print/json -> AgentSessioninteractive -> AgentSessionRuntime -> AgentSessionSDK -> AgentSessionRPC -> AgentSessionRuntime -> AgentSession,最后都进入 Agent -> agent loop

SDK 创建完整 AgentSession

createAgentSession() 不是只创建底层 Agent,而是组装 Pi 产品层需要的整套运行环境。

1

路径

解析 cwdagentDir

2

服务

创建 auth、model registry、settings、session manager。

3

资源

resourceLoader.reload() 加载 extensions、skills、prompts。

4

状态

恢复 model、thinkingLevel、messages。

5

Session

创建 AgentAgentSession

SDK 的定位

SDK 是直接嵌入:你的 Node 应用和 Pi 在同一个进程里,直接拿到 AgentSession、订阅事件、调用 prompt()

Options 让宿主接管边界

外部应用可以选择默认 Pi 配置,也可以替换存储、模型、工具和资源加载方式。

配置和模型

  • cwd / agentDir
  • authStorage
  • modelRegistry
  • model / thinkingLevel

工具和资源

  • tools
  • excludeTools
  • noTools
  • customTools
  • resourceLoader

会话和设置

  • sessionManager
  • settingsManager
  • sessionStartEvent

最小 SDK

const { session } = await createAgentSession({
  sessionManager: SessionManager.inMemory(),
});

session.subscribe((event) => {
  // message_update / tool_execution_update / agent_end
});

await session.prompt("What files are here?");

为什么 inMemory

测试、临时自动化、子 agent、服务端 pipeline 可能不想默认写 JSONL。SDK 允许宿主选择自己的存储策略。

Runtime 管 session replacement

长期宿主不能只拿一个固定 AgentSession,因为 new、resume、fork、clone、import 都会替换当前 session。

AgentSession
= 当前这一个会话的 agent 控制器

AgentSessionRuntime
= 长期宿主,负责持有当前 session,
  并在 new/fork/switch/import 时替换它
为什么不能只清空 messages

AgentSession 绑定了 sessionManager、agent.state.messages、extensionRunner、resourceLoader、settingsManager、modelRegistry、cwd、event listeners 和 UI/extension bindings。

Services split 给宿主决策点

CLI/RPC/interactive 需要先创建 cwd-bound services,再根据 settings、extensions、CLI 参数决定怎么创建 session。

固定流程

createAgentSessionServices()
-> collect diagnostics
-> resolveModelScope()
-> buildSessionOptions()
-> process --api-key
-> createAgentSessionFromServices()

Replacement 流程

emit session_before_*
-> teardownCurrent()
-> createRuntime(...)
-> apply(result)
-> rebindSession(newSession)
-> withSession(new ctx)
和 06 的 stale 检查接上了

旧 session dispose 后,旧 extension ctx 不应该继续用。长期宿主要重新绑定 UI、事件订阅和 extension context。

RPC 是 JSONL agent server

外部进程启动 pi --mode rpc,通过 stdin/stdout 远程控制长期 AgentSessionRuntime。

输入

{"id":"1","type":"prompt","message":"Read README.md"}

输出

{"id":"1","type":"response","command":"prompt","success":true}
{"type":"agent_start"}
{"type":"message_update", ...}
{"type":"agent_end"}

Commands

  • prompt / steer / follow_up
  • set_model / compact
  • switch_session / fork / clone

Responses

  • type: "response"
  • id 关联 request
  • success / error

Events

  • message_update
  • tool_execution_update
  • agent_end

Prompt response 只代表 accepted

RPC 的 prompt 是异步运行,response 不代表模型完成,真正完成要看事件流。

收到 prompt command
-> session.prompt(...) 异步跑
-> preflightResult(true) 后输出 success response
-> 后续 message_update / tool_execution_update 继续输出
-> agent_end 表示完成
为什么这点重要

外部 host 不能把 prompt response 当最终答案。它要持续消费事件流,或使用 RpcClient 的 promptAndWait() 等到 agent_end

RpcClient 是 typed wrapper

它帮 Node 集成方 spawn RPC 进程、写 stdin、读 stdout、匹配 response,并分发 AgentEvent。

const client = new RpcClient({ cwd });
await client.start();

client.onEvent((event) => {
  // message_update / tool_execution_update / agent_end
});

await client.prompt("Read README.md");
await client.waitForIdle();

内部机制

  • spawn node dist/cli.js --mode rpc
  • 每个 command 加 id。
  • response 用 id 匹配 pending request。
  • 非 response 当成 AgentEvent。

Extension UI

RPC 没有内置 TUI,但 extension UI 会变成 extension_ui_request,由外部宿主回 extension_ui_response

怎么选集成方式

先看宿主在哪里运行,再决定用一次性 CLI、interactive、SDK 还是 RPC。

场景
选择
原因
完成信号
命令行一次性使用
print/json
启动一次、处理一个 prompt、输出后退出。
进程退出或 agent_end
终端交互
interactive
需要 TUI、快捷键、session replacement。
UI 事件流
Node 应用内嵌
SDK
同进程直接创建 AgentSession,可替换 storage/tools/resources。
agent_end 或宿主订阅
外部进程长期控制 Pi
RPC
JSONL 长连接,远程 command、events、extension UI request。
agent_end,不是 prompt response

常见误解

  • SDK 不是只创建底层 Agent,而是创建完整 AgentSession
  • RPC 不是更复杂的 json mode;它是常驻 agent server。
  • prompt response 只代表 accepted,不代表回答完成。
  • session replacement 后旧订阅和旧 extension ctx 不能继续当成当前 session。

自测题

  • CLI、interactive、SDK、RPC 最后复用的核心对象是什么?
  • 什么时候选 SDK,什么时候选 RPC?
  • 为什么 RPC 比 print/json 更像长期 agent server?
  • 为什么 prompt response 不代表最终回答?

最终闭环

到这里,Pi agent 的主线已经从 CLI 入口走到外部集成。

SDK

直接嵌入 Pi 的产品级 AgentSession。

Runtime

管理长期宿主里的当前 session replacement。

RPC

把 Runtime 暴露成长期 JSONL 控制协议。

学习路线闭环

CLI 入口 -> 模型接口 -> agent loop -> tools -> session -> extensions -> SDK/RPC。