A thinking model reasons before answering and returns the reasoning beside the answer.
Thinking on and off
Thinking is on by default. "chat_template_kwargs": {"enable_thinking": false} turns thinking off.
| Property | Thinking on | Thinking off |
|---|---|---|
chat_template_kwargs.enable_thinking | true (default) | false |
message.reasoning | Reasoning text | null |
| Streamed reasoning | delta.reasoning | None |
usage.completion_tokens | Answer plus reasoning | Answer |
usage.completion_tokens_details.reasoning_tokens | Reasoning tokens | 0 |
| First answer token | After the reasoning | Without a reasoning step first |
Use thinking for maths, code and multi-step questions. Turn thinking off for chat, extraction, classification, tool calls and many parallel requests.
chat_template_kwargs is not an OpenAI parameter. The Python SDK sends the field through extra_body; curl and
fetch send the field at the top level of the body.
Example
The example asks the same question with thinking on and off.
curl
curl https://api.albastov.com/v1/chat/completions \
-H "Authorization: Bearer $ALBASTOV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-27b",
"max_tokens": 400,
"messages": [{"role": "user", "content": "Is 91 prime? Answer yes or no."}]
}'Python
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.albastov.com/v1", api_key=os.environ["ALBASTOV_API_KEY"])
question = [{"role": "user", "content": "Is 91 prime? Answer yes or no."}]
on = client.chat.completions.create(model="qwen3.8-27b", messages=question, max_tokens=400)
msg = on.choices[0].message
print("reasoning:", getattr(msg, "reasoning", None))
print("answer:", msg.content.strip())
print("reasoning tokens:", on.usage.completion_tokens_details.reasoning_tokens)
off = client.chat.completions.create(
model="qwen3.8-27b", messages=question, max_tokens=400,
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
print("answer without thinking:", off.choices[0].message.content.strip()){
"message": {
"role": "assistant",
"content": "\n\nNo",
"reasoning": "We need answer user: \"Is 91 prime? Answer yes or no.\" Need final yes or no. 91=7*13 not prime. Answer no. Ensure only yes/no maybe \"No\".\n"
},
"usage": {
"prompt_tokens": 63,
"completion_tokens": 50,
"total_tokens": 113,
"completion_tokens_details": {"reasoning_tokens": 46}
}
}Token budget
max_tokens includes reasoning tokens. A low max_tokens ends the response during the reasoning, with
finish_reason: "length" and empty content. Set max_tokens to 1,000 or more for hard questions, and stream
long reasoning: a non-streamed request without a response after about 100 s fails with 524.
Reasoning field
The reasoning field is reasoning (delta.reasoning in a stream). Clients written for other servers may read
reasoning_content instead. The OpenAI Python SDK returns reasoning as an attribute: read message.reasoning.
contentcan start with blank lines after the reasoning. Trimcontent.- Send earlier assistant turns with
contentonly, withoutreasoning.
Model support
Every chat model reasons (capabilities.thinking is true in GET /v1/models). The enable_thinking switch is
confirmed on qwen3.8-27b, qwen3.8-27b-fast and qwen3.8-27b-uncensored. qwen3.8-27b-uncensored reasons more
briefly than qwen3.8-27b.
Reference
- Chat completions reference:
chat_template_kwargs,max_tokensand the reasoning response fields.