Session 中断后重新启动时如何恢复上下文?
未标记
考查重点:会话恢复与动作状态核对。按Session ID加载目标/检查点、摘要与最近完整消息,再按预算构新输入,外部动作先核状态再续
本题目录
参考答案
核心回答
恢复要接回同一会话的任务状态和模型上下文,不能只重新加载一段聊天记录。先根据 Session ID 找到已持久化的消息、摘要、执行位置和待处理输入,核对中断时未确认的工具动作,再按上下文预算组装下一次模型请求,从可继续的位置推进。
进程内的消息列表在重启后会丢失,因此状态要存到可跨进程读取的后端。摘要用于控制输入长度,原始消息和动作记录用于回查;恢复时尤其要保留目标、约束、已完成事项及最近完整的工具调用与结果。恢复执行不等于外部动作只发生一次:对于结果不明的写操作,要先查询业务状态或使用稳定的幂等键,不能看到“未完成”就直接重做。
需要保存哪些内容?
- 会话与任务信息: 会话标识、任务目标、关键约束、所用模型及必要的配置版本,避免接错会话或用不兼容的配置继续。
- 已提交的执行进度: 最近有效检查点、步骤或任务状态、尝试次数,以及已经受理但尚未处理的输入。进度不能只放在内存中的线程、协程或队列里。
- 消息与证据: 原始用户消息、模型回复、工具调用 ID 和结果;长历史可以另存摘要,并保留原文、文件或产物的引用。
- 未确认的动作: 哪些调用已开始、哪些有完成结果、哪些因中断而状态不明。动作记录需要能关联外部业务对象,才能核对是否已经发生。
同一会话的恢复还需要执行协调,避免两个恢复请求同时推进。单进程可以按会话串行;多实例则需要另行设计所有权与并发控制,不能把一个内存锁当成跨进程保证。
恢复顺序怎样安排?
先确认中断原因和是否允许续跑:用户主动停止的任务,不应因为服务重启就自动重新启动。随后读取最近已提交的状态,核对遗留的执行中记录;结果明确的步骤沿用结果,结果不明的步骤按工具性质处理。
例如,仓库读取通常可以重新查询;创建工单、发信或提交支付则应先用操作 ID 查询是否成功,再决定重试、补偿或等待人工处理。数据库中的“工具失败”只是本地记录,不能证明外部动作没有发生。
最后重新装配当前可用的指令、工具及权限规则,加入任务状态、摘要与近期完整消息。摘要可能遗漏否定条件、金额或文件路径,这类关键内容应能从结构化状态或原文核对。准备好下一次模型输入后再继续执行,并将新增结果及时持久化。
OpenCodeTypeScript
核心回答
OpenCode 是能够阅读仓库、修改文件和执行命令的编程助手。以该版 TypeScript 会话实现为例,它把用户输入受理、会话执行和模型输入重建分开:先将输入写入持久待处理队列,按会话串行推进步骤;服务重启后检查遗留执行标记,核对未结束的工具记录,再从持久消息重建上下文继续。
这恢复的是任务的推进依据。它不会接回旧模型请求的进程现场,也不会仅凭会话恢复就撤销或去重所有文件、命令和外部系统的副作用。
输入先持久受理,再唤醒执行
Session.prompt 先按输入 ID 核对已有记录,再准备并受理输入,之后才唤醒执行器。resume: false 可以只受理而暂不执行。相同会话、相同输入类型和相同 ID 的重试沿用第一次受理的内容,因此重新发送并不意味着替换原输入。
待处理输入保存在 session_inbox 中;投递时消费待处理行,并在同一事件事务中插入可见消息。这样,恢复时可以区分“已经受理、尚未投递”和“已经成为会话消息”的输入,而不依赖客户端是否收到了响应。
重启标记与执行协调各管一件事
执行器在开始执行时,随开始事件的事务写入持久执行标记。正常完成、失败或用户主动中断会释放标记;服务关闭导致的中断保留标记,进程突然退出也可能留下它。
受管理服务启动时,恢复扫描识别这些遗留会话,持久增加恢复尝试次数,再安排继续执行;超过预算则记录失败。这个标记用于识别未结束的执行,不是分布式租约。
同一会话的多次唤醒由进程内协调器合并,同一会话串行推进,不同会话可以并发。重启恢复假定旧进程已经退出,不能据此允许多个进程共享数据库并同时接管同一会话。
先结清遗留记录,再重建模型输入
Runner 开始推进时,会把遗留的 streaming/running 工具记录标为中断失败,把遗留的执行中压缩记录标为压缩失败。这段处理让后续模型能看到调用没有取得正常结果,避免历史永远停在“执行中”;它没有证明实际动作未发生,也没有恢复那个动作的执行现场。
之后每一步重新选择会话上下文并加载持久历史,再进行一次模型流式请求。工具调用及结果进入会话记录,下一步从更新后的历史继续,而不是依赖一个只在内存里保存消息的无限工具循环。
长历史采用压缩时,本地摘要路径会保留任务目标、要求、决定、工作状态和下一步等内容,并通过 keepID 引用近期消息;历史加载再取回这些近期消息组成文本,与摘要及后续消息一起重建模型输入。原生模型压缩还有模型兼容条件,不能将任意压缩结果直接用于任意模型。
哪些状态仍要另行核对?
最关键的情况是:工具已经修改文件或完成外部请求,但进程在结果落库前退出。恢复后即使工具记录被标成中断,动作也可能已经发生。输入 ID 的受理幂等与会话串行,都不能替代业务动作的幂等和结果核对。该版重启恢复明确采用至少一次的执行语义。
同样,遗留后台 Shell 的取消或完成通知,是对后台任务状态的处理;不能把通知当成任意子进程、外部服务或业务资源已经恢复的证据。文件快照与显式回退也不能撤销任意命令的外部副作用。
验证时应分别在输入受理后、工具动作完成但结果未写入时、模型输出中途和压缩过程中终止进程,再检查恢复后的输入数量、消息顺序、工具状态及实际文件或业务结果。还要区分用户主动停止与服务退出,确认不会把用户已取消的任务自动重启。
对应教程
- 《记忆与对话历史(含 Redis 基础)》:回看按会话标识读取历史、组装模型输入与写回消息的基础过程。
- 《LangGraph 高级特性》:状态持久化部分说明检查点、会话标识及内存与 SQLite 后端的区别;本题的 OpenCode 答法采用其自身的会话机制。
参考资料
- 国内:JavaGuide:状态机与流程编排:采用任务实例、执行记录、恢复扫描与业务幂等的区分,解释为何保存进度后仍要核对未确认的外部动作。
- 国内:JavaGuide:Agent 记忆:借鉴历史缩减、摘要和外部引用的分工,解释持久记录不必全部原样进入下一次模型输入。
- 国内:zero2Agent:记忆与上下文:参考关键约束与摘要分离的讨论,说明恢复后需要核对否定条件、数字和状态,不能只依赖概括性摘要。
- 国内:Datawhale:记忆与检索:依据进程内临时历史与持久存储的区别,解释重新创建 Agent 后为什么需要从外部后端接回会话信息。
- 国外:LangChain:Checkpointers:采用线程标识、检查点、待执行任务和重放边界的分工,组织通用恢复步骤。
- 国外:Anthropic:Effective context engineering for AI agents:采用压缩与结构化笔记的思路,说明恢复输入应保留目标、决定和未解决事项,以及过度压缩可能遗漏关键细节。
相关面经
1 篇百度
Go 后端开发工程师(Agent)如果 Session 中断,重新启动之后,怎么恢复上下文?