K1.3.4 Task 1.3

Resume 节省 85% Token,支持多次后续跟进

子代理完成第一个任务后,可能已经积累了有价值的上下文——探索了 50+ 个文件、找到了 15 篇论文、构建了依赖图。Resume 以重新开始成本的一小部分保留这些上下文用于后续跟进。而且不限于一次跟进——resume 支持多次顺序循环。

Resume 流程

  1. 首次查询:协调者调用 Task 工具 → 子代理运行 → 返回 ResultMessage
  2. 捕获:从 ResultMessage 提取 session_id,从响应内容提取 agentId
  3. 跟进:调用 query(),带 resume=session_id 和引用 agentId 的 prompt

恢复的会话从上次结束的地方精确接续——所有工具结果、发现、推理和中间上下文完好无损。

数据:resume vs 新会话

多轮子代理工作流的生产对比:

指标新会话(重新注入上下文)Resume
每次跟进的 prompt token8,0001,200
每次跟进的延迟15 秒4 秒
答案质量相同相同

Token 减少 85%,延迟减少 73%,质量完全相同。 每个任务 3 次跟进的话:每任务节省约 20,400 token 和约 33 秒。

为什么差距这么大?新会话必须把上下文作为 prompt 文本重新注入(贵,有损)。Resume 的上下文已经在会话状态里了(免费,无损)。输入 token 少不代表信息少——恢复的 agent 有更多上下文,因为它保留了完整会话,而不只是一份摘要。

多次 resume 链式调用

Resume 不限于一次跟进。同一个 session_id 支持多次顺序 resume:

  1. 初始审计 → 发现漏洞
  2. Resume #1 → 协调者要求对最重要的问题提出修复建议
  3. Resume #2 → 协调者要求 agent 验证修复是否解决了发现的问题
  4. Resume #3 → 协调者要求最终摘要

每次 resume 累积上下文。3 个循环后,子代理拥有完整历史:初始发现、修复建议、验证结果。在任何一步重新开始新会话都会丢失这些累积的理解。

缓存所有 session_id

当协调者为一个研究任务派生 5 个子代理时,缓存全部 5 个 session_id——不只是你预期会跟进的那个。Session_id 是轻量的字符串标识符,没有持续存储成本。未使用的会话以零成本保持空闲。

SDK 支持恢复任何有效的 session_id,不只是最近完成的那个。如果一个意外的问题需要回到 5 个子代理中的 #2,缓存的 session_id 让它无需重新分析就能实现。

最常见的 resume bug

# 首次查询
result = await query(prompt="Audit the auth module", options=options)
# BUG: 这里没有捕获 session_id

# 跟进尝试
await query(prompt="Suggest fixes", options=ClaudeAgentOptions(resume=None))
# Error: "Cannot resume session: session_id is required"

协调者完成了首次查询但从未从 ResultMessage 捕获 session_id。Resume 调用的 resume=None。修复:总是在初始查询时捕获会话元数据,即使你不确定是否需要跟进。

错误消息很明确:“session_id is required”——不是 “session expired” 或 “topic mismatch”。SDK 不强制查询之间的主题相似性;只要 session_id 有效,任何跟进 prompt 都可以。

什么时候不该 resume

独立任务:如果跟进和第一个任务毫无关系,新会话更干净。恢复的会话带着所有之前的上下文,在无关历史上消耗上下文预算。

过时上下文:如果底层数据在首次查询后发生了显著变化(文件修改、数据库更新),子代理缓存的工具结果引用的是过时信息。用注入的先前发现摘要重新开始。


一句话总结: Resume 比新会话节省 85% token 和 73% 延迟且质量相同,支持在同一个 session_id 上链式多次跟进,需要从首次 ResultMessage 捕获 session_id——缓存所有 session_id,它们很便宜。