这节看复用边界
前六节讲内部运行;07 讲同一套能力怎么被外部应用、长期宿主和远程进程使用。
main.tsmodes/interactivecore/sdk.tscore/agent-session-runtime.tscore/agent-session-services.tsmodes/rpc/rpc-mode.tsCLI print/json -> AgentSession,interactive -> AgentSessionRuntime -> AgentSession,SDK -> AgentSession,RPC -> AgentSessionRuntime -> AgentSession,最后都进入 Agent -> agent loop。
SDK 创建完整 AgentSession
createAgentSession() 不是只创建底层 Agent,而是组装 Pi 产品层需要的整套运行环境。
路径
解析 cwd 和 agentDir。
服务
创建 auth、model registry、settings、session manager。
资源
resourceLoader.reload() 加载 extensions、skills、prompts。
状态
恢复 model、thinkingLevel、messages。
Session
创建 Agent 和 AgentSession。
SDK 是直接嵌入:你的 Node 应用和 Pi 在同一个进程里,直接拿到 AgentSession、订阅事件、调用 prompt()。
Options 让宿主接管边界
外部应用可以选择默认 Pi 配置,也可以替换存储、模型、工具和资源加载方式。
配置和模型
cwd / agentDirauthStoragemodelRegistrymodel / thinkingLevel
工具和资源
toolsexcludeToolsnoToolscustomToolsresourceLoader
会话和设置
sessionManagersettingsManagersessionStartEvent
最小 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 时替换它
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)
旧 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_upset_model / compactswitch_session / fork / clone
Responses
type: "response"id关联 requestsuccess / error
Events
message_updatetool_execution_updateagent_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/jsonagent_endinteractiveSDKAgentSession,可替换 storage/tools/resources。agent_end 或宿主订阅RPCagent_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。