Codex 工具调用报 400,问题到底出在哪?
如果 Codex 经 Responses API 兼容接口回传工具结果时出现No tool call found for function call output with call_id ...这条 400 能直接说明的是当前处理function_call_output的系统无法在本次请求关联的上下文中找到对应call_id。工程排查应先核对 ID 和状态续接再检查兼容层转换、并发与重试多上游切换只是后续需要受控验证的假设。本文提供两个相互独立的 Python 协议验证模板一个显式重放完整 Items一个使用previous_response_id。它们用于验证目标端点的工具调用链不是在复刻 Codex 内部实现也不是无需适配即可投入生产的 Agent。先分清四种 ID标识来源用途item.id模型返回的 output Item标识一条输出 Itemitem.call_id模型返回的function_call将工具结果与具体工具调用配对response.id一次 Responses 响应供previous_response_id续接响应链Conversation IDConversation 对象标识对应 API 中的持久会话回传function_call_output时必须使用对应function_call的item.call_id。它不是函数名、数组下标或item.id也不应由客户端重新生成。OpenAI 官方示例同样把response.output加回输入并使用item.call_id回传结果见 Function calling 指南查阅日期2026-08-03。错误出现在 Codex 终端不代表错误一定由 Codex 或 OpenAI 原生服务生成。Codex 支持配置自定义 provider 和 Base URL当前 provider 协议为 Responses兼容网关是否完整实现工具和状态语义仍需实测。参见 Codex 配置参考查阅日期2026-08-03。运行代码前先固定验证环境不要只保存一段脚本。每次实验至少记录openai Python SDKpip show openai 的实际版本或锁文件版本 模型目标端点明确支持 Responses function calling 的模型 ID 入口SDK 使用的 Base URL以及最终请求的完整 /v1/responses URL 工具能力是否支持 function、strict、tool_choice 和连续工具调用 状态路径显式 Items 重放或 previous_response_id每次只测一种 数据设置store、ZDR 以及 reasoning encrypted content 的要求不同兼容端点支持的字段并不相同因此示例使用环境变量不提供“万能模型 ID”。若目标端点不支持指定函数的tool_choice、strict或某种状态路径应先记录为兼容性差异再按对方文档建立单独基线。协议验证与行为验证也要分开协议验证在端点支持时用tool_choice{type: function, name: get_status}强制首轮调用指定函数避免把“模型没有自主选择工具”误判为协议故障。行为验证改用tool_choiceauto和自然提示评估模型在真实任务中是否自主调用工具。下面代码采用协议验证模式。当前tool_choice结构可在 Function calling 指南中复核。公共辅助代码只记结构不打印业务参数importhashlibimportjsonimportosfromimportlib.metadataimportversionfromopenaiimportOpenAI MODELos.environ[TEST_MODEL_ID]MAX_TOOL_ROUNDS4clientOpenAI(api_keyos.environ[OPENAI_API_KEY],base_urlos.environ[OPENAI_BASE_URL],)tools[{type:function,name:get_status,description:Return the current status of a task.,parameters:{type:object,properties:{task_id:{type:string}},required:[task_id],additionalProperties:False,},strict:True,}]forced_tool{type:function,name:get_status}defshort_hash(value):ifnotvalue:returnNonereturnhashlib.sha256(value.encode(utf-8)).hexdigest()[:12]deflog_response(label,response):print({label:label,sdk_version:version(openai),response_id_hash:short_hash(response.id),item_types:[item.typeforiteminresponse.output],call_id_hashes:[short_hash(item.call_id)foriteminresponse.outputifitem.typefunction_call],})defcreate_response(label,**request):try:returnclient.responses.create(**request)exceptExceptionasexc:# 不直接打印异常正文避免兼容端点把请求片段带入错误信息。print({label:label,error:api_request_failed,type:type(exc).__name__})raisedefrun_tool(name,arguments):ifname!get_status:raiseValueError(funknown tool:{name})return{task_id:arguments[task_id],status:running}defbuild_tool_outputs(response):outputs[]foriteminresponse.output:ifitem.type!function_call:continuetry:argumentsjson.loads(item.arguments)exceptjson.JSONDecodeErrorasexc:print({error:invalid_tool_arguments_json,response_id_hash:short_hash(response.id),item_type:item.type,tool_name:item.name,call_id_hash:short_hash(item.call_id),})raiseRuntimeError(工具参数不是合法 JSON)fromexctry:resultrun_tool(item.name,arguments)exceptExceptionasexc:# 工具失败是应用状态不要复用旧 call_id 重建响应链。result{ok:False,error_type:type(exc).__name__,message:tool execution failed,}outputs.append({type:function_call_output,call_id:item.call_id,output:json.dumps(result,ensure_asciiFalse),})returnoutputs日志只保留 SDK 版本、Item 类型序列以及 response/call ID 的短哈希不输出原始 ID、工具参数或工具结果。真实项目还应通过环境变量或密钥管理系统提供凭证不要把 API Key 写进代码。示例把受控工具异常作为结果回传让模型有机会解释失败。若错误属于权限、数据完整性或不可安全恢复的异常也可以明确终止链路关键是不要拿旧call_id重新绑定一条新响应链。生产代码还应细分超时、业务错误和系统错误并避免向模型泄露内部堆栈。路径一显式重放完整 Items这一方式由应用维护history。每轮都把响应中的全部 output Items 加入历史再追加本轮工具结果defverify_with_explicit_replay():history[{role:user,content:查询任务 demo-001 的状态}]forround_indexinrange(MAX_TOOL_ROUNDS):responsecreate_response(fexplicit_round_{round_index1},modelMODEL,instructions根据工具结果回答需要时可以继续调用工具。,toolstools,tool_choiceforced_toolifround_index0elseauto,inputhistory,)log_response(fexplicit_round_{round_index1},response)tool_outputsbuild_tool_outputs(response)ifnottool_outputs:ifround_index0:raiseRuntimeError(首轮未产生 function_call协议验证无效)ifnotresponse.output_text:raiseRuntimeError(工具链结束但没有最终文本)returnresponse.output_text# 必须保留完整 output而不是只复制文本或 function_call。history.extend(response.output)history.extend(tool_outputs)raiseRuntimeError(超过最大工具轮数主动终止)# 单独运行本路径时再取消下一行注释# print(verify_with_explicit_replay())这里不能只挑出function_call。对于推理模型首轮还可能包含下一轮需要的 reasoning Items。OpenAI 的 Conversation state 指南给出了保留完整输出的状态管理方式查阅日期2026-08-03。如果使用store: false、ZDR 或其他无状态条件还要按目标接口核对是否应通过include[reasoning.encrypted_content]获取并回传加密推理内容。OpenAI 的 Responses API Create 参考说明该字段支持无状态多轮中的 reasoning Items查阅日期2026-08-03。本文模板没有开启这类设置不声称覆盖 ZDR也不能假设兼容网关支持同样行为。路径二用previous_response_id续接如果目标端点明确支持服务端响应链可用一个完全独立的函数验证。该函数不复用上一节的historydefverify_with_previous_response_id():previous_idNonepending_input[{role:user,content:查询任务 demo-001 的状态}]forround_indexinrange(MAX_TOOL_ROUNDS):request{model:MODEL,instructions:根据工具结果回答需要时可以继续调用工具。,tools:tools,tool_choice:forced_toolifround_index0elseauto,input:pending_input,}ifprevious_idisnotNone:request[previous_response_id]previous_id responsecreate_response(fprevious_id_round_{round_index1},**request)log_response(fprevious_id_round_{round_index1},response)tool_outputsbuild_tool_outputs(response)ifnottool_outputs:ifround_index0:raiseRuntimeError(首轮未产生 function_call协议验证无效)ifnotresponse.output_text:raiseRuntimeError(工具链结束但没有最终文本)returnresponse.output_text previous_idresponse.idpending_inputtool_outputsraiseRuntimeError(超过最大工具轮数主动终止)# 单独运行本路径时再取消下一行注释# print(verify_with_previous_response_id())两段代码的状态来源不同显式重放由应用携带完整 Itemsprevious_response_id引用服务端保存或可恢复的响应链。本教程为隔离变量建议每次只运行其中一个函数。生产实现除非有明确协议依据和端到端测试不要在引用previous_response_id的同时重复提交同一份完整历史以免引入重复上下文这是一项实现建议不应包装成所有组合都被 API 绝对禁止。当前明确的接口互斥是previous_response_id不能与conversation同时使用。具体字段见 Responses API Create 参考。此外上一响应的instructions不会仅因引用previous_response_id自动继承所以模板在每轮都显式传入指令。怎样让兼容端点验证可复现如果条件和权限允许建立两个基线在官方原生端点运行同一最小脚本只替换 Base URL、凭证和目标端点支持的模型在兼容端点运行。两边必须记录 SDK 版本、完整 endpoint、模型 ID、状态路径和 Item 类型序列。原生端点通过而兼容端点失败只能把问题范围缩小到两者差异不能自动证明是哪一个转换字段出错还需对照兼容网关入口与出口的脱敏结构。如果无法使用原生端点至少保存兼容端点每轮的response ID 与前序 response ID 的受控哈希关系function_call - function_call_output - message等 Item 类型序列每个 call ID 的受控哈希和对应工具名精确入口、模型、SDK/网关版本、时间与重试序号转换前后字段是否从 Responsescall_id变成其他协议的工具调用 ID。仍然报 400按故障矩阵排查位置典型问题验证动作ID 配对把item.id、旧链 ID 或自建 ID 当成call_id按短哈希建立 function call 与 output 一一对应关系参数解析item.arguments不是合法 JSON单独捕获JSONDecodeError只记结构元数据状态续接漏传必要 Items或previous_response_id指错链分别运行两个独立模板不共享可变输入协议转换call_id与另一协议的工具 ID 映射错误或丢 reasoning Item对照网关入口、出口的脱敏 Item 序列并发工具完成顺序与返回顺序不同结果按数组下标配对每个任务携带自己的call_id以 ID 为键汇总自动重试新响应链收到旧链工具结果记录重试序号和 response 关系隔离后逐项恢复工具执行超时或业务失败被误当成协议失败回传受控错误结果或按策略明确终止多上游网关或上游状态无法跨节点恢复前述项目通过后再做固定与受控切换实验本文不再展开“如何证明多上游是根因”的完整判断框架。工程上应记住固定上游成功、切换上游失败只能增强假设还要定位究竟是网关映射、上游 Response ID 作用域还是转换链丢项。无法控制路由时把结论保留为待验证不要在生产流量上强制切换。最终验收不能只看 HTTP 200SDK、模型、Base URL、完整 endpoint 和状态路径已记录协议测试使用目标端点支持的确定性tool_choice每个function_call_output.call_id均来自对应function_call参数 JSON 失败、工具失败和 API 失败能够分开识别显式重放与previous_response_id在独立输入中分别验证若使用store: false或 ZDR已核对 encrypted reasoning 支持网关转换前后的 Item 类型和 ID 关系能够对应并发、重试和连续工具调用均在最大轮数保护下回归模型最终消费工具结果并生成有效回答而不只是第二次请求返回 200日志、截图和公开文章不含真实凭证、完整 ID、业务参数或工具输出。看到No tool call found ... call_id先把脚本变成可重复的协议实验固定版本和端点强制首轮工具调用分别验证两种状态路径再对照网关转换、并发与重试。只有完成这些步骤后才有条件讨论路由架构否则修改负载均衡只是把一个可验证的配对问题换成新的猜测。

相关新闻

SpringBoot面试核心:自动装配、启动流程与生产部署实战解析

SpringBoot面试核心:自动装配、启动流程与生产部署实战解析

1. 项目概述:为什么SpringBoot面试题如此重要?如果你是一名Java开发者,或者正在向这个方向努力,那么“SpringBoot面试”这个词组对你来说一定不陌生。它几乎成了求职路上的一个必经关卡,无论是初级、中级还是高级岗位&…

2026/8/6 5:56:30 阅读更多 →
状态模式与策略模式深度辨析:从设计意图到Python实战

状态模式与策略模式深度辨析:从设计意图到Python实战

1. 项目概述:当“状态”与“策略”狭路相逢在软件设计的江湖里,状态模式和策略模式这对“孪生兄弟”常常让开发者们傻傻分不清楚。它们都基于组合和接口,都旨在将行为封装成独立的类,乍一看,结构图都长得差不多。但如果…

2026/8/6 5:56:30 阅读更多 →
鲁棒估计与5点算法:从理论到实践的计算机视觉几何求解

鲁棒估计与5点算法:从理论到实践的计算机视觉几何求解

1. 从理想模型到现实世界:为什么我们需要鲁棒估计?在计算机视觉,特别是三维重建和运动恢复结构(SfM)领域,本质矩阵(Essential Matrix)的求解是一个经典且核心的问题。它描述了同一场…

2026/8/6 5:56:30 阅读更多 →

最新新闻

Windows自动备份方案:任务计划程序+PowerShell+Robocopy实战

Windows自动备份方案:任务计划程序+PowerShell+Robocopy实战

1. 为什么你需要一个自动备份方案? 如果你还在手动复制粘贴重要文件,或者指望自己每周五下午能记得去点一下备份按钮,那我得说,你的数据正走在一条危险的钢丝上。我见过太多因为一次系统崩溃、一次误删、甚至一次勒索病毒攻击&…

2026/8/6 9:23:32 阅读更多 →
软件逆向工程入门:从黑盒分析到实战破解

软件逆向工程入门:从黑盒分析到实战破解

1. 从“黑盒”到“白盒”:逆向工程究竟是什么? 如果你和我一样,最初听到“逆向工程”这个词,脑海里浮现的可能是电影里特工破解保险箱,或者黑客在屏幕上敲出一行行绿色代码的神秘场景。听起来很酷,但似乎离…

2026/8/6 9:23:32 阅读更多 →
NVIDIA Profile Inspector终极指南:免费解锁200+显卡隐藏设置

NVIDIA Profile Inspector终极指南:免费解锁200+显卡隐藏设置

NVIDIA Profile Inspector终极指南:免费解锁200显卡隐藏设置 【免费下载链接】nvidiaProfileInspector 项目地址: https://gitcode.com/gh_mirrors/nv/nvidiaProfileInspector 你是否知道你的NVIDIA显卡其实隐藏着200多项官方控制面板无法访问的高级设置&am…

2026/8/6 9:23:32 阅读更多 →
蓝桥杯单片机竞赛入门:IAP15F2K61S2开发板实战指南

蓝桥杯单片机竞赛入门:IAP15F2K61S2开发板实战指南

1. 项目概述:从零上手蓝桥杯单片机竞赛如果你正在准备蓝桥杯单片机设计与开发竞赛,或者刚拿到一块型号为IAP15F2K61S2的开发板,面对一堆资料和原理图感到无从下手,那么这篇内容就是为你准备的。我参加过多次这类竞赛的指导工作&am…

2026/8/6 9:23:32 阅读更多 →
第七史诗自动化助手终极指南:如何24小时自动刷书签与挂机讨伐

第七史诗自动化助手终极指南:如何24小时自动刷书签与挂机讨伐

第七史诗自动化助手终极指南:如何24小时自动刷书签与挂机讨伐 【免费下载链接】e7Helper 【Epic Seven Auto Bot】第七史诗多功能覆盖脚本(刷书签🍃,挂讨伐、后记、祭坛✌️,挂JJC等📛,多服务器支持&#x…

2026/8/6 9:23:32 阅读更多 →
客户端与服务器持续同步解析(轮询,comet,WebSocket)

客户端与服务器持续同步解析(轮询,comet,WebSocket)

客户端与服务器持续同步解析(轮询,Comet,WebSocket) 在现代 Web 应用中,实时数据同步(如消息推送、在线协作、股票行情)已成为核心需求。从最初的简单轮询到如今的 WebSocket,技术的…

2026/8/6 9:22:31 阅读更多 →

日新闻

深入解析LimboAI C++内核:架构设计与性能优化实战

深入解析LimboAI C++内核:架构设计与性能优化实战

1. 项目概述:为什么我们需要深入LimboAI的C内核?如果你是一名使用Godot引擎的游戏开发者,尤其是对AI行为逻辑有较高要求的项目,那么LimboAI这个名字你大概率不会陌生。它作为Godot 4生态中一个备受瞩目的行为树与状态机插件&#…

2026/8/6 0:00:06 阅读更多 →
Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

Unity 2D游戏敌人AI系统:基于PlayMaker状态机与2D Toolkit的实战开发

1. 项目概述与核心思路大家好,我是老张,一个在游戏开发一线摸爬滚打了十多年的老码农。今天咱们接着聊《空洞骑士》风格2D动作游戏的Demo制作。上一期我们搭好了基础框架,处理了角色移动和碰撞,这一期,我们要让游戏世界…

2026/8/6 0:00:06 阅读更多 →
被动防火门市场前景发展趋势

被动防火门市场前景发展趋势

被动防火门依靠材质结构、密闭构造阻隔烟火蔓延,无需电控启动,是建筑被动消防系统核心构件,行业依托新规管控、城市更新、工业安全升级迎来稳定扩容,整体朝着合规化、专项化、低碳化、智能化方向发展。现阶段 GB12955‑2024 新版国…

2026/8/6 0:00:06 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/5 15:00:43 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/5 13:13:56 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/5 21:00:14 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →