Agent SDK 的 session 机制我理解错了两次

Claude 中文知识站 Lv4

标题不是标题党,我是真的理解错了两次。而且每次都是踩坑踩出血才改认识。

我以为的 session 和实际的 session

刚用 Agent SDK 那会儿,我对 session 的心智模型是这样的:一个 session 就是一坨对话历史的 JSON 数组,保存在 .claude/sessions/<id>.json,resume 的时候把它塞回 messages 参数继续聊。

简单直接对吧?但这个理解挪到实际场景里全是问题。

第一次撞墙:我让 agent 修改了一个文件,然后中断 session。下次 resume 的时候它突然说”我刚才已经把 config.ts 改成 xxx 了”,但那个文件我在中断后手动改回过。agent 的说法和现实不一致,它给出的建议全是基于一个过时的世界模型。

第二次撞墙:我并行起了两个 session,一个让 agent A 重构 auth/ 目录,一个让 agent B 重构 db/ 目录。跑着跑着发现 agent B 突然开始改 auth/ 的文件。我以为是工具权限没隔离好,查了半天才发现是 session 之间有上下文泄露。

这两次之后我去翻了源码,才对 session 有了靠谱的认识。

session 到底存了什么

Agent SDK 的 session 文件远不止对话历史。我把一个中等规模的 session 文件扒开看过,里面大致有这几块:

  • messages 数组:对话历史,每条带 role、content、tool_uses、tool_results
  • filesystem snapshot:agent 在这个 session 里碰过的所有文件的初始快照 + 修改 diff
  • tool_call_history:每次工具调用的输入、输出、耗时、成功与否
  • hook_state:用户注册的 hook 的状态(比如计数器、缓存)
  • context_usage:当前 context window 用了多少 token,哪些可以压缩
  • metadata:agent id、model、创建时间、父 session、子 session

一个跑了 2 小时的 code review session,文件大小大概 47MB。跑了 4 小时的代码迁移任务,file snapshot 部分膨胀到 83MB。

明白了 session 存了什么,第一次撞墙的那个现象就解释清楚了——agent resume 时会基于 filesystem snapshot 判断”我改过什么”,但它不会去实际读磁盘比对。我在中断期间手动改回文件,这个信息 session 无感知。

resume 和 continue 的真实区别

SDK 其实有两个恢复命令:resumecontinue。官方文档我粗读过几遍,一直没搞清楚差别。后来自己做了实验才弄明白。

continue 是从最新 checkpoint 接着跑。checkpoint 是 session 运行过程中定期保存的”当前完整状态”。continue 等于说”这个 agent 刚才在干活,打了个盹,现在接着干”。

resume 是从头回放 session。它会读所有 messages,重新让 Claude 回答一遍——区别是 Claude 看到完整历史之后,再继续新的对话。resume 适合”这个 session 我之前结束了,现在想基于它的上下文继续问问题”。

两者的一个关键差异:continue 保留 filesystem snapshot,resume 不保留(会重新基于当前磁盘建立快照)。所以手动改过文件后应该用 resume,而不是 continue。这是我第一次撞墙的教训。

多 session 并行的污染

第二次撞墙让我学到 session 隔离没想象中那么彻底。

我并行跑两个 agent,分别用两个 session。默认情况下它们共享同一个 .claude/ 目录,包括 hooks/agents/ 配置、甚至 MCP server 的连接池。

具体是怎么污染的?我后来复盘发现:

  1. agent A 的一个 hook 往 .claude/shared-state.json 写了当前正在处理的文件列表
  2. agent B 的另一个 hook 读取了这个文件做”避免重复处理”的判断
  3. 两个 hook 是我自己写的,初衷是单 session 用
  4. 并行跑时 B 以为 A 在处理 auth/,就”帮忙”处理 db/ 以外的东西……但我给 B 的 prompt 本来只让它改 db/

根本原因是我的 hook 实现不对,没做 session 隔离。但 SDK 默认也没强制这个——它给你的是共享目录,你自己要用 session id 做 namespace。

解决方式:所有涉及共享状态的 hook,key 都加 session id 前缀。或者索性每个 session 用独立的工作目录(CLAUDE_AGENT_SESSION_DIR 环境变量能覆盖)。

误删 .claude/sessions 的事故复盘

这个事儿挺惨的。

当时我正在清理一个项目仓库,因为 .claude/ 目录整个被 .gitignore 了,我本地又装了 4 个不同 agent 的临时 session(累计 1.2GB),就顺手 rm -rf .claude/sessions/

结果是当天下午我要演示一个客户 demo,那个 demo 依赖一个跑了 40 分钟的 session——里面有 agent 分析客户代码之后建立的整套 mental model。演示前 30 分钟我想 resume,发现 session 全没了。我当时直接懵住。

后来的 debug 流程:

  • 先看 trash:Windows 回收站没有(rm -rf 走的是直接删除)
  • 翻备份:我本地没备份。客户那边也没。
  • 找日志:agent 运行时的部分 tool_call 日志在 stdout 里,我翻出终端 scrollback,救回了大概 60% 的关键上下文
  • 临时拼凑:基于日志拼了一份简化的 system prompt,在新 session 里手动喂给 agent,让它”假装记得”

演示凑合过了,但一身冷汗。

这件事的教训有几条。第一,session 目录要主动备份,至少一周一次。第二,生产环境的 session 目录最好挪到工作目录外(用 CLAUDE_AGENT_SESSION_DIR=/data/agent-sessions 这种),避免被项目清理脚本误伤。第三,session 里的上下文本身是资产,跟代码一样值钱。

基于 session 做增量 code review

踩完坑之后,我反过来把 session 的特性用在一个场景上——增量 code review。效果挺好,写出来分享下。

场景:我们仓库每天有 40+ PR,一个 reviewer agent 跑一次要十几分钟(要加载代码、构建依赖图、分析)。如果每个 PR 都从零起 session 太慢。

我的方案:

  1. 每天凌晨起一个基础 session,让 agent 把整个仓库扫一遍,在它的 mental model 里建立依赖图、模块职责、团队约定等。这个 session 跑完大概 14 分钟,产物是一个 snapshot。
  2. 每个 PR 来了,我用 resume 起一个新 session,继承那个 snapshot 的上下文。然后只把 PR 的 diff 喂给它。
  3. agent 基于已经有的全局理解 + 这个 diff,做 review。单 PR review 时间降到 47 秒左右。

关键点是 resume 能继承完整的对话历史和 filesystem snapshot,让 agent 不用重新加载整个仓库。

这套方案的 context 管理 我在另一篇里展开过。

一些小细节

  • session 目录里的文件名是 session id(UUID),不是人类可读的。想找特定 session 最好在工作流里显式指定 id。
  • session 文件不压缩,纯 JSON。如果你 session 特别多可以自己 gzip 归档。
  • CLAUDE_AGENT_SESSION_DIR 支持相对路径但会基于 agent 启动时的 cwd,容易混淆,建议用绝对路径。
  • session 里的 filesystem snapshot 只记录 agent 读过或写过 的文件,不是整个工作目录。所以 snapshot 通常比想象的小。
  • resume 的时候 Claude 会重读整个历史,这个过程如果历史太长会触发 prompt caching——合理用缓存能把 resume 成本降下来。

写在最后

session 这块儿看起来是个细节功能,但它其实是 Agent SDK 区别于”调 API 写 agent loop”的核心设计之一。理解它才能理解 Agent SDK 为什么这么组织代码。

误解它的代价就是我这两次撞墙的学费。希望看到这篇的人不用再交一遍。

继续读
理解了 session,下一步就是把 agent 的运行过程监控起来。SDK 的 hook 是可观测性金矿,我挖出了 7 类事件:Agent SDK 的 hook 是可观测性金矿
  • 标题: Agent SDK 的 session 机制我理解错了两次
  • 作者: Claude 中文知识站
  • 创建于 : 2026-04-18 19:28:00
  • 更新于 : 2026-04-19 14:51:00
  • 链接: https://claude.cocoloop.cn/posts/agent-sdk-session-state/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论