跳转到内容

重启之后,Session 能恢复什么

Agent 已经读取文件,进程却在下一轮模型请求前退出。重新启动后,聊天窗口还能显示用户问题和工具调用。

界面恢复,不等于执行器知道工具结果是否落盘、下一轮请求是否还在队列、写操作能否重试,也不代表它知道已经消耗了多少预算。

重新显示历史与继续未完成的运行,需要不同的数据。

Pi 的 Session 是一棵追加写入的树

Section titled “Pi 的 Session 是一棵追加写入的树”

AgentHarness Session 使用 entry 记录 message、model change、thinking level、active tools、compaction、branch summary、label 和自定义状态。每个 entry 指向父节点,因此用户可以从旧节点派生新分支,不需要覆盖原历史。

核心结构见 packages/agent/src/harness/session/session.ts

JSONL storage 先写一条 v3 header,后续每次变化追加一行。切换 leaf 也会留下记录。查看 JSONL storage 的读取与追加

JSONL 指“一行一个 JSON 对象”。下面是为了说明关系而简化的三行,不是源码字段的逐字拷贝:

{"type":"header","version":3,"sessionId":"s-01"}
{"id":"e-01","parent":null,"type":"message","role":"user","text":"检查项目"}
{"id":"e-02","parent":"e-01","type":"message","role":"assistant","text":"开始读取"}

entry 是一条追加记录,parent 指向它从哪条记录继续,leaf 是当前选中的分支末端。切回 e-01 再追加新消息,就会得到另一条 branch,原来的 e-02 仍保留。

这套结构很适合重建对话、模型选择和分支。模型对象、工具实现、Extension、认证信息和工作环境仍需宿主程序重新装配。

Session、Compaction、Memory 不是一回事

Section titled “Session、Compaction、Memory 不是一回事”

这三个词经常被统称为“记忆”,实际用途不同:

机制 主要用途 典型寿命
Session 保存一次任务的消息、状态与分支 一次任务到长期归档
Compaction 给当前模型请求腾出窗口 当前任务的后续 turn
Long-term memory 在多个任务之间复用少量事实或偏好 直到被更新或删除

Session 恢复不应该擅自把每段对话抽成用户事实。长期记忆也不应该覆盖当前任务刚验证出的新信息。至少要为记忆保存来源、作用域、写入时间与失效条件。

Pi 的 durable harness 设计稿很坦率地列出当前缺口:查看 durable harness 的故障模型

  • Provider 的网络流无法从任意 token 位置接着收;
  • 进程重启后要重新创建模型、工具与资源;
  • 尚未落盘的队列项会丢失;
  • 非幂等工具在结果未记录时不能安全重放。

设计稿继续提出 operation、queue 与 tool lifecycle 的持久化方向,查看恢复记录方案。这些内容是设计目标,不能据此把当前 CLI 写成任意位置可恢复的 durable runtime。

MemorySessionStore 保存一次已结束运行的 messages、events、terminal 与 reason。

Terminal window
cd agent-harness-lab
npm run lab -- 06

预期观察:

{
"terminal": "completed",
"messages": 2,
"events": 4,
"hasInventedMemory": false
}

hasInventedMemory: false 表示 Session 没有根据一段聊天擅自添加长期事实。这个实验能证明最终快照可以重新读取,不能证明进程在任何指令位置退出后都能继续。

要继续未完成的运行,还需追加更细的记录:

queue_enqueued / queue_consumed
provider_started / provider_interrupted
tool_started / tool_finished
operation_started / operation_finished

这些记录要在动作发生时写入。如果只在整次 run 结束时一次性保存,最危险的中间状态仍然是空白。

下一章先定义任务何时停止。再往后把 operation journal 接进工具执行,处理程序死在 tool_startedtool_finished 之间的情况。