Reasoning
Reasoning lets supported models spend additional tokens planning before they answer. Use it for multi-step coding, math, analysis, tool-use planning, and other tasks where a slower request is worth a better final answer.
Gateway treats reasoning as a vendor-route capability. The same canonical model can expose different reasoning behavior depending on the vendor that serves the request, so check the exact route before sending reasoning controls.
Reasoning can increase latency and output-token cost. Some providers also return thinking by default for specific routes. Use /v1/models to inspect behavior before enabling reasoning broadly.
How reasoning works
Gateway supports three reasoning patterns:
- Gateway-controlled thinking uses the top-level
thinkingrequest field. Gateway translates it for routes that support that request style, and it is the portable spelling: write it once and it works across vendors. - Provider-native reasoning controls use provider-specific fields such as
reasoning_effort, when the selected route advertises that control. - Adaptive thinking lets the model decide how much to think, steered by an effort level rather than a token budget. The newest Claude models take this shape and reject a manual budget, so Gateway rewrites a
thinkingblock into it for them (see Adaptive thinking on Claude).
In responses, Gateway normalizes separate provider reasoning into thinking content blocks.
Always render or log these blocks separately from final text. Some providers treat reasoning text as intermediate output, and some applications should hide it from end users.
signature is populated on Anthropic routes and is null on providers that do not sign reasoning (Gemini thought summaries, for example). It is not decorative: if you send the assistant turn back in a later request, the signature must come back with it. See Replay reasoning in multi-round tool loops.
Discover support
Use GET /v1/models and inspect the vendor route you plan to use.
A reasoning-capable route has supports_reasoning: true and a reasoning object.
Check the route you will actually execute. If you use a routing policy, inspect every candidate route that policy can select.
Enable Gateway-controlled thinking
Use the thinking field when the route supports Gateway-controlled thinking. The budget_tokens value is required when type is "enabled" because providers that support explicit thinking need a budget.
Keep sending this shape even on routes that no longer accept it upstream. Gateway rewrites it to whatever the resolved route wants, so thinking.budget_tokens stays the one spelling that works everywhere.
Pick a reasoning budget that leaves enough room for the final answer. If you set max_tokens: 4096 and budget_tokens: 1024, the provider still needs remaining output capacity for visible text.
Use provider-native controls
Some routes advertise provider-native controls instead of the top-level thinking field. For example, GPT-OSS routes may expose reasoning_effort.
Only send provider-native controls when /v1/models lists them under reasoning.controls.
Provider-native controls are not interchangeable. A control that works on one vendor route can be ignored or stripped on another route for the same canonical model.
Adaptive thinking on Claude
The newest Claude models (Opus 4.7 and 4.8, Sonnet 5, Fable 5, and Mythos 5) do not accept a manual thinking budget. They decide how long to think on their own, steered by an effort level, and reject thinking: {"type": "enabled", "budget_tokens": N} outright.
Send the thinking block anyway. Gateway rewrites it for those models into adaptive thinking with a summarized display, plus an effort level derived from the budget you asked for:
The summarized display is deliberate. These models omit thinking output unless asked, so without it the response would carry empty thinking blocks. A disabled directive is dropped for the same reason: reasoning is always on for this generation.
The adaptive shape is also accepted directly on the Anthropic-compatible surface, if you would rather write it than have it translated:
An explicit display is preserved rather than overwritten, and an effort level the route does not accept returns 400 unsupported_reasoning_effort.
Earlier Claude models on the direct anthropic vendor take an effort level too, translated back into a thinking budget. Gateway picks that budget against the request’s max_tokens and keeps a reserve for the answer, so high under a tight max_tokens runs at a lower level with a reasoning_effort_adjusted warning instead of failing Anthropic’s rule that max_tokens must exceed the thinking budget. Raise max_tokens when you want the level you asked for.
Effort levels per route
Effort levels are validated against the vendor route that serves the request, not the canonical model. Two vendors hosting the same model often accept different sets, and the level you can use is whatever reasoning.effort_values lists for the route you land on.
List the levels every vendor accepts for a model:
Same model, seven routes, five different answers. A request for max served by baseten runs at xhigh; served by fireworks it runs at the model’s default with no effort control at all.
Ceilings also move by model generation, which is why the route’s own effort_values is the answer rather than a rule of thumb. Three cases catch people out:
minimalbelongs to the original gpt-5 family only. Thegpt-5,gpt-5-mini, andgpt-5-nanoroutes accept it; gpt-5.1 and later reject it, and so do the o-series routes.- Claude on Bedrock stops at
high. Bedrock’s Converse API drops the field adaptive thinking needs, soxhighandmaxare unavailable there even though the directanthropicvendor accepts both. maxon gpt-5.6 and later runs atmax. Gateway dispatches those requests down a path that carries the level through rather than clamping it. The clamp does still apply below a 2,048-token output budget, because that path fails outright on an exhausted budget where the alternative returns a partial answer.
Which route serves you depends on:
- A
vendororvendorspin in the request. - Your own provider keys. With BYOK preference on, requests go to the vendors you hold keys for, even when another vendor accepts more levels.
- Routing policies, and how Gateway picks a vendor among the routes that survive your organization’s filters.
A request that names an effort level steers that choice: candidates narrow to routes that can honor the level before the cheapest one wins, as long as at least one candidate can. So on an unpinned request you usually land on a route that accepts the level you asked for, and only fall back to the closest level when no route accepts yours. An explicit vendor pin skips the narrowing, because the pin is the stronger instruction.
If your requested level is not in the resolved route’s list, the Gateway does not reject the request. It sends the closest level the route accepts and tells you what it did.
The reasoning_effort_adjusted warning
When the applied level differs from the one you asked for, the response carries a warning. detail.applied_effort is what actually ran.
Streaming responses carry the same warning on the final chunk. On /v1/openai/responses it appears in the same warnings array.
Watch for reasoning_exhausted alongside it. That one means the model spent its whole thinking budget and never wrote an answer, so the response is a 200 with finish_reason: length, empty content, and full billing. Raise the budget or lower the effort level and retry. See Warnings for the rest of the vocabulary.
If a level is being adjusted, the usual cause is something narrowing the candidate set: a vendor pin, a BYOK preference, or a policy whose targets all lack the level. Remove the constraint and Gateway prefers a route that accepts your level on its own. include_routing_metadata: true shows routing.vendor_used when you are not sure which route served you.
Disable reasoning
If a route advertises disable_supported: true, you can request thinking.type: "disabled".
Use disable controls for latency-sensitive requests, short classification tasks, or prompts where reasoning tokens are not worth the extra cost. If the route does not advertise disable_supported, Gateway may strip unsupported disable fields before sending the request upstream.
Read thinking blocks
Reasoning output appears as thinking content blocks before or alongside text blocks.
In code, branch on content.type.
Some providers may include reasoning-like text inside a normal text block. Treat the public /v1/models route metadata as the source of truth for whether Gateway expects separate reasoning blocks.
Replay reasoning in multi-round tool loops
A tool loop sends the model’s previous turn back on the next request. When reasoning is enabled on an Anthropic route, that turn contains a signed thinking block, and the signature has to travel with it.
Anthropic rejects a thinking block whose signature is missing with 400 thinking.signature: Field required. Gateway drops unsigned blocks before dispatch to prevent that error, so a lost signature does not fail the request — the model silently loses its own prior reasoning on every later round, and you are still billed for the thinking tokens. Echo the signature back and the reasoning is preserved.
Each surface exposes the signature differently, because the OpenAI wire format has no field for provider reasoning.
On the native and Anthropic surfaces, echo the assistant content blocks back verbatim and the signature travels with them. On the OpenAI-shaped surfaces, both fields are Gateway extensions, so your client has to carry them explicitly.
Claude produces reasoning on the first assistant turn of a request. After a tool result is returned it typically answers without a new thinking block, so a long loop usually carries one signed block rather than one per round. That is provider behavior, not a Gateway limitation.
Redacted reasoning
Anthropic sometimes encrypts reasoning instead of returning it in the clear. Gateway preserves those blocks, and they carry the same replay requirement.
On /v1/anthropic the block keeps its provider shape:
On /v1/responses it arrives as a thinking block with empty text and the payload on redacted_data:
There is nothing readable to show a user. Pass it back unchanged with the rest of the turn.
Reasoning with routing policies
Routing policies can choose among multiple vendors and models. If a request includes thinking, every route that might serve the request must support Gateway-controlled reasoning, or the request can fail during capability checks.
For deterministic behavior, pin model and vendor when you need a specific reasoning mode.
Use a routing policy when you only need a reasoning-capable route, not a specific provider behavior. In that case, configure the policy with models whose selected vendor routes all support the same reasoning control.
Streaming
Reasoning works with stream: true on supported routes. Gateway accumulates provider reasoning deltas and returns them as thinking content in the streamed response.
Streaming can delay visible text because the model may spend tokens on thinking before it emits final answer text.
Reasoning composes with streaming, structured output, and tool calling at the same time. None of those features is non-streaming-only.
How reasoning arrives depends on the surface:
/v1/responsesstreams cumulative frames. Each chunk carries the wholethinkingblock accumulated so far, not a delta, so read the latest frame rather than concatenating. The signature appears once the block is complete./v1/anthropicstreamsthinking_deltaevents, then asignature_deltacarrying the signature, matching Anthropic’s own stream. Redacted blocks arrive as a completecontent_block_startof typeredacted_thinking, since there is nothing to stream incrementally./v1/openai/chat/completionsand/v1/ai-sdk/chat/completionsstream reasoning text ondelta.thinkingand deliverdelta.thinking_signatureon the final chunk, because the signature only exists once the block is finished.
Common errors
The model does not support Gateway-controlled reasoning
The selected route does not support the thinking field. Use GET /v1/models, inspect vendors.<vendor>.capabilities.reasoning.controls, and choose a route that supports thinking.budget_tokens or another compatible control.
budget_tokens is required when thinking is enabled
Add a positive budget_tokens value when thinking.type is "enabled". Use a smaller budget for latency-sensitive requests and a larger budget for complex analysis.
A reasoning_effort_adjusted warning came back
The route that served the request does not accept the level you sent, so the Gateway applied the closest one (detail.applied_effort) or, when the route has no effort control, dropped it. Check detail.vendor, compare it with that vendor’s reasoning.effort_values in /v1/models, and pin a vendor that lists your level. See Effort levels per route.
The response has no thinking block
The route may not have produced separate reasoning for that prompt, the route may expose reasoning as normal text, or the selected vendor may not be the route you expected. Include include_routing_metadata: true while debugging and verify routing.vendor_used.