Sonex Labs

Empty replies from reasoning models in voice agents: thinking tokens eat your max_tokens

More language models now think before they answer, and teams building voice agents often switch them in without changing the settings that worked for the old model. When such a model returns an empty reply with the finish reason "length", it has almost always spent its whole output cap on hidden reasoning before writing a word. On a call that sounds like the agent choosing to stay silent. Check the finish reason and the reasoning token count first, then turn reasoning off for live turns or give the model a cap that leaves room to speak.

Reasoning model, empty reply: Empty replies from reasoning models in voice agents: thinking tokens eat your max_tokens
Written by
Anmol Agarwal
Published
Last updated
Reading time
7 min read
On this page
  1. Why a reasoning model can return nothing
  2. Why it is hard to diagnose in a voice agent
  3. How to spot it in your logs
  4. What reasoning costs on a call, even when it works
  5. Settings that stop empty turns
  6. Sources

Why a reasoning model can return nothing

A reasoning model writes hidden "thinking" tokens before its visible answer. A token is the unit a model reads and writes, roughly a short word or part of one. The output cap you send with a request, called max_tokens, max_completion_tokens or max_output_tokens depending on the API, counts both the thinking and the answer.

OpenAI's reasoning guide says the cap limits the "total number of tokens the model generates", reasoning included, and that the limit can be reached "before any visible output tokens are produced" (OpenAI reasoning guide). When that happens the request still succeeds. The reply has no content, and its finish reason, the field that says why the model stopped, reads "length".

The rule is not specific to one provider. NVIDIA's open voice-agent framework keeps reasoning off by default. Its configurations that turn reasoning on raise the generation limit from 1,024 to 4,096 tokens, because the reasoning block and the spoken answer share one budget (NVIDIA NeMo voice agent docs).

When the answer is in a different field

A related cause looks the same from outside. Servers that host open-weight models, such as vLLM, return the thinking in a separate field. The content field your pipeline reads can then be empty while the model was busy. The vLLM documentation also warns that this field was renamed from reasoning_content to reasoning, and client code still reading the old name may silently get an empty value (vLLM reasoning outputs).

A public example

Public reports show how ordinary the failure is. In an OpenAI community thread of 19 September 2025, o4-mini returned an empty message with finish reason "length" and usage showing 3,072 completion tokens, all 3,072 of them reasoning (OpenAI community thread). The poster had set reasoning effort to "low", had first tried a cap of 2,048 tokens and had then raised it to 3,072.

The same thread explains why the fault looks random. The poster found that retrying the same request sometimes worked and sometimes did not. How much a model reasons varies from request to request, even for one prompt, so a cap that is just big enough on most turns is exceeded on the turns where the model thinks longer.

Why it is hard to diagnose in a voice agent

An empty reply produces no error, so nothing alerts. And a silent agent is the symptom of half a dozen other faults, from a speech-to-text stall to a tool call the agent never spoke about, so the obvious suspects get checked first. Turn-taking settings and the prompt are usually blamed before anyone opens the raw response.

We hit this ourselves while probing a voice agent's model with a test harness. On the same model with a 320-token cap, 15 of 16 runs came back empty, each with about 320 reasoning tokens and no text. It nearly got written up as an empty-turn bug in the pipeline. The cause was the cap our harness was sending, not turn-taking and not the model.

Live calls were not affected, because production sent no output cap and no temperature for that model, so the provider's defaults applied. The fix was in the harness, which now sends exactly what production sends. We are not naming the model, because the lesson applies to any reasoning model.

How to spot it in your logs

Every OpenAI-compatible response carries the three facts you need: the finish reason, the visible content and the token usage. A reply where the finish reason is "length", the content is empty and there is no tool call is the signature. If usage also reports reasoning tokens close to the completion token count, the diagnosis is certain.

Log those fields on every turn, not only on errors. In a streaming pipeline the finish reason arrives on the last chunk, and token usage is often sent only if you ask for it, so make sure your client requests usage and your logger records it. The check below runs on a parsed response, including one from the Vyas LLM API, and is easy to wire into an alert on any assistant turn with no text and no tool call.

def empty_turn_reason(response: dict) -> str | None:
    """Explain an empty assistant turn in an OpenAI-compatible chat completion."""
    choice = response["choices"][0]
    message = choice.get("message") or {}
    content = (message.get("content") or "").strip()
    if content or message.get("tool_calls"):
        return None                                    # the turn said or did something
    usage = response.get("usage") or {}
    completion = usage.get("completion_tokens") or 0
    reasoning = (usage.get("completion_tokens_details") or {}).get("reasoning_tokens") or 0
    if choice.get("finish_reason") == "length":
        return f"output cap hit: {reasoning} of {completion} output tokens were reasoning"
    return f"empty reply, finish_reason={choice.get('finish_reason')}, {completion} output tokens"

# The shape reported in the o4-mini thread:
example = {
    "choices": [{"finish_reason": "length", "message": {"role": "assistant", "content": ""}}],
    "usage": {"completion_tokens": 3072,
              "completion_tokens_details": {"reasoning_tokens": 3072}},
}
print(empty_turn_reason(example))
# output cap hit: 3072 of 3072 output tokens were reasoning
Runs as shown on the example response; we have not run it against a live call. Some servers report reasoning under a different usage key, so check yours.
Decision chart for diagnosing a reasoning model empty response with finish_reason length in a voice agent
How to tell an output cap used up by reasoning from other causes of an empty voice-agent turn.

What reasoning costs on a call, even when it works

Even when the cap is large enough, reasoning is expensive in a voice agent, because nothing can be spoken until the thinking ends. NVIDIA's documentation says that "no content reaches text-to-speech" until the reasoning block closes. A June 2026 post from Chanl, a company that builds customer-experience agents, estimates that a 4,000-token thinking budget adds 3 to 5 seconds before the caller hears anything (Chanl, 21 June 2026). Our guide to LLM time to first token on phone calls shows how small that budget is to begin with.

The money cost is direct too, because OpenAI's guide says reasoning tokens are billed as output tokens. An empty reply that hit the cap is therefore billed in full. Take an illustrative case: a model that spends 300 tokens reasoning on each of 4 turns a minute adds 1,200 output tokens a minute. A short spoken reply needs roughly 240 (our working assumption of 4 turns of about 60 tokens).

At gpt-5-mini's listed $2.00 per million output tokens (OpenAI pricing), output cost rises from $0.00048 to $0.00288 a call-minute. That is six times as much, before you count the delay.

When reasoning earns its place

There is a competing view, and it has merit. Reasoning does improve some turns, such as checking an eligibility rule or settling a dispute. Chanl argues for a small, fast classifier that routes only those turns to a thinking path, while status checks and simple requests stay on a fast one.

That is a sound design. What does not work is leaving reasoning on by default for every "yes" and "thank you" on the call. If the slow turns are rare, a short spoken filler can cover them; our article on filler audio for voice agents explains when that helps.

Settings that stop empty turns

Pick one of three positions and set it on purpose. The first is to turn reasoning off for live turns. OpenAI's reasoning models take an effort setting whose values, depending on the model, include "none" or "minimal", and OpenAI notes that some models reject "none" with an error. Many open-weight models served by vLLM accept an enable_thinking switch through the chat template instead.

The second is to keep reasoning and size the cap for both parts. OpenAI recommends reserving at least 25,000 tokens for reasoning and output when you start experimenting, far more than a spoken reply needs. The third is what our production agents do: send no cap at all and let the provider's default apply. Reply length is then set through the prompt, and if you want a guard against runaway turns, a time limit provides one without cutting into the reasoning budget.

Why the alert stays on after the fix

Turning reasoning off is not a guarantee that it stays off. In April 2026, developers reported that GPT-5.4 on the Chat Completions endpoint ignored a reasoning effort of "none" whenever max_completion_tokens was also set, spending the whole cap on reasoning and returning an empty string (OpenAI community thread). OpenAI's support team acknowledged the bug and said on 20 April 2026 that a fix had been deployed.

A provider change can bring the same silence back without any change on your side. So keep the guard rails that catch the next surprise: the finish reason in every turn's log, an alert on turns with no text and no tool call, and a harness that sends the same settings as production. A silent agent has other causes too, such as a voice agent that ignores its tool result, and the same alert catches the start of those investigations.

Sources

  1. OpenAI: Reasoning models guide (output limits, billing, reasoning effort)Official
  2. OpenAI community: o4-mini returns empty response because reasoning tokens used all the completion tokens (19 September 2025)Secondary
  3. OpenAI community: GPT-5.4 ignores reasoning_effort "none" when max_completion_tokens is used (April 2026; fix deployed 20 April 2026)Secondary
  4. NVIDIA NeMo Labs Voice Agent: reasoning modeOfficial
  5. vLLM: reasoning outputsOfficial
  6. Chanl: Extended thinking for CX agents, when slow beats fast (21 June 2026)Secondary
  7. OpenAI API pricing (gpt-5-mini output price)Official

Change log: 24 Oct 2026, Rewritten as one continuous guide: added the renamed vLLM reasoning field, why the failure looks random, and the April 2026 GPT-5.4 report of "none" being ignored with a cap; corrected our own case to a test-harness probe; takeaways, steps, checklist and FAQs folded into the body

Questions about your calling setup?

Tell us what you call about, where and in which languages.