Reasoning Models reasoning_effort Extended Thinking OpenAI API Claude API

Reasoning Model API Parameters, Compared Across Providers

OpenAI reasoning_effort, Anthropic thinking, and Gemini thinkingBudget all control hidden reasoning tokens billed as output. How each knob works and how they differ.

AveMujica API 8 min read

Reasoning models add a step you cannot see: before writing an answer, the model produces hidden reasoning tokens, and those tokens cost money, consume the context window, and add latency. Every provider gives you a dial to control how much of this happens, but the three dials have different names, different value scales, and different defaults — reasoning_effort on OpenAI, thinking on Anthropic, thinkingConfig on Gemini. Getting reasoning models right is mostly about understanding those three knobs and one shared fact: reasoning tokens are billed as output tokens even though you never read them. This article walks each provider's parameters, the usage fields that expose the hidden cost, and where the abstractions stop lining up.

The shared mental model

Regardless of provider, a reasoning request has the same anatomy. Your input tokens go in. The model generates two kinds of output: hidden reasoning tokens and visible answer tokens. Both are billed at the output rate, both count against the model's context window, and only the visible ones come back to you (optionally accompanied by a summary of the reasoning, never the raw reasoning itself on most models). The dial each provider exposes changes how many hidden tokens the model is willing to spend. Turn it up for hard problems and multi-step agentic loops; turn it down for latency-sensitive, shallow tasks. Everything below is a variation on that theme.

OpenAI: reasoning_effort and the reasoning object

On OpenAI reasoning models you set effort. Chat Completions takes a top-level reasoning_effort string; the Responses API takes a reasoning object whose effort field does the same job and adds room for a summary and context controls.

from openai import OpenAI
client = OpenAI(base_url="https://your-gateway.example.com/v1", api_key="AVE_GATEWAY_API_KEY")

# Responses API
resp = client.responses.create(
    model="gpt-5.6",
    input="Prove there are infinitely many primes p with p mod 4 == 3.",
    reasoning={"effort": "high", "summary": "auto"},
)

Effort values are model-dependent and can include none, minimal, low, medium, high, and xhigh; the default varies by model. Lower effort prioritizes speed and fewer tokens, higher effort yields more thorough output at more cost. The hidden work is metered: reasoning tokens appear in usage under output_tokens_details as reasoning_tokens, so you can watch the invisible spend even though the tokens themselves are withheld. To see why the model concluded something, request a summary (summary: "auto" or "detailed"), which returns a summarized reasoning trace in the reasoning output item — you must opt in; it is not included by default.

Two features matter for stateless and agentic setups. For zero-retention operation, send store: false and add reasoning.encrypted_content to the include array; the API returns encrypted reasoning you pass back on the next turn to preserve continuity without the server storing anything. And reasoning.context (auto, current_turn, or all_turns) controls which prior reasoning items the model may draw on across a chained conversation.

The parameter you must not forget is max_output_tokens. It caps total generated tokens — reasoning plus visible answer — so if you set it too low the budget can be consumed entirely by hidden reasoning and you receive a status of incomplete (with incomplete_details citing max_output_tokens) and no visible text, while still paying for the input and reasoning tokens. OpenAI recommends reserving a generous headroom (on the order of tens of thousands of tokens) for reasoning plus output when you start out. Budgeting that headroom is the same discipline described in LLM context window management.

Anthropic: from budget_tokens to adaptive thinking

Anthropic's extended thinking historically used an explicit token budget. You enable it with a thinking object of type: "enabled" and a budget_tokens cap:

import anthropic
client = anthropic.Anthropic(base_url="https://your-gateway.example.com", api_key="AVE_GATEWAY_API_KEY")

msg = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=16000,
    thinking={"type": "enabled", "budget_tokens": 10000},
    messages=[{"role": "user", "content": "Are there infinitely many primes p with p mod 4 == 3?"}],
)

Three rules govern budget_tokens. It sets the maximum tokens for internal reasoning and must be less than max_tokens (except when interleaved thinking with tools lets the limit become the whole context window). The model may not use the full budget, especially at large values. And the reasoning surfaces as thinking content blocks — each carrying a thinking text and a signature — before the text blocks; you are billed for the full thinking tokens generated, not the shorter summary, so the billed output count will not match what you visibly see.

There is an important version split to plan around. budget_tokens is being retired: it is deprecated on some current models and returns a 400 on the newest ones (for example the Opus 4.8/4.7 and Sonnet 5 generation), which instead use adaptive thinking — a thinking object of type: "adaptive" paired with an effort setting, moving Anthropic conceptually closer to OpenAI's effort dial. When you build, branch on the model: send budget_tokens to the models that still accept it and the adaptive/effort form to the ones that require it. A gateway can hide part of this, as the next section shows.

One tool-use rule is non-negotiable: during a tool loop you must pass the model's thinking blocks back unmodified in the following assistant message, or the API rejects the request with a 400. The blocks encode the reasoning that led to the tool call, and reordering or editing them breaks continuity. This mirrors OpenAI's advice to return reasoning items with function calls, and it is why portable tool calling across providers treats reasoning-block preservation as part of a correct tool loop.

Gemini: thinkingConfig and thinkingBudget

Gemini controls reasoning through a thinkingConfig inside generationConfig. The key field is thinkingBudget, a token allowance for thinking, with two special values: -1 lets the model decide dynamically, and (on models that allow disabling) 0 turns thinking off. An includeThoughts flag asks the API to return a thought summary. The consumed reasoning appears in usageMetadata as a thoughts token count, again billed as output.

from google import genai
from google.genai import types

client = genai.Client()
resp = client.models.generate_content(
    model="gemini-3.5-flash",
    contents="Are there infinitely many primes p with p mod 4 == 3?",
    config=types.GenerateContentConfig(
        thinking_config=types.ThinkingConfig(thinking_budget=-1, include_thoughts=True),
    ),
)

Which models let you disable thinking, and the exact budget ranges, vary by model tier — check the model page rather than assuming a value carries across generations.

What a gateway normalizes, and where it stops

Behind one OpenAI-compatible endpoint, a gateway forwards each provider's reasoning parameters to the upstream that understands them: reasoning_effort and the reasoning object to OpenAI, thinking to Anthropic, thinkingConfig to Gemini. It also folds the three different hidden-token counts into one unified usage view, so a reasoning request's real output cost is visible in your logs regardless of which vendor served it.

This gateway additionally offers a convenience worth knowing: it can parse an effort suffix on the model name and translate it into the provider's own reasoning parameter. Appending -high, -medium, -low, -minimal, -xhigh, or -max to a model id (for example claude-opus-4-8-high or a -thinking variant) lets a client that can only set a model string still choose an effort level, and the gateway maps that suffix to the right knob for the target provider. The registered model/effort variants and their per-model rates are published on the public pricing page.

Be explicit about the limits, because the abstractions genuinely do not align:

  • The scales are different. OpenAI's effort is an enum, Anthropic's legacy budget_tokens is an absolute token count, and Gemini's thinkingBudget is a token count with sentinel values. "High effort" and "10,000 budget tokens" are not translations of each other; mapping one to another is a heuristic, not an equivalence.
  • Defaults differ. Some models reason by default, some do not, and the default effort is model-specific. Do not assume silence means "no reasoning."
  • Feature coverage differs. Encrypted reasoning continuity, thought summaries, and disabling thinking are supported unevenly across providers. A gateway can pass a field through, but it cannot make a provider honor a capability it does not offer.

Treat the gateway as the layer that gives you one billing view and one passthrough path, and keep provider-specific logic where a genuine capability gap exists.

Practical defaults

A few starting rules save money and latency:

  1. Match effort to task depth, not to importance. A hard extraction needs more reasoning than a long but shallow summarization. Effort is about problem structure, not stakes.
  2. Always reserve output headroom. With any reasoning model, set the max-output cap high enough that hidden reasoning cannot starve the visible answer, or you will pay for reasoning and receive nothing.
  3. Measure the hidden tokens. Watch reasoning_tokens / thinking tokens in your usage logs; a task whose reasoning tokens dwarf its answer tokens is a candidate for lower effort or a non-reasoning model, a decision covered in choosing the right LLM model.

FAQ

Are reasoning tokens billed even though I never see them?

Yes. Hidden reasoning tokens are billed at the output-token rate on all three providers and also occupy the context window. That is why the billed output count is larger than the visible answer would suggest, and why watching the reasoning-token field in your usage logs matters — it is real spend you cannot see in the response body.

Why did I get an empty or incomplete response from a reasoning model?

Usually the output cap was too low and reasoning consumed the whole budget. OpenAI returns a status of incomplete citing max_output_tokens; Anthropic requires budget_tokens to be less than max_tokens. Raise the total output limit so hidden reasoning cannot starve the visible answer, and reserve generous headroom on reasoning routes.

Is Anthropic's budget_tokens the same as OpenAI's reasoning_effort?

They serve the same purpose but are not equivalent. reasoning_effort is an enum (low/medium/high and related values); budget_tokens is an absolute token count. On Anthropic's newest models budget_tokens is unsupported and adaptive thinking with an effort setting replaces it. A gateway can map an effort label onto a provider's parameter, but the mapping is approximate, not a one-to-one translation.

How do I set a reasoning level if my client can only send a model name?

Use the gateway's effort suffix. Append -high, -medium, -low, -minimal, -xhigh, or -max to the model id and the gateway parses it and applies the matching reasoning parameter for the target provider. This lets thin clients pick an effort level without sending the provider-specific field themselves.

Find the effort knee on your task

Run the same hard prompt three times at low, medium, and high effort through your gateway, and record two numbers from your usage logs each time: reasoning tokens and answer quality on your own rubric. You will usually find a knee where more effort stops improving the answer but keeps spending tokens. Pin your route just below that knee — that single measurement, on your task, beats any provider's default.

References