ARCHITECTURE · 06
会话日志:DeepSeek Harness 的单一事实来源
直接答案
DeepSeek Harness 的会话(Session)是一份仅追加的类型化事件日志,是智能体完整交互历史的唯一事实来源。模型看到的对话历史不单独存储,而是从日志实时派生;回放就是拿同一组事件重新派生一遍。官方不变量是"模型可见即已记录":抵达模型请求的一切必须能从日志重建。仅追加日志:只往后写,从不改历史
Session 是一份仅追加的类型化 SessionEvent(会话事件)日志。每条事件携带:
- 单调递增的
seq(序号); - epoch 毫秒时间戳
time; - 按
type判别的data(数据载荷)。
所有事件必须是无损 JSON——Session.append 在运行时会校验,塞不进 JSON 的东西根本进不了日志。这条约束保证了日志永远可以被序列化、传输和回放。
核心事件词汇(按官方 session 文档口径)
按官方 docs/subsystems/session.zh.md(逐行对齐源码 SessionEventMap),核心会话事件共 13 种:
- 轮次与步骤:
turn/start、turn/end、step/start、step/end; - 消息:
user/message、assistant/chunk、assistant/message; - 工具:
tool/call、tool/result; - 其他:
todo/write、request/header、request/context、session/end-seed。
这些事件在循环哪个节点产生,见 Agent Loop页;tool/call、tool/result 的执行侧见工具系统页。两点澄清(这是常见误读):
- 没有
steering/message这个事件类型。中途引导(steering)产生的是user/message,只是它的 source(来源标记)不同。 - 上面是核心词汇。插件可以通过声明合并扩展事件类型,比如官方的 compaction(上下文压缩)插件就加了
compaction/*、hook/invoked等事件(机制见插件系统页第 6 节)。
派生历史:模型看到的是"投影"
模型历史由 deriveMessages()(派生消息函数)从日志算出来,规则包括:
assistant/chunk(流式碎片)只用于回放和界面保真,派生时跳过;- 内容为空、只有用量信息的
assistant/message也跳过; tool/result投影成一条带tool-result块的 user 消息送回给模型。
所以会话日志 ≠ 聊天记录:日志里有碎片、请求头、todo 快照等全部事实,模型看到的只是投影。这也解释了为什么改模型配置不影响旧会话——每个会话保留自己日志里记录的模型信息;以及为什么图片一旦进了会话日志,同一会话的后续请求仍可能携带它(本站教程实测口径,实测细节见《模型》教程)。
request/header:让"模型可见即已记录"落地
request/header 事件(EpochHeader)记录了一次模型请求的调用配置、渲染后的系统提示词和已组装的工具 schema。有了它,每次对话请求都是日志的纯函数——给定同样的日志前缀,就能重建模型当时看到的一切。这就是架构总览里那条不变量(第 5 节)的实现机制。
崩溃恢复与轮次结束原因
轮次结束原因(TurnEndReasonMap)有六种:
completed:完成;aborted:实时取消;blocked:被拦截;error:出错;max-tokens:超长度;interrupted:中断。
特别注意 interrupted:它是唯一不由循环发出的结束原因——由崩溃恢复流程合成,用来关闭崩溃时遗留的开放轮次,且不截断已经持久化的事件。interrupted ≠ aborted:前者是事后修复,后者是当场取消。
持久化与分叉
- 持久化是独立的能力接缝:
ctx.sessionPersistence定义 locate / create / append 等操作,后端有 JSONL(默认)和可选 SQLite。session/event是同步通知,落盘用固定批处理窗口,session/flush是排空检查点。 - 会话元数据(
SessionHeader)与日志分开存储:格式版本、工作目录、谱系、seed 边界、委派深度(delegationDepth,跨重启保留递归预算)、Agent 预设等。 - 分叉(fork):
ctx.sessions.fork(source, boundary?, childSessionId?)选取到指定边界为止的事件前缀开子会话;拒绝结束于开放轮次内的前缀——不会静默截断。子会话元数据带parentSession和seedLength,继承工作目录。
- 兼容性提醒:日志格式版本
SESSION_FORMAT_VERSION = 0,官方不提供兼容承诺;当前构建不认识的必需事件类型会被拒绝加载,而不是静默跳过(除非事件信封标了ignorable: true)。
EVIDENCE
证据与来源
本页包含:官方事实 / 教程实测
| # | 事实声明 | 状态 | 来源 |
|---|---|---|---|
| 1 | 仅追加日志、派生历史、回放重新派生 | 官方事实 | |
| 2 | 核心事件词汇 13 种(含 request/context、session/end-seed,无 steering/message) | 官方事实CV1 校正口径 | |
| 3 | steering 是 user/message 的 source 而非独立事件类型 | 官方事实CV1 校正口径 | |
| 4 | 插件经声明合并扩展事件(compaction/*、hook/invoked) | 官方事实 | |
| 5 | 事件携带 seq / time / data、isJsonValue 运行时校验 | 官方事实 | |
| 6 | 派生规则:chunk 跳过、空 assistant/message 跳过、tool/result 投影为 user 消息 | 官方事实 | |
| 7 | request/header(EpochHeader)内容、"模型可见即已记录"机制 | 官方事实 | |
| 8 | TurnEndReasonMap 六值、interrupted 由崩溃恢复合成 | 官方事实 | |
| 9 | 持久化 seam、JSONL 默认 + 可选 SQLite、批处理窗口、flush | 官方事实 | |
| 10 | SessionHeader 字段(delegationDepth、agentPreset 等) | 官方事实 | |
| 11 | fork API、拒绝开放轮次前缀、子会话元数据 | 官方事实 | |
| 12 | SESSION_FORMAT_VERSION=0、未知必需事件拒绝加载除非 ignorable | 官方事实 | |
| 13 | 改模型配置不影响旧会话、图片随会话日志携带 | 教程实测本站已验证内容 |
|