你的session并不属于你

本文基于 Earendil 团队的一篇文章展开分析,并结合我在本地 Claude Code 与 Codex 会话文件中的实测验证。
原文地址:https://earendil.com/posts/session-portability

一、你每天产生的 session,真的属于你吗?

我们每天都在用 Claude Code、Codex、OpenCode 对话、写代码、处理各种问题,日积月累会产生大量的会话 session。但你有没有认真想过:这些 session 到底属不属于我们?或者说,是不是完完全全属于我们?

当然,我们确实可以对 session 进行归档、查看和导出。但问题在于,我们能看到的部分,往往只限于「我们问了什么」和「agent 回答了什么」——也就是人类方便阅读的那一层文本。而一个真实的 session 远不止于此。

在 agent 给出最终回答之前,它要做一大堆动作:发起网页搜索、调用工具、解析返回结果、在多个子 agent 之间协调通信。这些才是真正消耗 token 的部分,也恰恰是我们看不到的部分。 某种意义上,agent 最后那段回答,是整个会话里最「不重要」、花费 token 最少的一环。

二、本地有文件,不等于 session 属于你

也许你会反驳:不对啊,Claude Code 和 Codex 的会话内容明明都保存在我本地。是的,文件确实在本地,但「文件在本地」和「内容可读」是两回事。

我把本地的会话文件翻了一遍,结果挺有意思。

Claude Code 把每个会话存成 JSONL 文件,路径长这样:

~/.claude/projects/<工作目录>/<sessionId>.jsonl

如果这个会话派生了子 agent,还会在同目录下生成:

~/.claude/projects/<...>/<sessionId>/subagents/agent-<hash>.jsonl

Codex 则按日期分目录存放所谓的 rollout 文件:

~/.codex/sessions/YYYY/MM/DD/rollout-<时间戳>-<uuid>.jsonl

外加一份索引 ~/.codex/session_index.jsonl,记录每个会话的 id、标题和更新时间。

文件都在,结构也清楚。但当我打开这些 JSONL,逐行去看 agent 真正的「思考过程」时,看到的却是这样的内容。

Claude Code 的 thinking,是一串加密签名

在某一个项目的会话文件里,我统计了一下:主会话有上千个 thinking block,子 agent 文件里还有上百个。每一个 thinking block 都长这样

{
  "type": "thinking",
  "thinking": "",
  "signature": "EqoCCokBCBAYAipAXWNZFG5y0zi++xWNeppfhKTXG9AuItV6qUXfdwE/+Ow86IixXuYlhw9zUEaV20CJ..."
}

thinking 字段是空的,signature 是一段 base64 密文,短的几百字符,最长一条有两万多字符。也就是说,模型真正在脑子里想的那段过程,被加密封印了,本地文件里只留下一串我们解不开的签名。这正是 Anthropic 的设计:加密的完整思维链放在 signature 里,可读的「思维文本」即便开启也只是另一个模型产出的摘要,而非原始思维链。

Codex 的 reasoning,同样是一坨密文

Codex 这边也差不多。我抽查了本地几百个 rollout 文件,其中有近两百个文件里出现了 encrypted_content 字段,全部出现在 reasoning 类型的记录里。典型的一条长这样:

{
  "type": "reasoning",
  "summary": [{"type": "summary_text", "text": "**Selecting frontend-design skill**"}],
  "content": null,
  "encrypted_content": "gAAAAABpppejjPDm4EpcRasgitLFhetlXV7_QsFuNw2hhE6pBQOe9V1QIyjdPeHFZKMSU4YZl8RqhF1ABn86BDIy..."
}

summary 只给了一句话摘要(这里仅是「正在选择某个技能」),而真正消耗算力、被你计费的那段推理,全塞进了 encrypted_content 这串 Fernet 风格的密文里。客户端拿不到密钥,解不开。

值得欣慰的地方——并非全部都被封印

公平地说,两家也并非把所有东西都藏起来。

Claude Code 在上下文超限做压缩时,会生成一个 isCompactSummary: true 的记录,内容是完全可读的,写明了「这个会话是从之前一个用尽上下文的对话延续而来的,之前的主要目标和进展如下……」。我在本地全量检索 encrypted_content,Claude 的项目目录下一个都没有——它的压缩路径是可读的。

Codex 这边,当上下文需要交接时,本地存的是一段可读的 handoff summary(「另一个模型已经处理过这个问题,这是它的思维摘要,你在此基础上继续,避免重复劳动」)。这也是可读的,只不过它是 Codex 客户端自己做客户端侧压缩,而不是走 OpenAI 服务端那个文档明说「不可人类解读」的 opaque compaction。

更有意思的是子 agent 通信。文章特别点名了 Codex 在 2026 年 6 月的一个 commit(Encrypt multi-agent v2 message payloads),说父 agent 调用 spawn_agent 时,message 参数会被加密,子 agent 之间的消息也只剩 encrypted_content。但我翻本地文件时发现:我这台机器上的 spawn_agent 调用,message 参数居然是明文的,子 agent 的 commentary 消息也是明文。原因很简单——我的 Codex 配置里 model_providercustom,接的是第三方端点,没走 OpenAI 官方的 Responses Multi-agent 加密路径。

这恰恰反证了文章的判断:这种加密是 OpenAI 官方服务端的行为,换个 provider 就能绕开。 但这也意味着,一旦哪天切回官方端点并启用 multi-agent v2,子 agent 到底被交代了什么任务,就会立刻从「可审计」变成「一团密文」。

三、为什么这件事很重要

我们作为用户,花真金白银购买 token 让 agent 解决问题,理应能清楚看到这些过程信息,因为这是我们自己花钱产生的数据。agent 供应商当然可以打着「为了人类阅读方便」的旗号,按他们认为合适的方式去处理和呈现,但当我们想看细节时,他们应该提供这种能力。

更深层的问题在于可迁移性。当这些 session 真正属于我们、我们能拿到它的全部细节时,我们就可以方便地把一个进行中的任务从模型 A 切换到模型 B。因为新模型在接手时,不只需要人类方便阅读的文本,它更需要那些内部的工具调用细节、推理上下文、子 agent 之间传递的任务说明。

而模型供应商把这些细节做成加密的、并且关键部分只存在自己服务器上,某种程度上就是在构建自己的围墙花园,想以此来圈住用户。你在我这积累了几天的上下文?抱歉,别的模型看不懂那段密文,你只能继续用我。

文章里有一段话说得很直白:所谓 encrypted_content,名字听起来像是为你设计的隐私功能,实际上是一个只有服务商能打开、对你不透明的胶囊。更准确的叫法应该是 provider-sealed state(服务商封印状态)。这种加密不向推理服务商隐藏数据,它向的是你。

四、检测 session 到底属不属于你

文章给了五条很实用的检测标准,我也用它们逐条对照过本机:

  1. 可检查(Inspection):用户能否看到模型看到了什么、工具做了什么、各个 agent 之间传达了哪些信息?
  2. 可导出(Export):这个会话是否自包含,除了能下载的普通文件外,不依赖任何外部东西?
  3. 可重放(Replay):是否有其他实现方式能重建语义等价的上下文?——带着加密 signature / encrypted_content 切到别的模型,那部分等于丢了。
  4. 可审计(Audit):人类能否在事后解释系统为什么采取了某个动作?
  5. 可删除(Deletion):用户能否识别并移除所有依赖该会话的服务端副本?

五、满足什么条件,才算 session 完全属于你

文章呼吁的七条标准,我把它们当作一份理想清单:

  1. 本地事件日志是权威存储。服务器存储可以镜像或加速它,但客户端无需引用任何服务端 ID 就能重建会话。
  2. 存储是显式的store: false 应该易用、有文档、最好默认开启;凡是需要保留数据的特性,在使用时就该明确告知。
  3. 没有任何不透明元素能单独承载语义。加密推理、压缩项、工具签名可以为了同厂商的质量而存在,但每一个都必须配一份可读的、与厂商无关的交接表示。
  4. 托管工具必须有全保真日志。记录全部输入、输出、证据、过滤步骤、来源、时间戳和内容哈希——而不只是一段漂亮答案加几个引用。
  5. 子 agent 通信可审计。为每个 agent 保留完整可读的任务、消息、结果、谱系、所用模型和工具权限。
  6. 压缩结果可检查。返回可读摘要、生成摘要所用的指令,以及足够的上下文来理解哪些内容被丢弃了。
  7. 工件可导出。文件、容器输出、搜索快照、生成的媒体,都能下载到本地内容寻址的归档里。

六、关于蒸馏:道德不应是单行道

文章最后讨论了大模型蒸馏的问题,态度简单明了:Distillation Is Great Actually(蒸馏其实是好事)

Anthropic 一方面自己大量抓取公开互联网信息、把书拆开来扫描以训练模型,另一方面却指责 DeepSeek、Moonshot、MiniMax 等实验室对其模型进行「蒸馏攻击」。文章明确表示不支持这种双标。

立场很清楚:一切本应是开放的,任何实验室都可以公开获取公开资源;而你交付给用户的内容和输出,也应当完全归用户所有。Anthropic 和 OpenAI 这些闭源厂商,从公开互联网获取内容训练自己的模型、通常无需事先征得个人许可,却同时坚持其他机器不得从这些实验室生成的输出中学习。这种道德上的不对称显而易见。

文章认为,对蒸馏的态度应从敌视转向支持。蒸馏能把昂贵的尖端能力转化为更小、更便宜、更高效的模型——可以在本地运行、在受限硬件上运行、由用户自己控制。它能增加竞争、在某个 API 消失时保住能力、减少常见任务的算力和能源消耗。

七、用户最低限度的自由

用户应该能够关闭账户、保留会话状态,并把会话交给另一个模型继续处理。新模型可能会有不同表现,可能会提出问题,也可能不如旧模型好用。但它不该面对着一团密文,而旧模型当年却能清清楚楚地看到你的历史、计划和委托任务。

我们不反对服务商开发更优秀的状态管理 API。我们反对的是:把更好的性能和更弱的用户控制捆绑在一起。

状态存储应是可选的;托管工具应可被观察;压缩过程应可读;agent 间通信应可审计;理想情况下,不透明的推理要么并不真正不透明,要么至少应提供一份可移植的交接表示。蒸馏应是一条让能力变得更可用的路径,而不是一个被用来垒高围墙的借口。

关于 Earendil

写下这篇文章的 Earendil(earendil.com)是一家 2025 年成立的营利性公益公司,总部横跨维也纳与旧金山,宗旨是「用软件和开放协议增强人类的能动性」。团队由两位开源老兵创立:Armin Ronacher(Flask、Jinja2、Click 作者)与 Colin Daymond Hanna;2026 年 4 月,pi agent 的作者 Mario Zechner 带着项目加入,成为第三位核心成员。

团队目前主要在做两款产品:
pi 是一套开源的 AI agent 工具包与编码 agent CLI(统一 LLM API、agent loop、TUI,本文的本地验证正是跑在它上面);
Lefos 则是一个主打数据自主权的个人「互联网花园」。

暂无评论

发送评论 编辑评论


				
上一篇