课程大纲 › 领域 1:Agent 架构与编排

1.7 管理会话状态、恢复与分叉

タスクステートメント1.7:セッションの状態、再開、フォークを管理する

官方大纲原文(日文):知识 4 条 · 技能 4 条

需要掌握的知识

  • 特定の過去の会話を続行するための、--resume <session-name>を使用した名前付きセッションの再開
  • 共通の分析ベースラインから独立したブランチを作成し、異なるアプローチを探るためのfork_session
  • コード変更後にセッションを再開する際、以前に分析したファイルへの変更をエージェントに伝えることの重要性
  • 古くなったツール結果を抱えたまま再開するよりも、構造化されたサマリーを使って新しいセッションを開始するほうが信頼性が高い理由

需要能做到的事

  • セッション名を指定して--resumeを使用し、複数の作業セッションにまたがって名前付きの調査セッションを続行する
  • fork_sessionを使用して並列の探索ブランチを作成する(例:共通のコードベース分析から、2つのテスト戦略やリファクタリングのアプローチを比較する)
  • セッションの再開(以前のコンテキストがおおむね有効な場合)と、サマリーを注入して新たに開始すること(以前のツール結果が古くなっている場合)のいずれかを選択する
  • 全体を再探索させるのではなく、的を絞った再分析のために、再開したセッションに具体的なファイル変更を伝える

课程讲解 · AI 草稿,未经人工审核 以官方文档为准

这一条考什么

考你在多次工作时段之间如何管理 Agent 会话:用 --resume <会话名> 接续某个特定的历史会话;用 fork_session 从同一个分析基线分出互不干扰的分支来比较方案;代码已改动时要明确告诉恢复后的会话哪些文件变了;以及在旧工具结果已经过时的情况下,为什么"注入结构化摘要后新开会话"比硬恢复更可靠。

核心概念

用名字恢复特定会话

Claude Code 会把每次会话的对话记录保存在本地。常见的接续方式:

  • claude --continue(-c):继续当前目录下最近一次会话。适合"刚才断了,接着干"。
  • claude --resume(-r):不带参数时弹出会话选择器;带上会话名或会话 ID 时直接加载那一次会话。

当你同时进行多条调查线(例如昨天的"认证模块深挖"和今天的"支付重构"),最近一次会话未必是你想要的那个。给会话起一个有意义的名字(在会话里可以用 /rename 之类的命令命名),之后用 claude --resume auth-deep-dive 精确接续,比翻找 UUID 或依赖"最近一次"更可靠。

# 昨天:在会话中命名为 auth-deep-dive
# 今天:精确恢复这条调查线
claude --resume auth-deep-dive

# 无头模式下也可以恢复并继续提问
claude -p --resume auth-deep-dive "根据昨天的结论,列出 token 刷新逻辑的三个风险点"

在 Agent SDK 中,对应的是在选项中传入 resume=<session_id>;会话 ID 可以从初始化系统消息或最终结果消息中取得。

fork_session:从同一基线分叉

你已经在一个会话里花了不少轮次分析完代码库结构,现在想比较两种测试策略(集成测试优先 vs. 单元测试优先)。如果在同一个会话里先试 A 再试 B,A 的探索内容会污染 B 的判断;如果分别从零开始,又要重复分析。

fork 的做法:以该会话为基线创建一个新的会话 ID,新分支继承到分叉点为止的全部上下文,之后的内容与原会话互不影响。

  • Agent SDK:ClaudeAgentOptions(resume=base_id, fork_session=True)。
  • Claude Code CLI:在 --resume / --continue 时加上 --fork-session。

对同一个基线 fork 两次,就得到两个并行的探索分支,最后比较两者的结论。

恢复前告知文件变更

恢复的会话里保存着当时的工具结果——比如昨天 Read 过的 auth/token.py 内容。如果今天你或同事已经改了这个文件,模型并不知道,仍会基于旧内容推理。正确做法是在恢复后的第一条消息里具体说明改了什么:

自上次会话以来的变更:
- auth/token.py:refresh_token() 改为异步,新增 retry 参数
- auth/session.py:删除了 legacy_login()
其他文件未改动。请只重新读取这两个文件,并更新之前关于 token 刷新的结论。

这让 Agent 有针对性地重新分析受影响的部分,而不是要么沿用过时信息,要么把整个代码库重新探索一遍。

何时恢复,何时用摘要新开

  • 恢复会话:之前的上下文大体仍然有效(代码基本没变、调查方向不变),只需少量更新。
  • 新开会话并注入结构化摘要:之前的工具结果大面积过时(大量文件被重构、分支切换、依赖升级),或会话历史已经很长、充满试错噪声。

为什么后者更可靠:恢复的会话里过时的工具结果依然"看起来真实",模型很难分辨哪些已失效,容易混用新旧事实;而一份结构化摘要只保留仍然成立的结论、未决问题与关键文件清单,上下文更短、更干净。摘要可以长这样:

**调查摘要(截至 2026-10-20)**
- 目标:定位 token 刷新偶发失败
- 已确认:失败只在并发刷新时出现;与 Redis 锁超时有关
- 已排除:时钟偏移、网络超时
- 未决:新版 refresh_token() 的重试是否幂等
- 关键文件:auth/token.py、auth/lock.py

多 Agent 管线崩溃后的恢复同理:让各 Agent 把结构化状态导出到已知位置,恢复时由协调者读取清单并把相关状态注入各 Agent 的提示,而不是回放完整的协调者对话日志。

正确做法与反模式

  • 正确:给调查会话命名,用 --resume <名称> 精确接续。反模式:用 --continue 碰运气,结果接上了另一条无关会话。
  • 正确:用 fork_session 从同一份分析基线分出两条分支比较方案。反模式:在同一会话里轮流尝试两种方案,或每种方案都从零重新分析。
  • 正确:恢复后明确列出改动的文件与改动内容,要求针对性重读。反模式:什么都不说直接继续,或要求 Agent 重新探索整个代码库。
  • 正确:旧工具结果已大面积过时时,写结构化摘要并新开会话。反模式:坚持恢复一个充满过时文件内容的长会话。
  • 正确:在上下文大体有效时优先恢复,节省重复工作。反模式:每次都从零开始,浪费已有分析。

常见陷阱

  • "用 --continue 接上最近的对话"——题目强调"特定的某次会话"时,最近一次不一定是它,应选 --resume <名称>。
  • "用会话转录文件里的 UUID 配合其他参数"——可行但不是题目期望的最佳做法,命名会话更清晰。
  • "重新开始并再次读取同样的文件"——在上下文仍然有效时浪费了已有分析。
  • "恢复会话后让 Agent 重新扫描整个仓库以防遗漏"——应告知具体变更做定向再分析。
  • "把协调者的完整对话日志交给各 Agent 以恢复状态"或"让每个 Agent 各自维护状态文件、独立重载"——前者噪声大,后者失去协调,正确答案是结构化导出加协调者注入。

实操练习

目标:用 Agent SDK 体验恢复与分叉,确认两个分支互不影响。

  1. pip install claude-agent-sdk,在一个小项目目录中保存 session_lab.py。
  2. 运行脚本:第一步建立基线分析并记录会话 ID;第二步从基线 fork 出两条分支,分别探讨两种测试策略。
  3. 第三步恢复原始基线会话,询问它"刚才讨论过哪种测试策略",确认它不知道分支里的内容。
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage

async def run(prompt, **opts):
    session_id, text = None, ""
    async for msg in query(prompt=prompt, options=ClaudeAgentOptions(
            allowed_tools=["Read", "Glob", "Grep"], max_turns=15, **opts)):
        if isinstance(msg, ResultMessage):
            session_id, text = msg.session_id, msg.result
    return session_id, text

async def main():
    base_id, base = await run("概览这个项目的目录结构与核心模块,150 字以内。")
    print("基线会话:", base_id, "\n", base)

    a_id, a = await run("基于以上分析,设计'集成测试优先'的测试方案。",
                        resume=base_id, fork_session=True)
    b_id, b = await run("基于以上分析,设计'单元测试优先'的测试方案。",
                        resume=base_id, fork_session=True)
    print("分支 A:", a_id, "\n", a, "\n分支 B:", b_id, "\n", b)

    _, check = await run("我们之前讨论过哪种测试策略?", resume=base_id)
    print("基线会话自检:", check)

asyncio.run(main())

检查结果:a_id、b_id 与 base_id 三者不同;两个分支都能引用基线中的模块分析;恢复的基线会话回答"尚未讨论测试策略"。CLI 版本可用 claude --resume <id> --fork-session 做同样的实验。

自测清单

  • --continue 与 --resume <名称> 的区别是什么?什么情况下必须用后者?
  • fork_session 解决了什么问题?分叉后的会话与原会话是什么关系?
  • 恢复会话时,为什么要明确告诉 Agent 哪些文件改了?应该怎么说?
  • 在什么情况下,"结构化摘要 + 新会话"比恢复旧会话更可靠?原因是什么?
  • 多 Agent 管线中途崩溃,你会如何设计状态持久化与恢复?

对应题目(6)

题目归类由 AI 判断,仅供参考。

练习这 6 道题