The public chat models reason by default. Read the reasoning, control its effort, turn it off, and avoid an empty answer.
The public chat models on Munito AI, such as qwen/qwen3.8-27b and zai-org/glm-5.3-flash, reason before they answer by default. google/gemma-4-12b reasons only when a request turns its reasoning on. The API returns the reasoning in its own field, apart from the answer.
Reasoning tokens are output tokens: they count in the output usage, and you pay the output price for them.
The OpenAI SDK uses the base URL https://api.munito.ai/inference/v1, and the Anthropic SDK uses https://api.munito.ai/inference. Both read the key from MUNITO_API_KEY.
Effort levels and the off switch
| Model | reasoning_effort | Turn reasoning off |
|---|---|---|
qwen/qwen3.8-27b | low, medium, xhigh | reasoning_effort: "none", or chat_template_kwargs: {"enable_thinking": false} |
zai-org/glm-5.3-flash | low, high, max | Not available. reasoning_effort: "none" runs as low. |
deepseek-ai/deepseek-v4-flash | low, high, max | reasoning_effort: "none", or chat_template_kwargs: {"thinking": false} |
deepseek-ai/deepseek-v4.1-flash-1017 | low, high, max | reasoning_effort: "none", or chat_template_kwargs: {"enable_thinking": false} |
aleph-alpha/kolibri-1 | none, low, medium, high | reasoning_effort: "none", or chat_template_kwargs: {"enable_thinking": false} |
google/gemma-4-12b | - | Off by default. chat_template_kwargs: {"enable_thinking": true} turns it on. |
A level that a model does not list moves to the nearest level that it lists. On a tie, it moves to the lower level. For example, high on qwen/qwen3.8-27b runs as medium.
none turns reasoning off with the switch of the model. A model that always reasons runs its lowest level instead.
none with a switch that the same request turns on returns 400, and so does a value that is not an effort level:
{
"error": {
"message": "'reasoning_effort' is not supported: choose one of: low, medium, xhigh",
"type": "invalid_request_error",
"param": "reasoning_effort",
"code": null
}
}A chat_template_kwargs option that the model does not list returns 400 with 'chat_template_kwargs' is not supported: unsupported template option or value.
Read the reasoning
pip install openaiimport os
from openai import OpenAI
client = OpenAI(
base_url="https://api.munito.ai/inference/v1",
api_key=os.environ["MUNITO_API_KEY"],
)
response = client.chat.completions.create(
model="zai-org/glm-5.3-flash",
messages=[{"role": "user", "content": "A train leaves at 09:40 and arrives at 13:15. How long is the trip?"}],
reasoning_effort="low",
max_tokens=2048,
)
message = response.choices[0].message
print("Reasoning:", (message.model_extra or {}).get("reasoning"))
print("Answer:", message.content)
print("Output tokens:", response.usage.completion_tokens)| API | Where the reasoning is | Reasoning tokens |
|---|---|---|
| Chat Completions | message.reasoning, and delta.reasoning in a stream | In usage.completion_tokens |
| Responses | An output item of type reasoning, with reasoning_text parts | In usage.output_tokens. usage.output_tokens_details.reasoning_tokens gives the count. |
| Messages | A thinking block before the text block | In usage.output_tokens |
In a Chat Completions stream, the usage chunk also gives the count in usage.completion_tokens_details.reasoning_tokens. See Streaming.
The empty answer trap
The model writes its reasoning first and its answer after it. max_tokens limits both together.
When the limit is too small, the output stops during the reasoning. content is then null, and finish_reason is length.
{
"message": {
"role": "assistant",
"content": null,
"reasoning": "The user asks for 17 * 23. Let me"
},
"finish_reason": "length"
}To prevent it:
- Set
max_tokensto 2048 or more. The model stops when it is done, and you pay only for the tokens that it makes. - Lower the effort with
reasoning_effort: "low". - Turn the reasoning off where the model allows it.
- Check
finish_reason. If it islength, send the request again with a higher limit.
Turn reasoning off
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.munito.ai/inference/v1",
api_key=os.environ["MUNITO_API_KEY"],
)
response = client.chat.completions.create(
model="qwen/qwen3.8-27b",
messages=[{"role": "user", "content": "Translate 'good morning' into German."}],
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
max_tokens=512,
)
print(response.choices[0].message.content)The OpenAI SDK has no chat_template_kwargs argument, so send it in extra_body. With curl, put it in the JSON body.
Responses
On Responses, set the level with reasoning: {"effort": "low"}. The levels are the same as for reasoning_effort.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.munito.ai/inference/v1",
api_key=os.environ["MUNITO_API_KEY"],
)
response = client.responses.create(
model="qwen/qwen3.8-27b",
input="A train leaves at 09:40 and arrives at 13:15. How long is the trip?",
reasoning={"effort": "low"},
max_output_tokens=2048,
)
print(response.output_text)
print("Reasoning tokens:", response.usage.output_tokens_details.reasoning_tokens)Messages
On Messages, thinking: {"type": "disabled"} turns the reasoning off. On zai-org/glm-5.3-flash, which always reasons, it selects the low level.
thinking: {"type": "enabled"} and {"type": "adaptive"} turn it on. Set the level with output_config.effort.
pip install anthropicimport os
from anthropic import Anthropic
client = Anthropic(
base_url="https://api.munito.ai/inference",
api_key=os.environ["MUNITO_API_KEY"],
)
message = client.messages.create(
model="qwen/qwen3.8-27b",
max_tokens=2048,
messages=[{"role": "user", "content": "What is 17 * 23?"}],
thinking={"type": "disabled"},
)
for block in message.content:
print(block.type, ":", getattr(block, "text", None) or getattr(block, "thinking", ""))thinking.budget_tokens is accepted from 1024 up to below max_tokens, but the model does not keep to it. max_tokens is the only limit on the output.
See Models and pricing for the output price of each model.