Skip to content

Qwen3's enable_thinking Parameter

9 min read · updated August 11, 2026

enable_thinking is not a model parameter. It is an argument to the chat template, and what it changes is a handful of tokens at the start of the assistant turn. Knowing that explains every strange thing it does — including why passing it to some servers has no effect at all.

What the flag actually does

Qwen3 is a hybrid model: one set of weights trained to answer either directly or after an explicit reasoning pass. The switch between those two behaviours is made in the prompt, and the chat template shipped with every Qwen3 repository is what writes it.

With enable_thinking=True, which is the template default, the assistant turn is opened and left for the model to fill. The model begins by emitting a <think> block, reasons inside it, closes it, and then writes the answer. With enable_thinking=False, the template pre-fills an empty thinking block into the assistant prefix — a <think> immediately followed by </think> — so the model resumes generation at a point where the reasoning is, as far as it can tell, already over and empty. It writes the answer directly.

That is the whole mechanism. It is a prefill trick, and it is why the flag belongs to tokenizer.apply_chat_template rather than to model.generate. There is no logits mask, no separate model, and no server-side mode.

Several otherwise confusing behaviours fall out of that immediately. Passing enable_thinking to a server that applies the template itself, without routing it through the template arguments, does nothing at all and reports no error — the parameter is simply not where the template can see it. Building your prompt string by hand and then setting the flag also does nothing, because your string is what the model receives. And prefilling the empty block yourself, without the flag, works perfectly: the flag is a convenience for writing four tokens you could write.

The same request, twice

from transformers import AutoTokenizer

tok = AutoTokenizer.from_pretrained("Qwen/Qwen3-8B")
messages = [{"role": "user", "content": "How many r in strawberry?"}]

on  = tok.apply_chat_template(messages, tokenize=False,
                              add_generation_prompt=True,
                              enable_thinking=True)
off = tok.apply_chat_template(messages, tokenize=False,
                              add_generation_prompt=True,
                              enable_thinking=False)

The two strings are identical until the final assistant header. What differs is what follows it:

# enable_thinking=True — the turn is left open
<|im_start|>assistant


# enable_thinking=False — an empty reasoning block is prefilled
<|im_start|>assistant
<think>

</think>

And so the generated text differs in shape, not only in length:

# thinking on
<think>
Let me spell it: s-t-r-a-w-b-e-r-r-y. Positions 3, 8, 9 ...
</think>

There are three.

# thinking off
There are three.

Which means your parser has to change with the flag. With thinking on, the user-facing answer is everything after </think>, and code that renders the raw completion will show the reasoning to the user. Parsing the think tags covers the edge cases, of which the important one is a generation that hits its token ceiling before the closing tag ever arrives — leaving you with an unterminated reasoning block and no answer at all.

Where to pass it

The flag reaches the template differently in each stack, and passing it in the wrong place is silently ignored rather than rejected:

  • transformers — a keyword argument to apply_chat_template, as above.
  • vLLM and SGLang, OpenAI-compatible endpoint — inside chat_template_kwargs on the request body, because the template is applied server-side:
    {
      "model": "Qwen/Qwen3-8B",
      "messages": [{"role": "user", "content": "How many r in strawberry?"}],
      "chat_template_kwargs": {"enable_thinking": false}
    }
  • Alibaba Cloud Model Studio — a top-level enable_thinking field on the request, with the reasoning returned in a separate reasoning_content field rather than inline in content. That separation is a service behaviour, not a model one: the same weights served elsewhere put the tags in the content stream.
Default behaviour differs between the original Qwen3 checkpoints and the later single-mode releases. Some subsequent Qwen3 checkpoints ship as thinking-only or instruct-only models, where the flag is not meaningful and setting it does nothing. Check the card of the specific repository at github.com/QwenLM/Qwen3 rather than assuming the hybrid behaviour from the family name.

The soft switch in the prompt

Qwen3 also honours /think and /no_think as directives in a user or system message, which the template detects. This exists for multi-turn conversations where the mode should change partway through without rebuilding the whole prompt — the last directive in the conversation wins.

It is a weaker guarantee than the template flag, because it depends on the model attending to a marker rather than on the prefix being structurally closed. For anything programmatic, prefer the flag; use the directives when the person typing is the one choosing.

Multi-turn conversations raise a question the flag does not answer: what to do with the reasoning from previous turns when you send the history back. The Qwen3 guidance is to keep the final answer and drop the thinking block from prior assistant turns, and the template is written to expect that. Feeding old reasoning back in costs context for no benefit and, on long conversations, biases the model toward restating conclusions it reached earlier rather than reconsidering them. Strip everything up to and including the last </think> before appending an assistant turn to your history.

Watch what the flag does to your latency profile as well as your content. With thinking on, time to the first useful token is not time to first token: the stream begins immediately, but everything in it is reasoning until the closing tag. An interface that renders the stream directly will show the user a wall of working-out; one that waits for </think> shows nothing for several seconds. The usual answer is a third thing — render the reasoning in a collapsed region, so the user sees progress without seeing the draft as though it were the answer.

Sampling settings change with it

The Qwen3 model cards publish different recommended sampling parameters for the two modes, and this is not cosmetic. Thinking mode generates a long chain in which a single bad token can derail the whole reasoning pass, and the cards recommend against greedy decoding for it specifically — the documented failure is degenerate repetition, where the model loops the same reasoning step until it hits the token ceiling.

The two recommended settings, as published on the Qwen3 cards:

thinking on   temperature 0.6   top_p 0.95   top_k 20
thinking off  temperature 0.7   top_p 0.80   top_k 20

Budget for the token cost too. Thinking output is billed and counted like any other output, and the cards suggest allowing tens of thousands of tokens for hard problems in thinking mode. A ceiling tuned for direct answers will truncate a reasoning pass mid-thought, which is worse than not thinking at all: you pay for the reasoning and receive none of the answer. See the Qwen output ceilings for where those limits come from.