写作现场:2026 年 1 月 27 日。 pi-mono v0.50.1 将 provider stream、Agent loop、coding session 和终端界面拆成独立包。这个结构暴露了 Agent 系统常被压成一个 done 的问题:消息闭合、工具批次结束、loop 退出、消息落盘和 session 后处理发生在不同边界。
事件层级与完成条件
主要包之间的调用链为:
AgentSession
→ Agent
→ runAgentLoop
→ pi-ai provider stream
→ tool execution
→ 下一轮或退出
pi-ai 统一 provider 的流式消息;pi-agent-core 管理状态与 loop;pi-coding-agent 增加工具、session、compaction、extensions 和 CLI;pi-tui 负责终端呈现。事件流依次出现 agent_start、turn_start、消息与工具事件、turn_end,最后才是 agent_end。
四个关键边界不能互换:
message_end:token 已组装成完整 assistant message,其中仍可能包含待执行 tool call;turn_end:本轮 assistant message 与对应 tool result 已闭合;agent_end:loop 没有待处理工具或 follow-up,Agent回到 idle;- session settled:
AgentSession完成自动重试、compaction 等后处理。
UI spinner、SDK promise、账单、通知和下游自动化依赖不同边界。若界面在 message_end 就开放下一任务,上一轮工具可能尚未结束;若指标只计算 provider stream,则会漏掉工具执行、持久化和 session 后处理。
消息持久化、分支与 Compaction
pi 在 message_end 时 append session entry。逐 token 持久化会产生大量碎片,只在 agent_end 写入又可能丢失已经闭合、并即将触发工具的 assistant message。选择 message 边界,是在恢复粒度和写入成本之间取中间点。
session 使用 append-only JSONL tree,每个 entry 包含 id 与 parentId,当前 leaf 决定下一轮使用的分支:
root
└─ 用户问题
├─ 回答 A ─ 工具结果 ─ 当前 leaf
└─ 回答 B ─ 另一条实验
历史日志保留发生过的分支,模型上下文只包含当前路径的投影。达到 context window 阈值后,compaction summary 替换较老内容并保留近期 tail;原始 JSONL 仍在磁盘,但模型看到的是有损摘要。
需要区分三种数据:session log 记录发生过什么,branch 定义当前沿哪条路径,compaction 定义有限窗口里保留什么解释。append-only 提供可追溯性,不保证摘要完整,也不是外部工具状态的 checkpoint。恢复 transcript 无法复活进程、凭据或进行中的请求,更不能安全重放状态未知的付款与部署。
pi-mono 适合希望直接控制 provider、事件和 session 边界的框架作者与基础设施工程师;审批、RBAC、跨进程 exactly-once 和可视化工作流需要额外实现。成熟的 Agent 产品应分别暴露模型输出、工具批次、消息持久化、session 后处理和外部副作用的完成状态,而不是用一个绿色对勾覆盖全部阶段。
版本与源码
信息边界:本文写于 2026 年 1 月 27 日,只依据
v0.50.1;后续仓库迁移、通用 harness 与新增生命周期事件不在本文判断中。