Reasoning
Some models think before they answer. They produce a reasoning trace first, then the final text. kenari gives you one set of parameters for this on every chat format, returns the trace next to the answer, and bills the thinking as Output tokens. More thinking usually means better answers on hard problems. It can also mean a slower reply and more tokens, which cost money wherever Output tokens are billed.
Find models that support reasoning
Section titled “Find models that support reasoning”GET /v1/models describes reasoning for each model. The call is public, so you can filter it without a key:
curl -s https://kenari.id/v1/models | jq -r '.data[] | select(.reasoning == true) | .id'| Field | Meaning |
|---|---|
reasoning | true when the model can think. |
reasoning_options | The effort levels the model accepts, for example ["low", "medium", "high"]. Absent when the model has no effort levels. |
reasoning_toggle | true when you can switch reasoning on or off per request. |
The levels are none, minimal, low, medium, high, xhigh and max. none turns reasoning off, and minimal is treated as low. If you ask for a level the model does not list, kenari uses the highest listed level at or below it. If the model lists no level at or below the one you asked for, the level you asked for is sent unchanged. On a model that does not support reasoning, the reasoning fields are ignored.
Request reasoning
Section titled “Request reasoning”Each format has its own field. kenari maps all of them to the native reasoning control of the model’s provider.
| Format | How to ask |
|---|---|
| Chat completions | reasoning_effort, or the reasoning object below |
| Messages | thinking: {"type": "enabled", "budget_tokens": N}, or output_config: {"effort": "high"} |
| Responses | reasoning: {"effort": "high"} |
With Chat completions:
curl https://kenari.id/v1/chat/completions \ -H "Authorization: Bearer $KENARI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "step-3-7-flash:free", "reasoning_effort": "medium", "messages": [ {"role": "user", "content": "What is 17 * 24? Show the steps."} ] }'With Messages. Point the Anthropic SDK at https://kenari.id, without /v1:
import os
import anthropic
client = anthropic.Anthropic( base_url="https://kenari.id", api_key=os.environ["KENARI_API_KEY"],)
message = client.messages.create( model="step-3-7-flash:free", max_tokens=4096, thinking={"type": "enabled", "budget_tokens": 2048}, messages=[{"role": "user", "content": "What is 17 * 24? Show the steps."}],)
for block in message.content: if block.type == "thinking": print("Reasoning:", block.thinking) elif block.type == "text": print("Answer:", block.text)thinking: {"type": "disabled"} turns reasoning off on Messages only for models served through an Anthropic-style API. For other models it removes the effort setting, and the model’s default applies. To turn reasoning off on a model that supports it (reasoning_toggle is true), use reasoning: {"enabled": false} on Chat completions. A budget must be at least 1,024 and below max_tokens. At a max_tokens of 1,024 or less, models served through an Anthropic-style API get no thinking at all.
The reasoning object
Section titled “The reasoning object”Chat completions also accepts an OpenRouter-style reasoning object, which you can send on every chat model:
| Field | Type | Description |
|---|---|---|
effort | string | One of the levels above. |
enabled | boolean | false turns reasoning off. true without effort or max_tokens turns it on at medium. |
max_tokens | integer | A token budget for the thinking. Models that take a level instead of a budget may ignore it, so prefer effort. |
exclude | boolean | true hides the trace from the response. The thinking is still generated and billed. |
When a request has both reasoning and reasoning_effort, the reasoning object wins.
curl https://kenari.id/v1/chat/completions \ -H "Authorization: Bearer $KENARI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "step-3-7-flash:free", "reasoning": {"enabled": false}, "messages": [ {"role": "user", "content": "In one word, what is the capital of Indonesia?"} ] }'kenari turns enabled: false into the control the provider needs, so your code does not change per model. A model without reasoning_toggle set to true may keep thinking.
Set the level in the model id
Section titled “Set the level in the model id”Some coding tools offer only a few levels, or send none for a model they do not know. To pick the level anyway, add it to the model id after a colon:
curl https://kenari.id/v1/chat/completions \ -H "Authorization: Bearer $KENARI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-v4-1-flash:free:max", "messages": [ {"role": "user", "content": "What is 17 * 24? Show the steps."} ] }'kenari removes the suffix and runs the model at that level, whatever the request asks for. It writes the level into reasoning_effort, the reasoning object, thinking and output_config, and it also overrides a request that turns reasoning off. Everything else sees the plain model id: the model in the response, your key’s model restrictions, billing and the usage log. The x-kenari-gated-effort response header shows the level kenari sent.
- The level must be one the model lists in
reasoning_options. A level the model does not list, such asdeepseek-v4-pro:medium, is refused with a 400 that names the levels the model has.noneworks only on a model that lists it, and turns reasoning off. kenari/autoand a route acceptlow,medium,high,xhighandmax. Each model they call gets its highest listed level at or below that one. Abyok/id sends the level to your provider unchanged.- The suffix combines with
:freein either order.deepseek-v4-1-flash:free:maxanddeepseek-v4-1-flash:max:freeare the same model. - Ids with a level are not listed in
GET /v1/models. Type the id into your tool as a custom model name. Some tools look up the context window by model name, so set it by hand if your tool has that option. - A route name cannot end in a level, for example
fast:high.
The suffix is a kenari extension. OpenRouter uses the same colon form for its model variants, but none of its variants sets a reasoning level.
Read the reasoning trace
Section titled “Read the reasoning trace”Where the trace appears depends on the format.
On Chat completions it is in choices[].message.reasoning. The same text is also in reasoning_content, for tools that read that name.
{ "choices": [ { "message": { "role": "assistant", "reasoning": "17 * 24 = 17 * 20 + 17 * 4 = 340 + 68 ...", "reasoning_content": "17 * 24 = 17 * 20 + 17 * 4 = 340 + 68 ...", "content": "17 * 24 = 408." }, "finish_reason": "stop" } ]}On Messages it is a thinking block before the text block:
{ "content": [ {"type": "thinking", "thinking": "17 * 24 = 17 * 20 + 17 * 4 ..."}, {"type": "text", "text": "17 * 24 = 408."} ]}On Responses it is a reasoning item at the start of output, with the text in summary[].text. In a stream the trace arrives before the answer. See Streaming for the events of each format.
kenari does not shorten or filter the trace. It is the text the model produced. Some models return no trace, even when they think.
Billing
Section titled “Billing”Reasoning tokens are billed as Output tokens, at the same rate as answer tokens. A higher effort level or a larger budget can mean more tokens, and so a higher charge on models that bill them. :free models cost nothing. exclude: true changes nothing about the bill, because the thinking still happens. To spend less, lower effort or turn reasoning off. See How billing works.
Small max_tokens and empty answers
Section titled “Small max_tokens and empty answers”Thinking uses part of max_tokens. If max_tokens is small, the thinking can use all of it before the answer starts, and the response has no answer text. kenari reports this as a cut-off, not as a normal stop:
| Format | Signal |
|---|---|
| Chat completions | finish_reason is "length" |
| Messages | stop_reason is "max_tokens" |
| Responses | status is "incomplete" with incomplete_details: {"reason": "max_output_tokens"} |
The thinking tokens are still billed. Give a reasoning model enough max_tokens for the thinking and the answer together, or lower the effort.