Custom baseURL + Responses API sends max_output_tokens unconditionally, breaking OpenAI-compatible gateways
Summary
Configuring a custom provider with @ai-sdk/openai and a custom baseURL that targets the Responses API path causes 400 Bad Request: Unsupported parameter: max_output_tokens on some OpenAI-compatible gateways. The same gateway works when using @ai-sdk/openai-compatible (chat-completions path, max_tokens) and when using Codex CLI's native wire_api = "responses" provider configuration, suggesting Codex's own request construction omits the problematic field.
Environment
- opencode version: 1.15.10
- provider npm:
@ai-sdk/openai - model:
gpt-5.5 - OS: (observed across platforms)
- Install method:
npx opencode@latest/ bundled runtime - Relevant config: custom
providerblock with"npm": "@ai-sdk/openai","options": { "baseURL": "<custom-openai-compatible-gateway>/v1", "apiKey": "..." }, and a model entry such as"gpt-5.5": { "name": "GPT-5.5" }
Repository Decision
- Target repository:
openai/codex - Why this belongs there: The user-visible failure occurs when an external provider (
@ai-sdk/openai) is wired into the execution path used by Codex-based tooling. Codex CLI's ownwire_api = "responses"implementation demonstrates that a gateway-compatible request body is possible (it does not serializemax_output_tokens). The requested fix is for the Codex provider contract / custom-provider configuration to support Responses-API-style custom gateways without unconditionally emittingmax_output_tokens, either by omitting the field, by allowing the chat-completions path, or by exposing a provider option to sendmax_tokensinstead. - LazyCodex evidence (runtime +
$LAZYCODEX_SOURCE_ROOT/lazycodex-source): src/src/plugin/chat-params.ts(lines 169–183): the harness normalizes and always emits a positivemaxOutputTokensvalue as part of chat parameters.src/src/shared/session-prompt-params-helpers.ts(line 28):maxOutputTokensis forwarded into the prompt request body whenmodel.maxTokensis set.tests/hashline/headless.ts(line 6): LazyCodex/OmO code uses@ai-sdk/openai-compatible(createOpenAICompatible) for chat-completions-style integrations, which sendsmax_tokensrather thanmax_output_tokens.- Upstream Codex source evidence from
$LAZYCODEX_SOURCE_ROOT/openai-codex-source: codex-rs/codex-api/src/common.rs(lines 198–220): the nativeResponsesApiRequeststruct has nomax_output_tokensfield, so Codex CLI's own Responses-API request body never includes it.codex-rs/core/src/client.rs(lines 812–892):build_responses_requestconstructs the request without assigning any output-token limit field.sdk/typescript/tests/testCodex.ts(lines 26–31, 66–71) andcodex-rs/mcp-server/tests/suite/codex_tool.rs(lines 515–520): Codex CLI supports custom providers viamodel_providers.<id>.base_url+wire_api = "responses", and that native path works with the same gateway.
Reproduction
- Configure a custom provider with:
``json``
{
"provider": {
"my-gateway": {
"npm": "@ai-sdk/openai",
"options": {
"baseURL": "<custom-openai-compatible-gateway>/v1",
"apiKey": "..."
},
"models": {
"gpt-5.5": { "name": "GPT-5.5" }
}
}
}
}
- Run
opencode run --model my-gateway/gpt-5.5 'hello'. - Observe a
400 Bad Requestresponse whose error text includesUnsupported parameter: max_output_tokens.
Expected Behavior
Custom baseURL + Responses API should either work out of the box with gateways that only accept the OpenAI Responses API subset, or be configurable to send max_tokens instead of max_output_tokens for gateways that do not support the latter.
Actual Behavior
The request fails with 400 Bad Request because max_output_tokens is sent unconditionally by the @ai-sdk/openai Responses-API code path.
Evidence
- Source inspection of
openai-codex-source/codex-rs/codex-api/src/common.rsshows the nativeResponsesApiRequestbody lacksmax_output_tokens, matching the observed behavior that Codex CLI'swire_api = "responses"works against the gateway. - Source inspection of
lazycodex-source/src/src/plugin/chat-params.tsandlazycodex-source/src/src/shared/session-prompt-params-helpers.tsshows the LazyCodex/OmO harness always materializesmaxOutputTokensinto the request, which downstream Vercel AI SDK provider code maps tomax_output_tokensfor the Responses API. - Runtime reproduction was performed with the steps above against an OpenAI-compatible gateway at
<custom-openai-compatible-gateway>; the gateway returned400 Unsupported parameter: max_output_tokens. The gateway accepted the identical model via@ai-sdk/openai-compatible(chat completions,max_tokens) and via Codex CLI's nativewire_api = "responses"TOML provider block.
Root Cause
The @ai-sdk/openai Responses-API implementation serializes max_output_tokens unconditionally when an output-token limit is supplied. Some OpenAI-compatible gateways implement only the chat-completions-style max_tokens field (or omit both) and therefore reject the request. Codex CLI's native wire_api = "responses" path avoids this by not sending any output-token limit field at all, but Codex-based configurations that route through @ai-sdk/openai inherit the Vercel SDK behavior and cannot currently override it.
Proposed Fix
Introduce a Codex-side provider option (for example under model_providers.<id> or in the npm-provider wrapper) that:
- Omits
max_output_tokensfrom the Responses API request body when the provider is flagged as an OpenAI-compatible gateway, or - Allows the provider to use the chat-completions path (
max_tokens) instead of the Responses API path for custombaseURLconfigurations, or - Exposes a per-provider toggle such as
use_max_tokens: truethat the request builder consults before serializing the output-token limit.
Likely files / components to touch:
codex-rs/model-provider-infoorcodex-rs/core/src/client.rsfor native provider request construction.- The TypeScript SDK's provider wrapping layer (
sdk/typescript/src/exec.tsand related config plumbing) if the customnpmprovider path is handled there. - Config schema in
codex-rs/config/src/profile_toml.rs/codex-rs/config/src/thread_config/remote.rsto accept the new option.
Verification Plan
- [ ] Configure a custom provider with
@ai-sdk/openaiand a custombaseURLpointing to a mock OpenAI-compatible gateway that rejectsmax_output_tokens; confirm the request fails before the fix. - [ ] Apply the fix and confirm the same mock gateway receives a request without
max_output_tokens(or withmax_tokenswhen using the chat-completions path) and returns a successful response. - [ ] Regression check: ensure native OpenAI
wire_api = "responses"providers continue to work unchanged. - [ ] Regression check: ensure
@ai-sdk/openai-compatiblechat-completions providers continue to work unchanged.
---
This issue or PR was generated by LazyCodex.
Tag: lazycodex-generated
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗