Reasoning
Many current models reason before answering. Where the depth is adjustable, it is a parameter: reasoning_effort on Chat Completions, reasoning.effort on Responses, output_config.effort (or a thinking object) on Messages. Where it isn't adjustable, the model still reasons, and you pay for it as output tokens.
Works with
Models whose catalog entry lists reasoning_efforts. The levels vary by model and GET /v1/models is authoritative; the per-model ladder is also on the capability matrix. Models with reasoning_efforts: null (mindshub_air, kimi among them) reason internally on every request and the level isn't tunable.
A model can also pin the level it runs at without offering a choice of it: a null reasoning_efforts alongside a non-null default_reasoning_effort. mindshub_air is pinned to medium this way, so every request reasons at medium and a reasoning_effort you send is replaced by the pinned level rather than honored — reported as a clamp in X-MindsHub-Clamped-Params. Pick a model that publishes a ladder if you need to choose the level.
Request
- Chat Completions
- Responses
- Messages
- Chat Completions
- Responses
- Messages
response = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": "Prove that √2 is irrational."}],
reasoning_effort="high",
)
print(response.choices[0].message.content)
response = client.responses.create(
model="deepseek-v4-flash",
input="Prove that √2 is irrational.",
reasoning={"effort": "high"},
)
print(response.output_text)
message = client.messages.create(
model="deepseek-v4-flash",
max_tokens=4096,
messages=[{"role": "user", "content": "Prove that √2 is irrational."}],
output_config={"effort": "high"},
)
print(message.content[-1].text)
const response = await client.chat.completions.create({
model: "deepseek-v4-flash",
messages: [{ role: "user", content: "Prove that √2 is irrational." }],
reasoning_effort: "high",
});
console.log(response.choices[0].message.content);
const response = await client.responses.create({
model: "deepseek-v4-flash",
input: "Prove that √2 is irrational.",
reasoning: { effort: "high" },
});
console.log(response.output_text);
const message = await client.messages.create({
model: "deepseek-v4-flash",
max_tokens: 4096,
messages: [{ role: "user", content: "Prove that √2 is irrational." }],
output_config: { effort: "high" },
});
console.log(message.content.at(-1));
These samples use deepseek-v4-flash, which takes none, low, high and max and draws the prepaid wallet.
Requests never fail over the effort level. A recognized level outside a model's ladder is clamped onto it: below the floor, including none on a model without an off switch, you get the cheapest supported rung (which can cost more than the unsupported level you requested); above the ceiling you get the top rung; between rungs you get the lower one. Clamps are reported in X-MindsHub-Clamped-Params.
An unrecognized value such as a typo fits no rung. On a model that publishes a default_reasoning_effort you get that level, clamped onto the ladder like any other, and it is reported as a clamp; only a model that publishes no default drops the parameter and reports it in X-MindsHub-Dropped-Params, letting the provider's own default apply. On models with reasoning_efforts: null and no default the drop still comes with no header.
A clamp on an unrecognized level names the category other, not the value you sent — reasoning_effort=other>medium, never reasoning_effort=hgih>medium — because a level we don't recognize is caller-supplied text and isn't echoed back in a response header. A level we do recognize is named exactly as you sent it.
One consequence worth planning for: a typo no longer lands on the provider's default, it lands on the model's published one. On models whose default is the top of their ladder (glm, qwen, gemini, grok-4-5 among them) that is the dearest rung; on gpt-mini and gpt-nano, whose default is none, it turns reasoning off. Read default_reasoning_effort off GET /v1/models if that matters to you, and send a level you have validated.
If you send nothing, the model's default_reasoning_effort applies, which for most reasoning models is not "off". Send the lowest listed level explicitly if you want speed over depth.
Extended thinking on Messages
A thinking object on a Messages request ({"type": "enabled", "budget_tokens": 8000}) is forwarded to the target model where that model accepts it, including its budget_tokens; the current Claude 5 models accept it. thinking and redacted_thinking blocks in your message history are replayed to the model unmodified, so a multi-turn tool workflow on a thinking model keeps working. On the OpenAI-shaped APIs there is no thinking object; use the effort level.
Carrying reasoning across turns on Responses
include: ["reasoning.encrypted_content"] carries a reasoning model's thinking across chained turns (previous_response_id); the other include values are ignored. reasoning.summary asks for a summary on the returned reasoning item.
Response
- Chat Completions and Responses never return reasoning content; you get the final answer.
usage.completion_tokens_details.reasoning_tokens(oroutput_tokens_details.reasoning_tokens) is a subset of the output count, not an addition to it, broken out by the GPT/Grok families and Gemini models. Elsewhere it reads0, which means no separately-reported reasoning rather than no reasoning: the Claude family bills thinking as output without separating it. - Messages returns
thinkingblocks, on streamed and non-streamed turns alike, in Anthropic's required order (before the text), with theirsignature, usually with empty or withheld content. Don't assume the first block is your text.
Streaming
On Messages, thinking blocks stream as content_block_* events before the text and carry a signature so a streaming client can replay them. On the OpenAI-shaped APIs nothing about the stream changes. See Streaming.
Per-model differences
- Levels differ by model:
sonnetsupportslowthroughmax,deepseek-v4-flashtakesnone,low,highandmax,gpt-miniaddsnone. Read the model's own list rather than assuming a family shares one ladder. mindshub_airandkimireason internally with no adjustable level. Budgetmax_tokensgenerously for them (a few hundred tokens of headroom) or the reasoning uses the cap and the visible answer arrives truncated withfinish_reason: "length".mindshub_airis pinned tomedium: it publishes no ladder but does publish adefault_reasoning_effort, so every request reasons at that level and one you send is replaced by it.kimipublishes neither, so a level you send it is dropped with no header.- Gemini sets depth through
thinking_level, which the effort parameter carries; it accepts nothinkingobject.
Errors you can hit
None specific to this feature: an out-of-ladder level is clamped, and an unrecognized one falls back to the model's published default where it has one and is dropped where it does not — all reported in headers. A turn whose reasoning exhausted max_tokens ends with finish_reason: "length" (stop_reason: "max_tokens" on Messages, status: "incomplete" on Responses). See Errors.