Build
Reasoning models
Control how much reasoning models think with reasoning_effort or Claude's thinking, read the reasoning text, and understand how thinking tokens are billed.
On this page
Reasoning models think before they answer: they write internal reasoning tokens, then the reply. That makes them better at maths, planning, debugging and multi-step tool use, and slower and more expensive per request. You decide how hard they think.
Models with reasoning
| Model id | Input / 1M | Output / 1M |
|---|---|---|
| claude-opus-5-5 | $4.40 | $22 |
| claude-sonnet-5 | $2.20 | $11 |
| claude-haiku-4-5 | $1.10 | $5.50 |
| gpt-6.1-sol | $2.20 | $11 |
| gpt-5.6-sol | $5.50 | $33 |
| gpt-5.6-terra | $2.20 | $13.20 |
| grok-4.6 | $2.20 | $6.60 |
| claude-sonnet-5-5 | $2.20 | $11 |
| grok-4.7 | $2.20 | $6.60 |
| deepseek-v4-flash | $0.24 | $0.96 |
| deepseek-v4-pro | $1.32 | $3.96 |
Set the effort (OpenAI format)
On chat completions, reasoning_effort sets how much the model thinks. Common values are low, medium and high; some models also accept minimal, none or xhigh. Lower effort answers faster and uses fewer tokens.
curl https://api.oneaiapikey.com/v1/chat/completions \
-H "Authorization: Bearer $RELAYKIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-6.1-sol",
"reasoning_effort": "low",
"max_completion_tokens": 4000,
"messages": [{"role": "user", "content": "A bat and a ball cost $1.10 in total. The bat costs $1.00 more than the ball. How much is the ball?"}]
}'import os
from openai import OpenAI
client = OpenAI(base_url="https://api.oneaiapikey.com/v1", api_key=os.environ["RELAYKIT_API_KEY"])
reply = client.chat.completions.create(
model="gpt-6.1-sol",
reasoning_effort="low",
max_completion_tokens=4000,
messages=[{"role": "user", "content": "A bat and a ball cost $1.10 in total. The bat costs $1.00 more than the ball. How much is the ball?"}],
)
print(reply.choices[0].message.content)
print(reply.usage.completion_tokens_details.reasoning_tokens, "reasoning tokens")import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.oneaiapikey.com/v1", apiKey: process.env.RELAYKIT_API_KEY });
const reply = await client.chat.completions.create({
model: "gpt-6.1-sol",
reasoning_effort: "low",
max_completion_tokens: 4000,
messages: [{ role: "user", content: "A bat and a ball cost $1.10 in total. The bat costs $1.00 more than the ball. How much is the ball?" }],
});
console.log(reply.choices[0].message.content);
console.log(reply.usage.completion_tokens_details?.reasoning_tokens, "reasoning tokens");- Set
max_completion_tokens(ormax_tokens) with room for the thinking and the answer. If the limit is reached while the model is still thinking, you getfinish_reason: "length"and little or no text. - Many reasoning models accept only the default
temperatureandtop_p. Leave them unset. - The OpenRouter-style
reasoningobject ({"effort": "high"}or{"max_tokens": 4000}) is accepted as well. - In the Responses API, use
reasoning: {"effort": "low"}.
Claude models
Claude calls this extended thinking. You can turn it on in either format.
OpenAI format. Send reasoning_effort to a Claude model and the gateway turns it into Claude’s thinking settings. The thinking text comes back in message.reasoning_content (and delta.reasoning_content when streaming), separate from content.
reply = client.chat.completions.create(
model="claude-sonnet-5-5",
reasoning_effort="medium", # turns on Claude's extended thinking
max_tokens=8000,
messages=[{"role": "user", "content": "Plan a zero-downtime migration from MySQL 5.7 to 8.0."}],
)
msg = reply.choices[0].message
print(getattr(msg, "reasoning_content", None)) # Claude's thinking, when returned
print(msg.content) # the answerAnthropic format. On /v1/messages, pass Anthropic’s thinking parameter. The reply contains thinking blocks before the text block.
import anthropic, os
client = anthropic.Anthropic(base_url="https://api.oneaiapikey.com", api_key=os.environ["RELAYKIT_API_KEY"])
message = client.messages.create(
model="claude-sonnet-5-5",
max_tokens=16000,
thinking={"type": "enabled", "budget_tokens": 8000}, # budget must be below max_tokens
messages=[{"role": "user", "content": "Plan a zero-downtime migration from MySQL 5.7 to 8.0."}],
)
for block in message.content:
if block.type == "thinking":
print("THINKING:", block.thinking[:200], "...")
elif block.type == "text":
print(block.text)In multi-turn conversations with tools, send the assistant’s thinking blocks back unchanged, as Anthropic requires. The Anthropic SDKs do this when you append message.content as it is.
What you are billed for
- Reasoning tokens are output tokens, billed at the model’s output rate, even when the reasoning text is not shown to you.
usage.completion_tokensalready includes them;usage.completion_tokens_details.reasoning_tokensshows how many there were, when the provider reports it.- A hard question at
higheffort can use many times more tokens than the visible answer. Start atlowand raise it only where answers get better.
Related
- Cost control: set limits per key.
- Models: output prices per model.