快速结论:多轮对话调用 Responses API 时,如果你手动维护历史并过滤掉 reasoning 类型的输出项,只把 message 项塞回 input,下一轮就会触发 400。优先排查历史构造逻辑:reasoning+message 必须成对、按原始顺序完整传入。
适用环境:openai v2.29.0;Python v3.13;Windows 11,同时可在 Linux 复现。Issue 报告同样在 JS、Go、Java、.NET SDK 以及 curl 复现,说明属于 API 层约束而非单一 SDK 问题。复现模型为 gpt-5.3-codex(reasoning=high)与 o4-mini。
最快修复方案:手动维护历史时不要过滤 response.output,保留全部输出项及其原始顺序,把 reasoning 与 message 一起配对传回 input;或改用 previous_response_id 让服务端自己维护上下文。需要字典形式时可用 item.to_dict(mode=”json”)。
注意事项:o4-mini 的表现是非确定性的,有时只返回 reasoning 而无 message,因此问题不一定每次都出现;Issue 中提到的 Python 特有 model_dump() 生成空字段(status: None、encrypted_content: None)导致 400: Unknown parameter 是另一个独立 bug(#3008),不要与本配对约束混为一谈。”
问题场景
用户在 Python SDK 中使用 client.responses.create() 构建多轮对话,手动维护 conversation 列表,每轮把 response.output 过滤后只保留 type == “message” 的项追加回历史。第一轮正常,进入第二轮时请求被拒。该模式在 gpt-5.3-codex(reasoning=high)下稳定复现,o4-mini 下非确定性复现。OpenClaw 在生产环境(gpt-5.3-codex)因同一原因中断,需要引入 downgradeOpenAIReasoningBlocks() 来剥离孤立的 reasoning 项。
报错原文
400: Item 'msg_...' of type 'message' was provided without its required preceding item of type 'reasoning'
原因分析
Responses API 要求 input 中的 reasoning 项与其后的 message 项作为连续配对出现。当用户只保留 message、丢弃 reasoning 项时,历史里就出现了没有前置 reasoning 的孤立 message,服务端校验失败返回 400。Issue 指出该约束没有在文档中说明,SDK 类型定义也无法阻止构造出违反约束的 input 数组,这是 API/OpenAPI 层面的约束,跨 5 种 SDK 表现一致。Issue 中明确说明这不是 SDK 独有的问题;至于文档缺失与契约未显式化的归属,Issue 将其归入 openai/openai-openapi#536 继续跟踪。
环境排查
- openai Python SDK 版本:Issue 中为 v2.29.0。
- Python 版本:v3.13。
- 操作系统:Windows 11,Linux 亦可复现。
- 模型与参数:gpt-5.3-codex(reasoning=high)稳定复现;o4-mini 非确定性复现。
- 确认你的历史构造逻辑是否只保留了 response.output 中的 message 项。
- 确认是否误用了 model_dump() 并产生空字段(与 #3008 相关,属独立问题)。
解决步骤
- 检查手动维护的 conversation / input 列表,定位是否存在只保留 message 而丢弃 reasoning 的过滤逻辑(例如 if item.type == “message”)。
- 改为保留 response.output 中的全部项,并维持它们的原始顺序,不要打乱 reasoning 与其对应 message 的相邻关系。
- 需要把项转成字典时,使用 item.to_dict(mode=”json”),避免使用会产生空字段的转换方式。
- 如果不希望自行维护历史,可改用 previous_response_id,让服务端接管上下文接续,从根上避免手工过滤导致的配对断裂。
- Issue 中提到的在 SDK 侧添加 ValueError guard(在 src/openai/resources/responses/ 等消息构建路径中,当 reasoning 项缺失时抛出描述性错误)属于社区提出的改进方向,截至当前讨论尚未合入,不能当作可用的修复手段。
验证方法
按同样方式重跑 Issue 中的复现脚本:第一轮请求应正常返回,第二轮构造 input 时不再出现孤立 message;请求返回 200 而非 400,即说明配对关系已满足。若仍报 400: Unknown parameter 而非上述配对报错,则说明命中的是 #3008 中的 model_dump() 空字段问题,需另行处理。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


