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/9/29 7:08:54 阅读更多 →
状态模式与策略模式深度辨析:从设计意图到Python实战

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

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

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

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

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

2026/9/28 22:23:46 阅读更多 →

最新新闻

SQL Server数据库加固规范实战:账号权限、日志审计与协议加密

SQL Server数据库加固规范实战:账号权限、日志审计与协议加密

简介:面向数据库运维、安全管理人员及需要满足合规要求的政企IT团队,这份Sql Server数据库系统加固规范文档提供了一套可落地的安全配置基线。内容围绕账号管理、认证授权、日志配置、通信协议、设备安全等核心模块展开,细化到具体核查项与操…

2026/10/9 18:00:33 阅读更多 →
包裹实例分割数据集实战:从解压到YOLOv8训练与掩码调优

包裹实例分割数据集实战:从解压到YOLOv8训练与掩码调优

简介:包裹实例分割数据集面向物流自动化、智能仓储与工业视觉方向的算法开发者及职业培训学员,聚焦传送带与仓库场景中包裹轮廓的精准分割需求。资源包共1438个文件,以718张jpg真实场景图像与718个同名txt标注文件为主体,另含1个y…

2026/10/9 18:00:33 阅读更多 →
ClawManager 多节点 Kubernetes 集群部署指南:结合 Longhorn 持久存储从零到一的完整实战

ClawManager 多节点 Kubernetes 集群部署指南:结合 Longhorn 持久存储从零到一的完整实战

ClawManager 多节点 Kubernetes 集群部署指南:结合 Longhorn 持久存储从零到一的完整实战 【免费下载链接】ClawManager A Kubernetes-native control plane for AI agent instance management, with governed AI access, runtime orchestration, and reusable reso…

2026/10/9 18:00:33 阅读更多 →
RHEL 7.6部署Oracle 19c ASM+Data Guard实战避坑指南

RHEL 7.6部署Oracle 19c ASM+Data Guard实战避坑指南

简介:本资源是一份面向DBA、系统运维工程师及Oracle高可用架构学习者的实战部署指南,聚焦RHEL 7.6环境下Oracle 19c单实例ASMData Guard物理备库的端到端搭建。内容覆盖硬件与系统预检(4核/20G内存/200G存储)、GI与数据库软件版本…

2026/10/9 18:00:33 阅读更多 →
医院门诊管理系统数据库设计:从需求分析到建表落地

医院门诊管理系统数据库设计:从需求分析到建表落地

简介:这是一份医院门诊管理系统数据库设计的课程设计文档,适合软件工程、数据库相关专业学生及需要完成类似课设的开发者参考。资源围绕小型医院门诊管理系统的数据库设计与实现展开,涵盖需求分析、数据流程图、数据字典、E-R图设计、概念与逻…

2026/10/9 18:00:33 阅读更多 →
Spring Boot+Vue微信小程序购物系统:从搭建到答辩全流程指南

Spring Boot+Vue微信小程序购物系统:从搭建到答辩全流程指南

简介:一套面向毕业设计场景的Java微信小程序购物系统完整可运行项目,基于Springboot与Vue实现前后端分离,适合计算机专业学生用于课题设计、期末作业或二次开发学习,也可作为微信小程序开发的进阶参考。项目已通过导师指导与答辩评…

2026/10/9 17:59:32 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →