Skip to content

fix(sse): route the public OpenAI GPT-5.6 family through the Responses API - #7242

Merged
diegosouzapw merged 2 commits into
release/v3.8.49from
fix/port-pr-2547-gpt56-sol-tools-responses
Jul 17, 2026
Merged

diegosouzapw merged 2 commits into
release/v3.8.49from
fix/port-pr-2547-gpt56-sol-tools-responses

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Jul 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • OpenAI's Chat Completions endpoint rejects GPT-5.6 requests that combine function tools with an active reasoning_effort — 400 "Function tools with reasoning_effort are not supported for <model> in /v1/chat/completions. Please use /v1/responses instead." Any agentic client hitting openai/gpt-5.6-sol with tools + reasoning got the 400 and burned a combo fallback attempt.
  • Root cause: the openai (API-key) registry entries for gpt-5.6 / -sol / -terra / -luna were missing the per-model targetFormat tag, so every request went to /v1/chat/completions.
  • Fix reuses the mechanism OmniRoute already has: the per-model targetFormat: "openai-responses" override that already routes gpt-5.5-pro / gpt-5.4-pro (fix(providers): Various OpenAI model returns [404] error due to endpoint #5842). It drives BOTH the outbound URL (DefaultExecutor.buildUrl → api.openai.com/v1/responses) and the body translation (resolveChatCoreTargetFormat → openai-responses). No new transport table or routing branch needed.

Attribution

Thanks to @Jordannst for the original implementation.

Changes

  • open-sse/config/providers/shared.ts — add targetFormat: "openai-responses" to GPT_5_6_API_CAPABILITIES (consumed only by the 4 public OpenAI GPT-5.6 catalog entries). Scoped to the public OpenAI API catalog; the codex provider has its own Responses transport and is untouched.
  • tests/unit/openai-gpt56-responses-routing.test.ts — new regression test.

Test plan

  • targeted unit test (new, fails before / passes after)

    Before (on release/v3.8.49):

    ✖ getModelTargetFormat routes the public OpenAI GPT-5.6 family through Responses
      AssertionError: gpt-5.6 must target openai-responses
      + actual: null   - expected: 'openai-responses'
    ✖ DefaultExecutor builds the /v1/responses URL for gpt-5.6-sol
      + actual: 'https://api.openai.com/v1/chat/completions'
      - expected: 'https://api.openai.com/v1/responses'
    

    After: ℹ tests 4 / ℹ pass 4 / ℹ fail 0

  • npm run typecheck:core — clean

  • npx eslint on changed files — clean (exit 0)

Negative coverage included: gpt-5.4 still resolves to null / /v1/chat/completions.


⚠️ Reviewer note — competing approach in flight

Another in-flight change targets the same root cause (GPT-5.6 + tools + reasoning) with the opposite strategy, and the two should not land together without a decision:

  • This PR preserves the client's reasoning_effort by routing the request to the Responses API.
  • The other approach (tests/unit/gpt5-tools-reasoning-guard.test.ts, currently uncommitted WIP) drops the client's reasoning when tools are present.

They are mutually exclusive in intent: one keeps reasoning by changing the endpoint, the other silently discards it. Worth picking one deliberately rather than merging both.

FWIW that WIP test currently does not import — it pulls stripGpt5ReasoningWhenTools from open-sse/services/gpt5SamplingGuard.ts, which does not export that symbol.

…s API

OpenAI's Chat Completions endpoint rejects GPT-5.6 requests that combine
function tools with an active reasoning_effort:

  400 "Function tools with reasoning_effort are not supported for
  <model> in /v1/chat/completions. Please use /v1/responses instead."

The openai (API-key) registry entries for gpt-5.6 / -sol / -terra / -luna
were missing the per-model `targetFormat` tag, so every request was posted
to /v1/chat/completions. Any agentic client sending tools + reasoning to
openai/gpt-5.6-sol hit the 400 and burned a combo fallback attempt.

OmniRoute already has the generic mechanism this needs — the same
per-model `targetFormat: "openai-responses"` override that routes
gpt-5.5-pro / gpt-5.4-pro (#5842). It drives BOTH the outbound URL
(DefaultExecutor.buildUrl → api.openai.com/v1/responses) and the body
translation (chatCore's resolveChatCoreTargetFormat → openai-responses).
Tagging GPT_5_6_API_CAPABILITIES is therefore the whole fix; no new
transport table or routing branch is required.

Scoped to the public OpenAI API catalog: the codex provider has its own
Responses transport and is untouched.

Co-authored-by: Sutarto Jordan Chrisfivo <Jordannst@users.noreply.github.com>
Inspired-by: decolua/9router#2547
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@diegosouzapw

Copy link
Copy Markdown
Collaborator Author

Aprovado tecnicamente — fail-without-fix confirmado (2/4 falham sem o fix) e sem colisão de arquivo com #7012/#7209 (constantes/arquivos diferentes). Mas o PR já sinaliza corretamente o ponto crítico: o #7101 ataca a MESMA causa-raiz com estratégia OPOSTA (descarta reasoning_effort em vez de re-rotear) e não exclui gpt-5.6 do seu escopo — se os dois forem mergeados sem decisão, o comportamento final de gpt-5.6+tools+reasoning depende da ordem de execução em chatCore.ts e pode anular este fix. Recomendo decidir ANTES de mergear ambos: ou #7101 exclui explicitamente os modelos com targetFormat já resolvido para 'openai-responses', ou só um dos dois entra.

diegosouzapw added a commit that referenced this pull request Jul 15, 2026
stripGpt5ReasoningWhenTools gated on provider+model-name alone, so once
#7242 routes the public GPT-5.6 family to /v1/responses (targetFormat
"openai-responses", which natively supports tools + reasoning), the two
PRs would compose into the worst of both worlds: routed to the endpoint
that supports reasoning, but reasoning stripped anyway. Pass the
request's already-resolved targetFormat into the guard and skip the
strip whenever it is not going out over /chat/completions, so the
guard tracks the actual upstream surface instead of a model-name list
that would need updating for every future GPT-5.x family.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)
@diegosouzapw
diegosouzapw merged commit 62bea04 into release/v3.8.49 Jul 17, 2026
15 checks passed
diegosouzapw added a commit that referenced this pull request Jul 17, 2026
…n tools (#7101)

* fix(openai): strip reasoning_effort when GPT-5.x tools present (port from 9router#2540)

Raw api.openai.com Chat Completions rejects GPT-5.x reasoning models that carry both function tools and an active reasoning_effort with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"). The existing forceResponsesUpstream guard only reroutes openai-compatible-* connections carrying MCP/tool_search tool shapes; the plain openai provider had no equivalent guard, so gpt-5.x models used with a coding client (function tools + any explicit reasoning effort) still hit the upstream 400. Add stripGpt5ReasoningWhenTools() (gpt5SamplingGuard.ts), wired into chatCore.ts alongside the existing sampling guard, to drop reasoning_effort/reasoning when function tools are present and reasoning is active, letting the request succeed on /v1/chat/completions.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)

* fix(openai): scope reasoning-strip guard to /chat/completions only

stripGpt5ReasoningWhenTools gated on provider+model-name alone, so once
#7242 routes the public GPT-5.6 family to /v1/responses (targetFormat
"openai-responses", which natively supports tools + reasoning), the two
PRs would compose into the worst of both worlds: routed to the endpoint
that supports reasoning, but reasoning stripped anyway. Pass the
request's already-resolved targetFormat into the guard and skip the
strip whenever it is not going out over /chat/completions, so the
guard tracks the actual upstream surface instead of a model-name list
that would need updating for every future GPT-5.x family.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)
diegosouzapw added a commit to olber1226/OmniRoute that referenced this pull request Jul 19, 2026
…heaper-inference#7663)

The PR added a `^gpt-5\.6(?:$|[-.])` fallback in getModelTargetFormat
alongside the existing `-pro$` heuristic, but the only existing test
file exercises curated ids (gpt-5.6/-sol/-terra/-luna) that already hit
the registry's targetFormat fast path via GPT_5_6_API_CAPABILITIES
(cheaper-inference#7242) — so the new regex branch itself was untested. Add cases for
an un-curated variant, the gpt-5.60 non-match, and the openai-only
scoping (never codex) to close the gap per Hard Rule cheaper-inference#8.

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
@diegosouzapw
diegosouzapw deleted the fix/port-pr-2547-gpt56-sol-tools-responses branch July 19, 2026 21:01
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…s API (cheaper-inference#7242)

* fix(sse): route the public OpenAI GPT-5.6 family through the Responses API

OpenAI's Chat Completions endpoint rejects GPT-5.6 requests that combine
function tools with an active reasoning_effort:

  400 "Function tools with reasoning_effort are not supported for
  <model> in /v1/chat/completions. Please use /v1/responses instead."

The openai (API-key) registry entries for gpt-5.6 / -sol / -terra / -luna
were missing the per-model `targetFormat` tag, so every request was posted
to /v1/chat/completions. Any agentic client sending tools + reasoning to
openai/gpt-5.6-sol hit the 400 and burned a combo fallback attempt.

OmniRoute already has the generic mechanism this needs — the same
per-model `targetFormat: "openai-responses"` override that routes
gpt-5.5-pro / gpt-5.4-pro (cheaper-inference#5842). It drives BOTH the outbound URL
(DefaultExecutor.buildUrl → api.openai.com/v1/responses) and the body
translation (chatCore's resolveChatCoreTargetFormat → openai-responses).
Tagging GPT_5_6_API_CAPABILITIES is therefore the whole fix; no new
transport table or routing branch is required.

Scoped to the public OpenAI API catalog: the codex provider has its own
Responses transport and is untouched.

Co-authored-by: Sutarto Jordan Chrisfivo <Jordannst@users.noreply.github.com>
Inspired-by: decolua/9router#2547

* chore(changelog): fragment for cheaper-inference#7242

---------

Co-authored-by: Sutarto Jordan Chrisfivo <Jordannst@users.noreply.github.com>
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…n tools (cheaper-inference#7101)

* fix(openai): strip reasoning_effort when GPT-5.x tools present (port from 9router#2540)

Raw api.openai.com Chat Completions rejects GPT-5.x reasoning models that carry both function tools and an active reasoning_effort with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"). The existing forceResponsesUpstream guard only reroutes openai-compatible-* connections carrying MCP/tool_search tool shapes; the plain openai provider had no equivalent guard, so gpt-5.x models used with a coding client (function tools + any explicit reasoning effort) still hit the upstream 400. Add stripGpt5ReasoningWhenTools() (gpt5SamplingGuard.ts), wired into chatCore.ts alongside the existing sampling guard, to drop reasoning_effort/reasoning when function tools are present and reasoning is active, letting the request succeed on /v1/chat/completions.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)

* fix(openai): scope reasoning-strip guard to /chat/completions only

stripGpt5ReasoningWhenTools gated on provider+model-name alone, so once
cheaper-inference#7242 routes the public GPT-5.6 family to /v1/responses (targetFormat
"openai-responses", which natively supports tools + reasoning), the two
PRs would compose into the worst of both worlds: routed to the endpoint
that supports reasoning, but reasoning stripped anyway. Pass the
request's already-resolved targetFormat into the guard and skip the
strip whenever it is not going out over /chat/completions, so the
guard tracks the actual upstream surface instead of a model-name list
that would need updating for every future GPT-5.x family.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…s API (cheaper-inference#7242)

* fix(sse): route the public OpenAI GPT-5.6 family through the Responses API

OpenAI's Chat Completions endpoint rejects GPT-5.6 requests that combine
function tools with an active reasoning_effort:

  400 "Function tools with reasoning_effort are not supported for
  <model> in /v1/chat/completions. Please use /v1/responses instead."

The openai (API-key) registry entries for gpt-5.6 / -sol / -terra / -luna
were missing the per-model `targetFormat` tag, so every request was posted
to /v1/chat/completions. Any agentic client sending tools + reasoning to
openai/gpt-5.6-sol hit the 400 and burned a combo fallback attempt.

OmniRoute already has the generic mechanism this needs — the same
per-model `targetFormat: "openai-responses"` override that routes
gpt-5.5-pro / gpt-5.4-pro (cheaper-inference#5842). It drives BOTH the outbound URL
(DefaultExecutor.buildUrl → api.openai.com/v1/responses) and the body
translation (chatCore's resolveChatCoreTargetFormat → openai-responses).
Tagging GPT_5_6_API_CAPABILITIES is therefore the whole fix; no new
transport table or routing branch is required.

Scoped to the public OpenAI API catalog: the codex provider has its own
Responses transport and is untouched.

Co-authored-by: Sutarto Jordan Chrisfivo <Jordannst@users.noreply.github.com>
Inspired-by: decolua/9router#2547

* chore(changelog): fragment for cheaper-inference#7242

---------

Co-authored-by: Sutarto Jordan Chrisfivo <Jordannst@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…n tools (cheaper-inference#7101)

* fix(openai): strip reasoning_effort when GPT-5.x tools present (port from 9router#2540)

Raw api.openai.com Chat Completions rejects GPT-5.x reasoning models that carry both function tools and an active reasoning_effort with HTTP 400 ("Function tools with reasoning_effort are not supported ... Please use /v1/responses instead"). The existing forceResponsesUpstream guard only reroutes openai-compatible-* connections carrying MCP/tool_search tool shapes; the plain openai provider had no equivalent guard, so gpt-5.x models used with a coding client (function tools + any explicit reasoning effort) still hit the upstream 400. Add stripGpt5ReasoningWhenTools() (gpt5SamplingGuard.ts), wired into chatCore.ts alongside the existing sampling guard, to drop reasoning_effort/reasoning when function tools are present and reasoning is active, letting the request succeed on /v1/chat/completions.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)

* fix(openai): scope reasoning-strip guard to /chat/completions only

stripGpt5ReasoningWhenTools gated on provider+model-name alone, so once
cheaper-inference#7242 routes the public GPT-5.6 family to /v1/responses (targetFormat
"openai-responses", which natively supports tools + reasoning), the two
PRs would compose into the worst of both worlds: routed to the endpoint
that supports reasoning, but reasoning stripped anyway. Pass the
request's already-resolved targetFormat into the guard and skip the
strip whenever it is not going out over /chat/completions, so the
guard tracks the actual upstream surface instead of a model-name list
that would need updating for every future GPT-5.x family.

Reported-by: Tech Solution (@techsolutionmta) (decolua/9router#2540)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant