anomalyco / anomalyco/opencode
[BUG] OpenAI Responses: assistant messages sent as {role:"assistant", content:[{type:"output_text"}]} rejected by strict OpenAI-compatible servers
@kitlangton is already working on this.
Since Aug 14, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
When a conversation history contains an assistant text message and opencode sends it
to an OpenAI Responses (/responses) endpoint, the request body uses:
{"role": "assistant", "content": [{"type": "output_text", "text": "..."}]}
This shape is not valid per OpenAI's Responses input schema. Real api.openai.com
tolerates it, but strict OpenAI-compatible servers that validate with the official
OpenAI SDK types (e.g. a self-hosted Qwen server exposing /v1/responses) reject it
with a 422/400 validation error, so switching a session to such a model fails.
Environment
- opencode 1.18.18 (Snap, stable)
- Default runtime (AI SDK path),
@ai-sdk/openai3.0.84 - Server: self-hosted OpenAI-compatible
/v1/responsesendpoint (validates with
openaiPython SDK pydantic types)
Repro
- Configure a custom provider/model pointing at an OpenAI-compatible
/responses
server. - Switch an existing session to that model so the history (including prior
assistant text) is resent. - The request fails with a pydantic
ValidationErroron theinputarray, e.g.:
loc: ('body', 'input', 'list[union[EasyInputMessageParam, Message, ResponseOutputMessageParam, ...]]', 2, 'ResponseFunctionToolCallParam', 'call_id')
msg: 'Field required'
input: {'role': 'assistant', 'content': [{'type': 'output_text', 'text': '...'}]}
Root cause
@ai-sdk/openai builds assistant input items as
{ role: "assistant", content: [{ type: "output_text", text }], id }
(convertToOpenAIResponsesMessages, dist/index.js ~3127).
Per the official OpenAI schema (openai-python types):
EasyInputMessageParamallowsrole: "assistant"butcontentmust be
str | list[input_text | input_image | input_file]—output_textis not
a valid easy-input content part.output_textis only valid inside a full output item
{ type: "message", role: "assistant", id, status, content: [...] }
(ResponseOutputMessageParam, wheretype/id/statusare required).
OpenAI's own API is lenient and accepts the non-conformant shape, which is why
this has gone unnoticed. The same bug also exists in the native llm protocol
(packages/llm/src/protocols/openai-responses.ts, lowerMessages).
Proposed fix
Emit assistant text as an easy-input message with input_text parts:
{"role": "assistant", "content": [{"type": "input_text", "text": "..."}]}
or, when an item id is available, the complete
{"type": "message", "role": "assistant", "id", "status": "completed", "content": [{"type": "output_text", "text": "..."}]}.
A local fix for the native protocol is ready and tests pass
(59 tests, packages/llm). The AI SDK path will additionally need a fix in
vercel/ai (or a bumped @ai-sdk/openai) to fix the released builds.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.