Reasoning models

Reasoning models

Some models think before they answer. The catalogue says which:
capabilities.reasoning is true, and capabilities.reasoning_efforts lists the levels
that model actually implements.

curl -s https://hisoka.ai/api/v1/models \
  | jq '.data[] | select(.capabilities.reasoning) | {id, levels: .capabilities.reasoning_efforts}'

Setting effort

{
  "model": "glm-5.3-flash",
  "reasoning_effort": "high",
  "messages": [{ "role": "user", "content": "Which of these two designs is safer?" }]
}

Accepted: none, low, medium, high, max. The value is clipped to what the model
declares, so a level it does not implement is not forwarded blindly.

An empty answer is a finished turn

A reasoning model given a small max_tokens can spend the whole budget thinking and return
content: "" with finish_reason: "stop".

That is a finished turn, not a failed one. The gateway keeps content empty, keeps the
reasoning separate, and records reasoning_only in the reply metadata.

Retrying this costs you twice

The model already answered; it just answered with thinking instead of text. A retry pays
for that same reasoning again and often produces the same empty content, because nothing
about the request changed. Raise the cap instead.

The gateway only retries on finish_reason: "length", which means the answer was actually
cut off.

Cap floors, measured

A cap too small to think leaves no room to answer. Observed minimums on this gateway:

Model family Smallest cap that produces text
deepseek 64 tokens
glm 256 tokens at reasoning_effort: max

For a model that reasons, the gateway raises a cap below 256 and reports it:

{ "hisoka": { "max_tokens": 256, "cap_raised_from": 16 } }

cap_raised_from is how you know a cap you set was not the cap that ran. A model that does
not reason keeps your exact cap, because raising it would spend tokens nobody asked
for and bill for them.

Leave max_tokens out

The reliable lever is the cap, not the effort level. Input and output share one window, so
a cap near the ceiling leaves no room for the prompt and the provider answers 400 asking
you to shorten the messages.

Sending no cap lets the provider apply its own default, which is sized for its model.

Effort levels behave differently per family

This is why the gateway clips rather than forwards everything:

  • deepseek answers on every level.
  • glm returns text on low and high, spends everything thinking on max at a small
    cap, and on none pastes its inner monologue into content because it has no
    “thinking off” mode.

A level a model treats as invalid turns an instruction into visible garbage you then pay
for, which is worse than ignoring the parameter.

In a stream

Reasoning arrives as its own deltas before any content. A stream with reasoning and no text
is the same finished turn described above, and it still emits its terminator so the client
is not left waiting. See Streaming.

Cost

Reasoning tokens bill as output, because that is how every provider charges them. A model
set to max on a hard question can therefore cost more than the visible answer suggests;
hisoka.usd_micro_charged is the number that settles it.