Reasoning
Thinking models, the reasoning object, and how thought is billed.
Models tagged REASONING in the catalog can think before answering. Request
it with the reasoning object — one surface across every provider,
whatever their native API calls it:
{
"model": "openai/gpt-oss-120b",
"stream": true,
"reasoning": { "effort": "low" },
"messages": [{ "role": "user", "content": "Which is larger, 9.11 or 9.9?" }]
}
| Field | Meaning |
|---|---|
effort | minimal, low, medium, or high — mapped to each provider's dial |
max_tokens | explicit thinking budget, for budget-style models |
exclude | true = think internally but omit the text from the response |
enabled | false = disable thinking on models that default to it |
Reading the thought stream
Reasoning text arrives on its own delta field, separate from content:
data: {"choices":[{"delta":{"reasoning":"Compare decimals: 9.11 vs 9.9 …"},…}]}
data: {"choices":[{"delta":{"content":"9.9"},…}]}
Some models attach reasoning_details entries alongside — summaries,
provider signatures, or encrypted blocks that let multi-turn tool use resume
correctly. Pass them back untouched if you continue the conversation.
Whether the thought TEXT is visible depends on the model and route; thinking TOKENS are always accounted either way.
Thinking variants
Some models also exist as a :thinking catalog variant (for example
anthropic/claude-opus-5:thinking) — same underlying model with thinking
pre-enabled and its own pricing row. Using the base id with a reasoning
object and using the variant are equivalent; the variant exists so a plain
model switch is enough for clients that can't send extra fields.
Billing
Thinking tokens are reported in
usage.completion_tokens_details.reasoning_tokens, inside
completion_tokens. They're billed at the model's reasoning rate when one is
listed, otherwise at the output rate — and the in-band usage.cost already
includes them, so there is never a surprise.