DeepSeek Harness 每轮固定 30 秒:Tool Call 调度分析

作者
DeepSeekAgent.io 编辑部
发布
更新

DeepSeek Harness 社区出现了一类很有辨识度的延迟:模型通常在 3~5 秒内已经生成回复,涉及工具调用时,工具却总要等到本轮开始约 30 秒后才执行;即使本轮没有工具,turn/end 也会在接近 30 秒时才出现。延迟集中在每轮的第一个动作,后续工具调用又恢复正常。

这不是普通的“模型慢”。固定时长、稳定复现和首动作集中三个特征,更接近流式响应结束信号、用量结算或调度器兜底计时器之间的同步问题。

事件时间线说明了什么

社区记录中的一个工具轮次具有如下顺序:

  • 约 6.04 秒:收到 assistant/message 与 tool/call;
  • 约 30.05 秒:出现 job/registered;
  • 约 30.59 秒:得到 tool/result。

另一个纯文本轮次在约 1.76 秒已经完成文本和 step/end,但 turn/end 仍延迟到约 30.03 秒。两条时间线共同说明,模型输出本身已经到达,等待发生在“本轮何时被视为可继续或可结束”这一层。

如果只是 IM 轮询、网络往返或某个工具启动缓慢,纯文本轮次不应出现同样的固定尾部等待;如果只是模型推理慢,assistant/message 也不会提前二十多秒到达。

为什么固定 30 秒值得优先排查兜底路径

随机延迟通常来自网络拥塞、排队或机器负载。接近常数的 30 秒更像超时配置。可能的路径包括:

  1. Provider 已发送文本或 Tool Call,却没有及时发送 DSH 期望的最终结束事件;
  2. 使用量或响应尾部仍在等待,调度器不敢立即提交首个工具任务;
  3. 某个适配层把“已收到 Tool Call”和“响应流已安全关闭”绑定在一起;
  4. 30 秒兜底计时器到期后,系统才补发完成信号并推进状态机。

这些仍是由事件序列推导出的诊断方向,不能替代具体版本的调用栈。最有价值的下一步,是把 Provider 原始流事件与 DSH 内部事件放在同一时间轴上,而不是继续笼统测试“网络快不快”。

一套可复现的排查方法

先建立三个最小样本:纯文本回复、一次简单工具调用、连续两次工具调用。每个样本记录以下时间点:

  • 请求发出;
  • 首个模型 Token;
  • Tool Call 块到达;
  • Provider 结束原因与用量到达;
  • step/end、turn/end;
  • job/registered、tool/result。

然后依次对照 Web UI 与 IM、不同 Provider、是否启用插件、是否启用推理输出。只改一个变量。如果所有入口都在第一个动作等待 30 秒,问题更可能位于共用的模型适配或 Turn 调度层;如果只有一个 Provider 触发,应重点检查它的结束事件映射。

社区案例已经排除了若干直觉原因:IM 轮询、Session 日志上传、记忆插件、Anthropic SDK 的简单 drain,以及常见的 streamIdleTimeout 设置都无法解释全部现象。排查应保留这些反证,避免重复绕路。

对用户体验和成本的影响

固定等待不会直接增加模型输出 Token,却会放大整个 Agent 流程的墙钟时间。需要用户确认、文件读取或搜索的短任务,每轮多 30 秒,很快就从十几秒变成几分钟。自动化任务也可能因外层超时提前失败,随后重试并产生额外调用。

在根因修复前,可以减少不必要的轮次:把明确目标、输入文件和验收条件一次给全;允许并行读取时合并工具请求;为自动化设置足够的总时限,同时限制重试次数。不要通过无限增大超时掩盖事件状态机问题。

这篇分析也可与多步工具调用中的 redacted_thinking 中断对照阅读:前者是完成信号推迟,后者是响应块类型未被适配器接受。两者都会表现为 Agent 卡住,但事件时间线完全不同。

参考资料

常见问题

模型很快返回文字,为什么工具仍没有执行?

文字到达不等于本轮响应流已经被适配器确认结束。应检查结束原因、用量事件、turn/end 与 job/registered 的先后关系。

把工具超时调大能解决吗?

通常不能。案例中的等待发生在工具注册之前,工具自身还没有开始运行。

为什么第二个工具调用可能很快?

社区复现显示延迟主要集中在每轮第一个动作,说明首个调度门槛或响应收尾路径比工具执行器本身更可疑。