we0agent

Guides

Resume

用 resume 模式从已持久化的会话恢复未完成的输出,无需追加新消息。

概述

We0Agent 的每次运行都带一个运行模式 mode,取值为 promptresume

  • prompt:追加新的用户消息并运行,是默认模式。
  • resume:不追加任何新消息,基于已持久化的会话历史,恢复上一轮中断在半途的 assistant message 或工具调用,并继续把这一轮跑完。

resume 适用于上一次运行没有正常收口的场景:进程崩溃、被 abort 打断、网络中断后留下的「未完成 assistant message」或「pending/running 状态的工具调用」。只要这些状态已经落库,用同一个 session_idresume 模式再跑一次,engine 就会接着上次断点往下走。

resume 完全依赖此前已持久化的消息和 part。如果换用一个空的 MemoryPersistence 去 resume,会因为没有历史可读而无事可做。参见 Persistence

Mermaid
Rendering diagram...

调用形态

三个运行入口 stream()invoke()build_request() 都接受 mode 参数。resume 时传入与上一轮相同的 session_id,并且不传 messages

import asyncio

# 流式恢复:继续消费上次断点之后的事件
async for event in agent.stream(
    abort=asyncio.Event(),
    mode="resume",
    session_id="ses_demo",  # 与上一轮完全相同的会话标识
):
    if event["type"] == "text-delta":
        print(event["text"], end="", flush=True)

需要最终结果而非事件流时,用 invoke()

result = await agent.invoke(
    abort=asyncio.Event(),
    mode="resume",
    session_id="ses_demo",
)
# result.result 为 "stop" 或 "compact"

mode 默认值是 prompt,因此恢复会话时必须显式写 mode="resume"

与 prompt 模式互斥

messages 参数在两种模式下的约束是互斥的,由 build_request() 在入口处校验:

模式messages校验行为
prompt必填省略时抛出 ValueError("messages is required in prompt mode.")
resume必须省略传入时抛出 ValueError("messages is not allowed in resume mode.")

也就是说,恢复一段会话和追加一条新消息是两件不能合并的事。如果你既想补充新输入又想继续上一轮,应当先用 resume 把上一轮收口,再用 prompt 追加新消息。

# 错误:resume 模式不允许携带 messages,会直接抛 ValueError
await agent.invoke(
    abort=asyncio.Event(),
    mode="resume",
    session_id="ses_demo",
    messages=[user_message("继续")],  # ✗
)

两种模式在运行启动阶段也不同。prompt 会先 ensure_session()、清理 revert 状态、中断上一轮遗留的未完成工具、再写入新的用户消息;resume 只做 ensure_session(),随后直接进入恢复与运行循环,不写入任何新消息。

恢复语义

进入运行循环后,engine 在每个 step 之前都会检查 transcript 中最后一条 assistant message 是否需要恢复。判定基于两类信号:

信号判定依据含义
未完成 assistant messageassistant_message.time.completed is None上一轮 assistant 输出没有正常收口。
未完成工具调用存在状态为 ToolStatePendingToolStateRunningToolPart工具调用发起后没有写回终态结果。

两类信号都不存在时,恢复无操作,直接按正常流程跑下一个 step。

工具调用恢复

对最后一条 assistant message 里的每个工具 part,resume 模式按其状态和执行策略决定动作:

工具状态动作说明
ToolStateCompletedkeep已完成,保留结果。
ToolStateErrorkeep保留错误结果;若该工具配置为出错阻断后续,会阻断其后未完成的工具。
ToolStatePending / ToolStateRunning(无副作用)recall重新执行该工具调用,补齐结果。
ToolStatePending / ToolStateRunning(有副作用)interrupt标记为中断,不重复执行,避免副作用被执行两次。
被前序中断阻断的未完成工具interrupt一旦前面出现 interrupt 或阻断性错误,后续未完成工具一律标记中断。

这里是 resumeprompt 的关键区别:prompt 模式会把所有未完成工具一律按中断处理(reason 为 prompt),不重新执行;而 resume 模式会尽可能重放那些无副作用的工具(recall),只对有副作用或被阻断的工具做中断收口。

是否「有副作用」由工具自身的执行策略决定。读取类工具通常可安全重放,写入、命令执行等会改变外部状态的工具会被判为有副作用,恢复时只做中断而不重跑。参见 AnyToolDefinition

assistant message 恢复

如果最后一条 assistant message 的 time.completed 为空,恢复会把它标记为已完成,并在没有既有错误时写入一个恢复错误:

字段
error.reason"UnfinishedAssistantMessage"
error.message"Assistant message was not completed before recovery."
error.metadata{"recovered": True, "mode": "resume"}

收口后运行循环会继续推进:把恢复后的状态作为新的起点,让模型基于补齐的工具结果和已收口的历史继续生成后续 step,直到这一轮自然结束。

与 abort 的配合

resume 最常见的来源就是被 abort 打断的上一轮运行。abort 会让 engine 在当前阶段收口并把已产生的状态落库,但这一轮的 assistant 输出可能仍是未完成的。此时用同一个 session_idresume 模式再跑一次,即可从断点继续。参见 Abort

abort = asyncio.Event()

# 第一轮:运行中被打断
try:
    await agent.invoke(
        abort=abort,
        mode="prompt",
        session_id="ses_demo",
        messages=[user_message("整理当前目录并生成报告。")],
    )
except asyncio.CancelledError:
    pass

# 第二轮:用新的 abort 信号从断点恢复,不再追加新消息
await agent.invoke(
    abort=asyncio.Event(),
    mode="resume",
    session_id="ses_demo",
)

默认行为与易错点

  • mode 默认是 prompt,恢复会话必须显式写 mode="resume"
  • resume 模式下传 messages 会抛 ValueError;要补充新输入请改用 prompt 模式单独发起。
  • resume 不会创建用户消息,也不清理会话的 revert 状态,它只做会话头校验加恢复运行。
  • resume 依赖已落库的历史。空的或换过的持久化端口没有历史可恢复。跨进程恢复请使用 SqlPersistence,参见 Persistence
  • 有副作用的工具在恢复时只做中断收口,不会被重新执行;只有无副作用的工具会被重放。
  • 当前 agent 配置了结构化输出时,stream() 会抛 ValueError,结构化结果只能通过 invoke() 获取,这一约束在 promptresume 两种模式下一致。

On this page