DeepSeek Harness 可追溯性实战:会话日志的 resume、fork 与 replay

DeepSeek Harness 可追溯性实战:会话日志的 resume、fork 与 replay

调试 Agent 最痛苦的是什么?是「它刚才为什么这么做,我事后查不出来」。你只能看到最终结果,看不到它中途看到了什么、调了哪个工具、模型到底返回了什么。

DeepSeek Harness(dsh)给出的解法,是一个贯穿始终的设计原则------「模型可见即已记录」 。这篇我们就实战一下:这条原则怎么落地,resumeforkreplay 到底怎么用。

一、先理解事件流:会话日志的骨架

DSH 把一个会话的过程,记成一条只增不改(append-only)的事件流。前几篇已经见过这些事件名,这里我们按层级重新梳理:

复制代码
turn/start                       # 一个轮次开始
  ├─ agent/pre-step              # 实时扩展点:决定模型看到什么
  ├─ step/start                  # 一个步骤开始
  │    ├─ user/message           # 追加用户消息(持久事件)
  │    ├─ agent/request          # 实时扩展点:即将发请求
  │    ├─ llm/stream             # 实时:模型流式输出
  │    ├─ assistant/chunk*       # 持久:模型的每个 token 块
  │    ├─ assistant/message      # 持久:完整回复
  │    ├─ tool/call*             # 持久:模型发起工具调用
  │    ├─ tools/pre-execute      # 实时:工具执行前(可拦截)
  │    ├─ tools/execute          # 实时:工具执行中
  │    ├─ tools/post-execute     # 实时:工具执行后
  │    ├─ tool/result*           # 持久:工具返回结果
  │    └─ step/end
  ├─ agent/turn-stopping         # 实时:轮次收尾
  └─ turn/end                    # 持久

留意标注:持久事件 (带 * 的)写进日志,是「事后可重建」的依据;实时扩展点是「当时可干预」的钩子。两条线分工明确------前者是黑匣子,后者是方向盘。

二、「模型可见即已记录」到底强在哪

这句话不是口号,而是一条运行时不变式(invariant)

凡是抵达模型请求里的内容,都必须能从日志中重建。

换句话说,模型看到的每一个字,日志里都有据可查;反过来,日志里没有的,模型就一定没看到过。这堵死了 Agent 里最隐蔽的一类 bug------「模型其实看到了 A,但你排查时以为它看到的是 B」。

为了维持这条不变式,DSH 有一个关键设计:deriveMessages() 能从日志投影出模型的完整历史 。也就是说,你不需要单独存一份「模型历史」,它随时能从事件流里算出来。而原始的 assistant/chunk 事件,则保证了回放和 UI 渲染的逐字保真(连流式输出的抖动都能还原)。

三、实战一:resume------中断后接着跑

Agent 跑长任务,最怕中途断掉重来。DSH 的 resume 让「接着上次跑」变成可能。

sh 复制代码
# 列出一个会话
dsh session list

# 从某个会话继续
dsh session resume <session-id>

底层逻辑很简单:会话日志是 append-only 的,resume 就是把日志重新投影成模型历史,然后接着往下追加。模型看到的是「之前完整发生过的一切」,所以它的回答能无缝衔接,而不是失忆。

对开发者来说,这解决了长任务的断点续跑;对评测来说,它意味着你可以从任意一个历史节点精确复现,而不是「大概重跑一遍」。

四、实战二:fork------从一个点分出对照实验

做 Agent 评测时,一个经典需求是:在同一个起点,测试「给不同的提示 / 用不同的工具 / 换不同的模型」会有什么不同结果

fork 就是干这个的:

sh 复制代码
# 从某个会话的某个点,分出一个新分支
dsh session fork <session-id> --at <step-id>

分叉之后,你得到一个和原会话共享前缀、但之后各自独立的新会话。于是你可以:

  • 分支 A:继续用模型 X;
  • 分支 B:从同一点切到模型 Y;
  • 分支 C:同一点但注入一段不同的 system prompt。

最后对比三个分支的走向,就是一次干净的对照实验(A/B test)。没有 fork 的话,你只能手搓三份输入,还保证不了「起点完全一致」。

五、实战三:replay------精确重现一次执行

resume 是「接着跑」,replay 则是「原样重放」。

当你复现一个 bug 时,最想要的是「一模一样地再来一次」。但 Agent 有随机性(temperature、工具执行时机),直接重跑往往对不上。replay 借助日志里的 assistant/chunk 等持久事件,把一次执行逐字重放出来:

sh 复制代码
dsh session replay <session-id>

它的价值在于:把「偶发问题」变成「可稳定复现的问题」。一旦能稳定复现,bug 就解决了一半。

六、实战四:telemetry------把事件流变成数据

日志不只是给人看的,更是喂给分析系统的。DSH 的 telemetry 就是「基于事件流做统计」的能力。

有了这条完整的事件流,你可以轻松算出:

  • 一次任务烧了多少 token、流式延迟多少;
  • 哪些工具被高频调用、哪些从来没人用;
  • 模型在哪一步反复空转(同一工具连续调用 N 次);
  • 一个任务失败前发生了什么(往前翻事件流即可)。

配合上一篇文章讲的类型化事件,你可以写一个 telemetry 插件,订阅 assistant/messagetool/result 等持久事件,把数据落到你自己的分析管线里------这又回到了「一切皆插件」:可追溯性本身,也是可扩展的

七、一条硬约束:新增能力,就要新增事件

最后说一个容易忽略的点。因为「模型可见即已记录」是条不变式,所以它反过来对你(插件开发者)提出了一个要求:

你每新增一项「模型可见」的能力,就必须同时新增一个对应的会话事件。

举个例子:如果你写了个插件,往请求里注入了一段「检索到的知识」,那你就不能只注入、不记录。你必须同时 emit 一个会话事件,把「这段知识是什么、注入到了哪一步」写进日志。否则,一旦模型因为这段知识做出了错误决策,事后你永远查不到原因------因为日志里根本没有它。

这条约束看似麻烦,实则是在从根上杜绝「模型看到了什么,日志里却查不到」的黑箱。理解了它,你就理解了 DSH 为什么敢把可追溯性当卖点。

八、小结

DSH 的会话日志不是一个「顺手记一下」的附属功能,而是它的数据底座resumeforkreplaytelemetry 全部派生自同一条 append-only 事件流,而「模型可见即已记录」这条不变式保证了这条流的可信

对要调试 Agent、复现 bug、做评测的开发者来说,这一套的可迁移价值很高------你不再是「猜它为什么这么做」,而是「回放现场看它到底怎么做」

下一篇,聊一个 Agent 绕不开的话题:安全。DSH 的沙箱机制(Landlock / Seatbelt / ACL)是怎么在系统层面把 Agent 关进笼子的。


参考:deepseek-ai/deepseek-harness 会话与可追溯性文档。

相关推荐
爱吃苹果的梨叔1 小时前
AI 算力监控中心怎么建?分布式坐席 + 大屏联动 + 过程回放
人工智能·分布式·python
JarmanYuo1 小时前
YOLO 涨点研究(六):网络结构改进之小目标增强篇1——无人机视角下的车辆与行人检测
人工智能·pytorch·python·yolo·计算机视觉·无人机
格林威1 小时前
C# 相机图像阴影校正:使用OpenCvSharp实现工业相机阴影平场校正功能
人工智能·数码相机·opencv·计算机视觉·c#·机器视觉·工业相机
烬羽1 小时前
给 Agent 一个检索式记忆:把对话历史存进 Milvus,该记的都记得
javascript·数据库·agent
桃西西呀1 小时前
9月1日起AI图要被标记了,机器怎么一眼认出哪张是 AI 画的?
人工智能·机器学习·llm
招财小梗1 小时前
沈阳AI企业咨询可定制数字化方案吗?
大数据·人工智能·python
其实防守也摸鱼1 小时前
教育信息技术应用创新---基础软件信息赛(题库)
大数据·运维·人工智能·web安全·自动化
Zzj_tju1 小时前
Prompt Injection 防御:隔离不可信上下文的最小复现
人工智能·深度学习·机器学习·自然语言处理·prompt
合合技术团队1 小时前
论文解读|合合信息与上海交通大学打造DocIQ模型,AI为文档图像质量“做体检”
人工智能·计算机视觉