现场是这样的。openai-agents 0.2 的 Runner.run 设了 max_turns 为 6,第 7 次工具调用后直接返回,result.final_output 是 None,业务侧记了空字符串,也没有异常。

中间走过弯路,把「工具没有收敛,每轮都在产生新的调用」当成主因,改完现象没变。

这类报错背后常见的原因有几处,逐个排除就行。到达轮次上限属于正常返回,不是异常;final_output 只在最后一条 assistant 消息上才有;没有检查 result 的原始消息列表。

动手时先打印 result 里的消息链与最后一轮状态

python -c "import json;print(json.load(open('result.json'))['last_agent'])"

显式判断 final_output 为空并抛业务异常

python -c "print({'check':'final_output is None -> raise'})"

接着让工具返回明确的终态标记,减少轮次

python -c "print({'done':True,'reason':'no_more_tools'})"

末了把 max_turns 调高并压测平均轮次

python run_stats.py --max-turns 12 --n 50

我习惯把每一步的执行时间和结果记在一边,后面复盘省事。

恢复的判定其实很直接。同一批请求都能拿到非空 final_output,平均轮次从 6 降到 3,日志里不再出现空回答。

补一句。轮次上限是护栏不是熔断,返回值为空要在业务侧显式判定,否则成功响应里会混进空内容。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189