OpenWorker 任务卡在中间不动 / 先看它最后一次工具调用

文章导读
任务停在“执行中”很久不动,先不要重跑,也不要直接把超时调大。打开任务详情,找到最后一次工具调用,看它是“请求已发出但一直没有响应”,还是“命令还在跑、或者已经结束但状态没有回写”。这两类原因的处置方向不同:前者要看模型和工具网关的响应,后者要看命令本身、采集与状态回写。判断顺序建议固定成一条线:任务详情 → 最后一次工具调用 → 请求与响应时间差 → 退出状态 → 超时与重试参数。
📋 目录
  1. Ⅰ 在任务详情里找到最后一次工具调用
  2. Ⅱ 分清是模型没返回还是命令没结束
  3. Ⅲ 把超时阈值和重试次数调一遍再看
  4. Ⅳ 复现时保留最小输入
  5. Ⅴ 按日志时间线写出这次的卡点结论
A A

任务停在“执行中”很久不动,先不要重跑,也不要直接把超时调大。打开任务详情,找到最后一次工具调用,看它是“请求已发出但一直没有响应”,还是“命令还在跑、或者已经结束但状态没有回写”。这两类原因的处置方向不同:前者要看模型和工具网关的响应,后者要看命令本身、采集与状态回写。判断顺序建议固定成一条线:任务详情 → 最后一次工具调用 → 请求与响应时间差 → 退出状态 → 超时与重试参数。

卡在中间时,先定位最后一次工具调用,再用日志里“请求行到响应行”的时间差和命令的退出状态分类:只有请求没有响应,偏模型或工具网关侧无响应;有响应但进程仍在、没有退出状态,偏命令没结束;两者都有、状态仍为运行中,偏状态回写或后续步骤卡住。超时阈值过短会制造假性卡死,调整后必须用同一任务重跑对比,并保留一个最小输入复现。

在任务详情里找到最后一次工具调用

把“卡住”落到具体某一步,才不会在整条任务上盲猜。通常路径是:任务列表 → 目标任务 → 执行记录 / 步骤轨迹(不同版本可能叫 Trace、运行日志、Steps)。进入后按时间正序看,找到最后一个状态不是成功、也不是明确失败的步骤,它就是卡点候选。

在这一条记录上,重点看四个字段:调用名称(工具或动作名,例如 shell、http、file_write)、开始时间、当前状态(运行中 / 等待返回 / 失败)、以及它的输入参数摘要与返回体。如果只有输入没有返回体,说明这一步还在等结果;如果有返回体但状态仍是运行中,问题多半在后续处理而不是这次调用本身。可以把这一条记录连同它的时间戳复制出来,作为后面比对的基准。

OpenWorker 任务卡在中间不动 / 先看它最后一次工具调用

分清是模型没返回还是命令没结束

第一类依据是日志里的时间差。在执行日志中过滤这次调用的请求行与响应行,看请求发出后多久出现对应响应:只有请求行、迟迟没有响应行,通常说明模型或工具网关侧没有返回;请求行和响应行都在,但步骤状态没往前走,通常说明状态回写或后续解析环节卡住。

# 在任务日志中定位这次调用的请求与响应(示意,字段名以实际日志为准)
grep -nE "tool.request|tool.response|step\.(enter|done|timeout)" task.log

# 确认命令进程是否还活着(把关键词换成实际命令)
ps -ef | grep -i "build.py" | grep -v grep

第二类依据是退出状态。命令结束后一般会留下 exit_code 或等价的状态字段;没有退出状态、进程又还在,基本可以判定命令没结束,例如在等待交互输入、卡在网络请求、卡在锁或磁盘 IO。进程不存在、也没有退出状态,则更像是执行器采集或回写缺失。这两类都不需要先去动模型参数。

把超时阈值和重试次数调一遍再看

参数过紧会造成假性卡死:命令本身要跑两分钟,单步超时却只有几十秒,页面表现就是一直停在执行中。可以先把单步超时放大,再把重试次数收敛到 1 或 0,避免重试把真实问题盖住。下面只是通用骨架,键名和层级需要按你的实际配置替换。

OpenWorker 任务卡在中间不动 / 先看它最后一次工具调用
task:
  step_timeout_seconds: 300   # 单步工具调用超时,先放大再看
  retry:
    max_attempts: 1           # 排查阶段先不重试
    backoff_seconds: 5
    retry_on: [timeout]       # 仅对超时重试,避免重复副作用

改完重跑同一个任务,做一份简单对比记录:改前的结束状态与耗时、改后的结束状态与耗时、是否仍出现同样的超时日志行。如果放大超时后任务正常结束,说明是阈值问题;如果仍然停在同一步且没有响应行,说明超时不是根因。需要注意,放大超时不解决无响应,重试则可能让非幂等命令重复执行,涉及写文件、发请求的命令要谨慎开启。

复现时保留最小输入

长上下文、大量附件和历史消息会干扰判断:可能是模型输入过长导致响应变慢,也可能是某条历史指令让工具参数变形。把原任务裁成最小版本再跑一次:只保留必要指令、单次工具调用、去掉附件和无关历史,其他条件尽量不变。

OpenWorker 任务卡在中间不动 / 先看它最后一次工具调用
  • 最小版本仍然卡在同一步,问题更可能在工具、参数或执行环境。
  • 最小版本能通过,逐步加回上下文再试,就能看到是从哪一段开始变慢或卡住。
  • 每次复现都记录任务标识、输入版本、结束状态,方便与原始任务对照。

按日志时间线写出这次的卡点结论

一次排查要沉淀成能复用的判断顺序,最直接的方式是把日志摘成时间线,每行对应一个证据。下面是格式示意,时间与内容按你的实际日志替换。

12:04:01 task.start      task_id=T-1043 steps=6
12:04:02 step.enter      step=3 tool=shell
12:04:02 tool.request    step=3 argv="python build.py"
(此处长时间无 tool.response)
12:06:02 step.timeout    step=3 elapsed=120s
12:06:02 task.state      status=running

据此写结论:卡点在第三步 shell 调用,请求已发出但没有响应行,进程检查显示仍存活,超时放大后重跑仍在同一步停下,最小输入复现同样卡住——判断为命令未结束,先查命令自身的阻塞点(交互输入、网络、锁),而不是继续调模型参数。反过来,如果时间线里请求行之后没有任何响应、进程也不存在,结论就应写成“上游无响应”,处理方向转为检查模型服务与工具网关的连通和返回。每次排查按这几个小节走一遍,下次遇到同类卡住,可以直接从最后一次工具调用开始对照。