模块定位
Agent 处理的不只是短文本。用户会上传图片、文件,工具会产生大结果,UI 要展示附件,持久层要避免把所有大对象塞进 session log。DeepSeek Harness 用 storage、attachment、spill 三组能力处理这些问题。
源码入口:
packages/storage/*packages/attachment/*packages/spill/*packages/client/ui-attachmentdocs/subsystems/attachment.mddocs/subsystems/spill.mddocs/subsystems/storage.md
Storage
Storage family 是非 session 存储 hub。它把“通用存储能力”从 session persistence 中拆出来。典型 backend 包括 JSON、SQLite,以及 domain form。
为什么不直接都塞 session log?因为 session log 是运行事实账本。大对象、附件正文、可复用 blob、工具 spill 内容,不一定适合以内联 JSON 事件保存。
Attachment
Attachment family 负责 durable attachment identity、validation 和 local content-addressed storage。它给用户上传和模型引用之间提供稳定身份。
1 | flowchart LR |
附件进入模型上下文时,关键不是“文件在磁盘哪个临时路径”,而是有一个 durable identity 和可验证内容。
Spill
Spill family 处理工具结果过大时的外置存储。工具结果如果无限制进入 model context,会造成:
- token 爆炸。
- UI 卡顿。
- session log 过大。
- replay 成本失控。
Spill policy 可以把 oversized result 替换成 preview + locator,让模型知道有完整内容可取,但不把全部内容塞进当前上下文。
与 Tool Pipeline 的关系
Spill 不应该是工具 body 自己临时 if length > ...。更合理的位置是在 tool result 的后处理或 spill policy 扩展点里,因为只有那里能统一处理不同工具的输出大小和模型可见内容。
UI 怎么展示
ui-attachment 提供 draft-image rail、message gallery、lightbox。工具 presentation 也可以引用附件或 locator。UI 渲染应依赖 durable id 和 presentation metadata,而不是临时本地路径。
常见坑
第一,附件路径不是 durable identity。路径可能过期、搬迁、权限变化。
第二,spill preview 不能假装是完整结果。必须明确 truncated/locator 语义。
第三,不要把二进制或大文本直接塞进 session event。
第四,UI replay 要用 durable metadata,而不是 upload 时的 live object。
继续读源码
packages/storage/README.mdpackages/attachment/README.mdpackages/spill/README.mdpackages/client/ui-attachment/README.mdpackages/core/tools/README.md#tool-owned-ui-presentation