ToolBox
返回博客列表
模型看到的每一步,都被记下来了:DeepSeek Harness 敢给企业用的底气

模型看到的每一步,都被记下来了:DeepSeek Harness 敢给企业用的底气

「模型所见,必入日志」——一句话翻到后面才明白是整套设计的地基。这篇拆 dsh 的会话层:为什么日志不是聊天记录,那条运行时不变式凭什么保证真实,回放/分叉/恢复怎么从日志长出来。

2026年8月22日6 分钟DeepSeek · AI智能体 · Agent · 开源

上周把 DeepSeek 开源的 Harness 源码教程从头翻完,十五个章节,有一句话我在三个地方都看到了它的影子:「模型所见,必入日志」。初看平平无奇,翻到后面才明白,这句话是整套设计的地基,也是它敢喊出「能上生产」的底气所在。

DeepSeek Harness 事件日志示意

先理解一个问题:agent 出事了,你拿什么复盘

企业用 AI 最怕的不是它笨,是它干了什么你完全不知道。

传统程序每一步都在代码里写着,出错能查日志、能断点、能回放。agent 不一样,它的每一步都是模型现场决定的,今天这么干明天那么干,你根本没法预判。要是它半夜自己跑了个什么操作,改了个不该改的文件,第二天你除了看最终结果,中间过程全是黑箱。

市面上大多数 agent 框架对这件事的答案是:存对话记录。你翻聊天记录,能看到它说了什么,但看不到它「当时脑子里装了什么、为什么这么想、调用了哪些工具、工具返回了什么」。

dsh 把这件事换了个做法:不存「对话」,存「日志」。

这俩有什么区别?区别大了。

日志不是聊天记录,是唯一真源

dsh 的会话层(packages/session)有一个核心设计:一段对话不是一个「消息列表」,而是一份只能追加的事件日志

模型说的每一句话、每一步思考、每一次工具调用、工具的返回结果,全部是这条日志上的一条事件。turn/startassistant/chunktool/calltool/result,各有各的事件类型,按时间顺序一条条追加,只增不改。

关键在这一句。模型的对话历史不是单独存的,是每次需要时从这份日志现场「投影」出来的。源码里叫 deriveMessages()——从日志推导出模型要看的消息。

这意味着什么?日志才是唯一的真相,对话历史只是它的一次投影。你随时可以从这份日志重新投影出任意时刻的模型视角,这就是 fork、恢复、回放这些功能的地基。市面上大多数框架是「存一份对话」,dsh 是「存一份流水账,对话随取随用」。

那这条流水账,凭什么保证真实?

那条不变式,才是真正的狠活

到这里你会说:这不就是事件溯源吗,微服务早就用烂了。

区别在后面这句。dsh 定了一条运行时不变式,而且用代码断言保证:凡是进入模型请求的内容,必须能从日志里重建出来。

反向说更清楚:你看到日志里有什么,模型就看到了什么;模型看到的东西,日志里一定找得到。两者画等号,中间没有漏网之鱼。

这条不变式对插件作者是个硬约束——你想往模型上下文里塞点新东西,不能直接塞,必须先在日志上定义一个新事件类型,再让这个事件能被投影成模型看到的文本。麻烦是麻烦。但换来一个极大的好处:任何时候,你都能精确知道模型当时看到了什么

出事了,翻日志,一步步还原模型当时的完整视角——它看过哪些文件、被注入了什么上下文、工具返回了什么、它在什么状态下做的决定。这不是事后补的审计报告,是本来就在那儿的、一分不少的真实记录。

那这些记录能拿来干嘛?

重放、分叉、恢复:日志派生的一切

因为对话历史是从日志投影的,一系列「高级功能」就成了顺水推舟:

回放。把日志重放一遍,等于把 agent 干过的活重演一遍,UI 上能看到每一步的原始 chunk 流,不是事后整理的摘要。

分叉(fork)。把一份日志复制一份,从某个节点开始改一个分支继续跑。对比两个方案,各跑各的,互不干扰。这比「复制整个对话」轻量得多,因为日志是结构化的,不是一大坨文本。

恢复。进程挂了,日志还在,下次启动从日志重建会话,agent 记得自己干到哪了。forkresume、transcript、遥测,全是这条流上长出来的。

对企业来说,这三个能力对应三个实际场景:出了事故能回放定位(审计)、改方案能分叉对比(实验)、跑挂了能无缝恢复(容错)。

说句公道话

这套设计不是没代价。每条事件都要定义类型、写投影逻辑,插件作者的学习成本比「往 messages 里 push 一条」高得多。日志只增不改,长期跑会有体积膨胀的问题,所以 dsh 还配套了压缩(compaction)机制,把老日志折叠成摘要。

但取舍很明确:为了「可审计、可回放、可恢复」这三件事,多付的这点复杂度是值得的。尤其企业场景,AI 一旦开始碰文件、跑命令、改配置,可审计性就不是可选项,是底线。

翻到第 9 章我还看到一层设计,审批没人应答时默认拒绝(fail-closed),跟日志这套是同一个思路:宁可多留痕迹、多拦一步,也不放过一次不可追踪的操作。上生产这件事,dsh 把「留痕」和「把关」两件事都做了,这是它跟那些玩具级框架最大的分水岭。

完整教程在 https://tool-ix.cn/tutorials/deepseek-harness

首发于公众号「键盘漫笔」