内容提要
作者将 iMessage 机器人 pi-imessage 迁移到 pi durable,并新增可视化 Web UI。文章重点介绍 Session 管理的五个概念:Conversation 是对话线,可 fork 或派生子对话;Entry 是不可变记录,包含用户消息、模型回复和工具结果等;Task 是持久状态机,Generation 与 Tool 各有阶段,崩溃后可恢复;Submission 是提交回执,状态依次为 queued、placed、done;Document 保存可变 JSON 状态。
延伸解读
为什么用不可变 Entry 加可变 Document
文章把对话记录拆成两类存储:Entry 一旦写入就不再修改,承载用户消息、模型回复、工具结果和 system prompt 变更;Document 则保存需要反复更新的 JSON 状态,例如 chat.db 已读到哪一行、chatGuid 对应哪个 conversationId。这种分工让对话历史保持可追溯,同时把游标、映射等易变信息隔离出来,避免为了改一个状态而重写历史记录。
崩溃恢复靠 Task 状态机而非重跑整轮
Generation 任务分为 prepare、request、tools 三个阶段,Tool 任务分为 call 和 execute 两个阶段,进程崩溃后从当前 phase 继续。Tool 的 execute 阶段只在崩溃恢复时进入,并根据 replay 参数决定是否重试,区分 safe 与 unsafe。这意味着恢复粒度落在单个任务上,而不是把整轮对话推倒重来,但工具是否可安全重试仍需由工具本身语义决定。
Submission 状态单向推进的实际用途
Submission 是提交输入后拿到的持久化回执,状态只会从 queued 到 placed 再到 done。文章指出 submit() 在落盘后即返回,此时 user entry 已写入,而 wait() 要等所有 generation 结束后才拿到最终 answer。作者认为这方便客户端做幂等与回复;案例中用 iMessage 消息的 GUID 作为 requestId,正是把去重键绑定到原始消息上。
多轮工具调用的停止条件
模型在一次 generation 中可一次性给出多个 tool call,默认并行执行;工具全部结束后触发下一轮 generation。停止条件并不复杂:某一轮 generation 的 stopReason 为 stop 时不再发起下一轮,而为 toolUse 时继续。案例中四轮 generation 依次调用 immich_search、immich_download、read,最后一轮返回文本并停止,最终回答的 entry 被写入 Submission 的 answer 字段。
Q&A
pi-imessage 迁移到 pi durable 后有什么变化?
作者将 pi-imessage 从 pi coding agent sdk 迁移至 pi durable,并为其打造了一个可视化的 Web UI,以便观察完整内部运行情况。
Pi Durable 中的 Conversation 是什么?可以 fork 吗?
Conversation 是一条对话线,即 transcript scope,可以任意 fork 一个分支。例如在 Slack 中,一条 thread 对应 fork 出的一个分支。在 Pi Durable 中,subagent 是由创建它的 tool task 所拥有的普通 conversation。
Pi Durable 的 Entry 有哪些类型?
Entry 是不可变的记录,类型包括:用户消息(pi.user)、模型回复(pi.assistant)、工具结果(pi.tool-result)、系统提示变更(pi.system)、重置(pi.reset)以及自定义类型。
Pi Durable 的 Task 崩溃后如何恢复?
Task 是持久状态机,每个 task 维护各自的状态机,进程崩溃后可从 phase 继续。内置 Generation 任务分为 prepare、request、tools 三个阶段;内置 Tool 任务分为 call(正常路径)和 execute(仅崩溃恢复时进入,根据 replay 参数决定是否重试)。
Submission 的状态是如何变化的?
Submission 是提交输入后拿到的回执,状态单向推进:queued(会话忙,先排队)→ placed(已写入 user entry,generation 开始)→ done(最终回答落盘)。
Pi Durable 中 Document 的作用是什么?
Document 保存可变的 JSON 状态,由 Chord 操作和偶尔的完整基表示。Entry 不可变,但有些状态天然要反复修改,这类状态放在 document 里,例如维护 iMessage chat.db 已读到哪一行、chatGuid 对应哪个 conversationId 等全局信息。