快速结论:当你在使用 OpenAI Python SDK 的 Responses API 回放自己构造(或从外部存储恢复)的 assistant 消息,尤其是包含多个 output_text 内容块时,类型检查器会要求你补上 id 和 status 字段,否则报错 sending a client-authored assistant turn requires either a fake message id or a # type: ignore。优先排查是否把 assistant turn 当成完整 OutputMessage 传入,以及是否启用了 pyright/mypy 等类型检查。
适用环境:Issue 中确认的信息包括:OpenAI Python SDK openai 2.48.0(正文验证)和 openai 2.49.0(评论验证)、类型检查器 pyright 1.1.411;示例使用的模型为 gpt-5。Issue 未提供操作系统、Python 版本、CUDA 或显卡信息,请勿据此推断。
最快修复方案:暂无确认的一步修复方案。Issue 最终被关闭并重定向到上游 openai/openai-openapi#565,因为修复需要落在 generated spec 一侧(放宽 OutputMessage.required 中的 id 与 status),SDK 端的补丁会在下次同步时被覆盖。
注意事项:Issue 中提到的临时绕过手段(编造 id、# type: ignore、把 content 写成字符串)都各有局限;编造 id 可能影响 prompt caching,字符串写法无法承载多个 output_text 块或 annotations。这些都不是已验证的官方修复。
问题场景
用户在 OpenAI Python SDK 中调用 client.responses.create(model=..., input=conversation),并把一段对话历史作为 input 传入。该历史中包含一条由客户端自行撰写或从存储回放的 assistant 消息,消息的内容是多个 output_text 块(例如从之前的 Responses API 输出中取回,或经过编辑后再发送)。在启用类型检查器(如 pyright)时,ResponseInputParam 无法接受这种写法,必须补上 id 和 status。
报错原文
Responses API: sending a client-authored assistant turn requires either a fake message id or a `# type: ignore`
类型不匹配的三种写法所对应的实际表现:
# 方式一:必须补上编造的 id 和 status
{"type": "message", "id": "msg_fake_msg_id", "status": "completed", "role": "assistant", "content": [...]}
# 方式二:省略 id/status 时,需要 # type: ignore
{"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "5", "annotations": []}]} # type: ignore
# 方式三:把 output_text 换成 input_text 可通过类型检查,但服务端返回 400
{"error": {"message": "Invalid value: 'input_text'. Supported values are: 'output_text' and 'refusal'.",
"type": "invalid_request_error", "param": "input[1].content[0]", "code": "invalid_value"}}
原因分析
可能原因是 OpenAI Python SDK 的请求类型复用了响应侧的 OutputMessage schema(由 openai-openapi 生成),而该 schema 把 id、type、role、content、status 全部列为 required。对于由 API 生成后再发回的消息,这些字段天然存在;但对于客户端自行撰写、从存储回放或编辑后的 assistant turn,id 和 status 并不存在,于是就出现了类型层面与服务端实际接受行为不一致的冲突。
Issue 评论对比了同类 schema:FunctionToolCall 同样既由服务端返回、又由客户端在工具调用往返中重新发送,但 spec 中只把语义字段(call_id、name、arguments)标记为 required,id/status 是可选的。因此评论认为更接近 OutputMessage 尚未获得同样的处理,而非有意约束 assistant 消息。最终维护者确认:这属于请求/响应 schema 分离问题,已在上游 openai/openai-openapi#565 跟踪。
环境排查
- 确认 OpenAI Python SDK 版本(Issue 验证过
2.48.0与2.49.0)。 - 确认类型检查器及版本(Issue 使用
pyright 1.1.411;mypy 行为未验证)。 - 确认传入
input的 assistant 消息是否使用了{"type": "message", ...}形式而非简化的EasyInputMessageParam字符串形式。 - 确认 assistant 消息的 content 是否包含多个
output_text块或 annotations —— 这类结构无法用字符串形式替代。 - 确认模型名称(示例为
gpt-5);Issue 未提供操作系统、Python、CUDA、显卡等信息,无需额外排查。
解决步骤
- 先判断你的 assistant 回放消息是否需要携带多个
output_text块或 annotations。如果不需要,可优先尝试评论中提到的字符串写法:{"role": "assistant", "content": "5"},它路由到EasyInputMessageParam,无需id/status,在pyright 1.1.411 / openai 2.49.0下验证通过。 - 如果需要保留多个
output_text块,Issue 中原作者确认字符串写法无法覆盖该场景,需要等待上游修复。可优先尝试的临时方式是补上编造的id和status,但要注意这可能影响 prompt caching,且需要自己保证同一对话前缀生成稳定的合成 id。 - 不要通过把
output_text改成input_text来绕过类型检查——Issue 验证这条路会在服务端返回 400Invalid value: 'input_text'。 - 不要 fork 修改
response_output_message_param.py:评论指出该 SDK 由 Stainless 从openai-openapi生成,本地补丁会在下一次 spec 同步时被回滚。 - 关注上游修复进展:维护者已将问题关闭并重定向到
openai/openai-openapi#565(请求/响应 schema 分离)。相关 spec 侧报告还包括openai/openai-openapi#475(content union 不匹配)。评论建议的窄修复是:从OutputMessage.required中移除id和status,与FunctionToolCall对齐;该修复同时覆盖status部分,而此前提出的#3015仅放宽id,不足以解决本问题。
验证方法
在类型检查器下运行你的构造代码:如果采用的临时写法不再需要 # type: ignore 或编造字段,并能在 client.responses.create(...) 下正常返回结果,即说明该写法在当前版本可用。若需要确认上游修复是否落地,请跟踪 openai/openai-openapi#565 的状态以及后续 SDK 版本中 OutputMessage.required 是否变更。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Bug] Claude Code heterogeneous agent fails with "spawn EINVAL" on Windows (npm install)](https://www.chat-gpts.plus/wp-content/uploads/2026/09/18493-b5d75f9f-768x403.jpg)
![[Bug] Android 1.0.15 routes remote Codex device execution to Provider API instead of Agent Gateway](https://www.chat-gpts.plus/wp-content/uploads/2026/09/18713-46b4b404-768x403.jpg)
