> This page is for version dev.
> For other versions, use one of these documentation indexes:
> - Latest (v1.6.1) (default): https://docs.nvidia.com/dynamo/latest/llms.txt
> - dev: https://docs.nvidia.com/dynamo/dev/llms.txt
> - v1.6.1: https://docs.nvidia.com/dynamo/v1.6.1/llms.txt
> - v1.6.0: https://docs.nvidia.com/dynamo/v1.6.0/llms.txt
> - v1.5.1: https://docs.nvidia.com/dynamo/v1.5.1/llms.txt
> - v1.5.0: https://docs.nvidia.com/dynamo/v1.5.0/llms.txt
> - v1.4.2: https://docs.nvidia.com/dynamo/v1.4.2/llms.txt
> - v1.4.1: https://docs.nvidia.com/dynamo/v1.4.1/llms.txt
> - v1.4.0: https://docs.nvidia.com/dynamo/v1.4.0/llms.txt
> - v1.3.0: https://docs.nvidia.com/dynamo/v1.3.0/llms.txt
> - v1.2.1: https://docs.nvidia.com/dynamo/v1.2.1/llms.txt
> - v1.2.0: https://docs.nvidia.com/dynamo/v1.2.0/llms.txt
> - v1.1.1: https://docs.nvidia.com/dynamo/v1.1.1/llms.txt
> - v1.1.0: https://docs.nvidia.com/dynamo/v1.1.0/llms.txt
> - v1.0.2: https://docs.nvidia.com/dynamo/v1.0.2/llms.txt
> - v1.0.1: https://docs.nvidia.com/dynamo/v1.0.1/llms.txt
> - v1.0.0: https://docs.nvidia.com/dynamo/v1.0.0/llms.txt
> - v0.9.1: https://docs.nvidia.com/dynamo/v-0-9-1/llms.txt
> - v0.9.0: https://docs.nvidia.com/dynamo/v-0-9-0/llms.txt
> - v0.8.1: https://docs.nvidia.com/dynamo/v-0-8-1/llms.txt
> - v0.8.0: https://docs.nvidia.com/dynamo/v-0-8-0/llms.txt
> - v0.7.1: https://docs.nvidia.com/dynamo/v-0-7-1/llms.txt
> - v0.7.0: https://docs.nvidia.com/dynamo/v-0-7-0/llms.txt

> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.nvidia.com/dynamo/llms.txt. For full content including API reference and SDK examples, see https://docs.nvidia.com/dynamo/llms-full.txt.

# Reasoning Parsing (Dynamo)

Some models emit reasoning separately from their final response. Dynamo can split that output into `reasoning_content` and normal assistant `content` by configuring `--dyn-reasoning-parser` on the backend worker. This page covers Dynamo-native parsing; if your model is not listed, use [engine fallback](/dynamo/dev/knowledge-base/modular-components/frontend/tool-calling/chat-processors), which also explains valid combinations of `--dyn-reasoning-parser`, `--dyn-chat-processor`, and `--dyn-tool-call-parser`.

See [Parser Generation Routing](/dynamo/dev/knowledge-base/modular-components/frontend/tool-calling/troubleshooting-tool-calls#parser-generation-routing) for version selection and compatible names.

## Configure Reasoning Parsing

Set `DYN_PARSER_VERSION` in the frontend and backend worker environments before startup: `1` selects legacy V1 parsing, `2` requires a compatible unified V2 parser, and unset or `auto` prefers compatible V2 with V1 fallback. See [Parser Generation Routing](/dynamo/dev/knowledge-base/modular-components/frontend/tool-calling/troubleshooting-tool-calls#parser-generation-routing) for supported configurations and family exceptions.

#### Launch Dynamo backend

Select `--dyn-reasoning-parser` from the supported list below. The backend can be SGLang, TensorRT-LLM, vLLM, or another installed backend.

For vLLM structured output or SGLang required/named tool choice, also configure the engine's native `--reasoning-parser`. The native parser controls when the grammar starts; Dynamo's parser populates `reasoning_content`. Parser names can differ between registries.

To inspect the available worker flags, run:

```bash
python -m dynamo.<backend> --help
```

The following example starts an SGLang worker for Qwen3.5:

```bash
python -m dynamo.sglang \
  --model Qwen/Qwen3.5-4B \
  --dyn-tool-call-parser qwen3_coder \
  --reasoning-parser qwen3 \
  --dyn-reasoning-parser qwen3
```

<details>
  <summary>
    Some models need both parsers configured together. Common pairings include:
  </summary>

  * `openai/gpt-oss-*`: `--dyn-tool-call-parser harmony --dyn-reasoning-parser gpt_oss`
  * `deepseek-ai/DeepSeek-V4-*`: `--dyn-tool-call-parser deepseek_v4 --dyn-reasoning-parser deepseek_v4`
  * `zai-org/GLM-4.7`: `--dyn-tool-call-parser glm47 --dyn-reasoning-parser glm45`
  * `moonshotai/Kimi-K2.5*` / Kimi K2.6 format-compatible outputs: `--dyn-tool-call-parser kimi_k2 --dyn-reasoning-parser kimi_k25`
  * `google/gemma-4-*` thinking models: `--dyn-tool-call-parser gemma4 --dyn-reasoning-parser gemma4 --custom-jinja-template examples/chat_templates/gemma4_tool.jinja`
  * `Qwen/Qwen3.5*`: `--dyn-tool-call-parser qwen3_coder --dyn-reasoning-parser qwen3`
  * Beam channel-grammar models: `--dyn-tool-call-parser beam --dyn-reasoning-parser beam`
  * MiniMax M2 style outputs: `--dyn-tool-call-parser minimax_m2 --dyn-reasoning-parser minimax_m2`
  * MiniMax M3 style outputs: `--dyn-tool-call-parser minimax_m3 --dyn-reasoning-parser minimax_m3`

  > **Warning**
  >
  > `minimax_append_think` is deprecated for MiniMax M2 tool-calling deployments. Use `--dyn-reasoning-parser minimax_m2` with `--dyn-tool-call-parser minimax_m2` so Dynamo can separate reasoning and pass MiniMax XML tool calls to the tool parser.
</details>

On Unified routes one parser preserves reasoning, text, and tool order. The legacy split route extracts reasoning before tool parsing. See [Tool Call Parsing (Dynamo)](/dynamo/dev/knowledge-base/modular-components/frontend/tool-calling/tool-call-parsing) for supported `--dyn-tool-call-parser` values.

#### Start the Frontend

Start the Dynamo frontend in another terminal:

```bash
python -m dynamo.frontend
```

#### Wait for Readiness

Wait for the frontend health endpoint to return a successful response:

```bash
curl --fail http://localhost:8000/health
```

#### Send a Reasoning Request

Send an OpenAI-compatible chat completion request:

```bash
curl -s http://localhost:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "Qwen/Qwen3.5-4B",
    "messages": [
      {
        "role": "user",
        "content": "If a train leaves at 3pm going 60 mph and another leaves at 4pm going 80 mph, when does the second catch up?"
      }
    ]
  }'
```

Dynamo places the chain of thought in `reasoning_content` and the user-facing answer in `content`.

#### View an example response

```json
{
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "reasoning_content": "The first train has a 1-hour head start at 60 mph, so it is 60 miles ahead at 4pm. The second train closes the gap at 80 - 60 = 20 mph. 60 / 20 = 3 hours after 4pm.",
        "content": "The second train catches up at 7pm."
      },
      "finish_reason": "stop"
    }
  ]
}
```

## Deployment-Level Thinking Default

Set `--dyn-default-thinking-mode` on a backend worker to choose the thinking
mode used when a request does not provide one. The worker publishes the value
through model runtime metadata, and the frontend applies it while rendering the
chat template. The option works with vLLM, SGLang, and TensorRT-LLM workers.

| CLI argument                  | Environment variable        | Values                | Default |
| ----------------------------- | --------------------------- | --------------------- | ------- |
| `--dyn-default-thinking-mode` | `DYN_DEFAULT_THINKING_MODE` | `enabled`, `disabled` | Unset   |

For example, make thinking disabled by default for a Qwen3 deployment:

```bash
python -m dynamo.vllm \
  --model Qwen/Qwen3-0.6B \
  --dyn-default-thinking-mode disabled
```

You can configure the same value through the environment:

```bash
DYN_DEFAULT_THINKING_MODE=disabled \
  python -m dynamo.vllm --model Qwen/Qwen3-0.6B
```

Use the same setting on every worker that serves the model. When the option is
unset, Dynamo preserves the model or chat template's native default.

The frontend's `--default-chat-template-kwargs` can also set a thinking default,
for example `'{"enable_thinking": false}'`. It applies to every model that the
frontend serves, including models behind a sidecar. On `/v1/messages` with a
reasoning parser, the Anthropic `thinking` parameter decides instead, because
that endpoint turns thinking on unless the request disables it.

Thinking controls use this precedence order:

1. An explicit request control
2. Thinking keys in the frontend's `--default-chat-template-kwargs`
3. `--dyn-default-thinking-mode` or `DYN_DEFAULT_THINKING_MODE`
4. The model or chat template's native default

Kimi K3 overrides this precedence for named calls: `--dyn-tool-call-parser kimi_k3` (or `kimi-k3`) forces thinking off, even if requested. The reasoning selector alone does not apply this override.

Explicit request controls include root-level `thinking`, top-level
`reasoning_effort`, and the `thinking`, `enable_thinking`, `thinking_mode`, or
`reasoning_effort` fields in `chat_template_args` or
`chat_template_kwargs`. When the frontend sets `--default-chat-template-kwargs`,
a request value of `null` or `"auto"` counts as unset.

The deployment option intentionally accepts only `enabled` and `disabled`.
Models that support adaptive thinking can still select it per request:

```json
{
  "model": "MiniMaxAI/MiniMax-M3",
  "messages": [{"role": "user", "content": "Explain this result."}],
  "thinking": {"type": "adaptive"}
}
```

Dynamo normalizes this request to `thinking_mode=adaptive` and removes any
`thinking` or `enable_thinking` key, so the decision stays with the model. A
`reasoning_effort` value still reaches models that grade on it, but under
`adaptive` it does not turn reasoning on or off. Because adaptive is an
explicit request control, it takes precedence over an `enabled` or `disabled`
deployment default.

> **Note**
>
> This option controls chat-template rendering. It does not force the inference
> engine or model to follow the requested mode. Models that ignore their
> template's thinking control may still emit reasoning.

## Supported Reasoning Parsers

Choose a model family, then expand the matching model option to see its parser name and configuration details.

The **Upstream name** column lists engine names that differ from Dynamo's, for engine fallback and native reasoning gates. Names vary by engine version; `Dynamo-only` describes this catalog, not every engine release.

Parsers marked **Force-reasoning: Yes** start reasoning without an opening tag. Other parsers can start from a generated opener or supported prompt-prefilled state. Prompt prefill and force-reasoning are separate mechanisms.

#### Kimi

#### Kimi K3

**Parser:** `kimi_k3` (Unified alias `kimi-k3`)

**Notes:** XTML thinking and response channels, including prompt-prefilled reasoning. See [Tool Call Parsing](/dynamo/dev/knowledge-base/modular-components/frontend/tool-calling/tool-call-parsing) for the K3 named-tool thinking override.

#### Kimi K2.5 / Kimi K2.6 format-compatible thinking models

**Parser:** `kimi_k25`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

Yes (V1)

**Notes:** V1 forces reasoning from the start. The default Unified Kimi K2 route begins as visible text unless an opening marker or supported prompt-prefilled reasoning state selects reasoning.

#### Kimi K2 Instruct / Thinking with Unicode delimiters

**Parser:** `kimi`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

No

**Notes:** `◁think▷...◁/think▷`

> **Warning**
>
> Kimi K2.7 may ignore `chat_template_kwargs.thinking=false` and continue to generate reasoning. Dynamo can separate emitted reasoning when a compatible parser is configured, but it cannot force the model to disable reasoning. Treat the request flag as best-effort for Kimi K2.7.

#### MiniMax

#### MiniMax M2 / M2.5 / M2.7

**Parser:** `minimax_m2`

**Upstream name:** vLLM: `minimax_m2`

**Force-reasoning:**

Yes

**Notes:** `<think>...</think>` with force-reasoning

#### MiniMax M3

**Parser:** `minimax_m3`

**Upstream name:** vLLM: `minimax_m3`

**Force-reasoning:**

No

**Notes:** `<mm:think>...</mm:think>`. Auto uses Unified for compatible M3 selectors; `1` selects legacy parsing. Both routes support prompt-prefilled reasoning. See [guided-decoding configuration](/dynamo/dev/knowledge-base/modular-components/frontend/tool-calling/troubleshooting-tool-calls#parser-generation-routing) for the required Dynamo and engine reasoning parsers. Alias: `minimax-m3`

#### MiniMax M2 / M2.1 (legacy)

**Parser:** `minimax_append_think`

Deprecated

**Upstream name:**

Dynamo-only

**Force-reasoning:**

No

**Notes:** Legacy pass-through with an implicit `<think>` opener. Use `minimax_m2` for MiniMax M2 tool-calling deployments.

#### DeepSeek

#### DeepSeek V4.1

**Parser:** `deepseek_v41`

**Notes:** Unified V4.1 reasoning and tool grammar; use V2/auto with matching selectors. Not available in V1.

#### DeepSeek V4 Pro / Flash

**Parser:** `deepseek_v4`

**Upstream name:** vLLM: `deepseek_v4`; SGLang: `deepseek-v4`

**Force-reasoning:**

No

**Notes:** `<think>...</think>`. Aliases: `deepseek-v4`, `deepseekv4`

#### DeepSeek R1, DeepSeek V3.1, and DeepSeek V3.2

**Parser:** `deepseek_r1`

**Upstream name:** Same name across Dynamo, vLLM, and SGLang

**Force-reasoning:**

Yes

**Notes:** V1 also accepts `deepseek_v3`, `deepseek_v3_1`, and `deepseek_v3_2` as reasoning aliases. These names do not identify a Unified family.

#### Qwen and QwQ

#### Qwen3.5, QwQ-32B, Qwen3-Think, and Qwen3-Coder

**Parser:** `qwen3`

**Upstream name:** Same name across Dynamo, vLLM, and SGLang

**Force-reasoning:**

No

**Notes:** `<think>...</think>`

#### GLM

#### GLM-4.5 and GLM-4.7

**Parser:** `glm45`

**Upstream name:** vLLM: `glm45`; SGLang: `glm45`

**Force-reasoning:**

No

**Notes:** `<think>...</think>`. With the default V2 parser, `glm45` selects
the `glm47` unified family; `glm47` is also accepted as a Dynamo selector.
With `DYN_PARSER_VERSION=1`, `glm45` uses the legacy `nemotron_deci`
implementation.

GLM does not assume reasoning by default. If the chat template already
ends the generation prompt with `<think>`, Dynamo starts parsing inside
reasoning without requiring the model to repeat the opening tag.

Thinking controls such as `chat_template_kwargs: {"enable_thinking": false}`
or `chat_template_kwargs: {"thinking": false}` affect the model's chat
template, not response visibility. If a GLM model still generates
reasoning, Dynamo keeps it in `reasoning_content` and returns the answer
in `content`.

For the default V2 parser on SGLang or vLLM, configure Dynamo's
`--dyn-reasoning-parser glm45` (or `glm47`) and the engine's native
`--reasoning-parser glm45`. Dynamo reconciles its reasoning state with
the rendered generation prompt, even if the request supplied a false
thinking flag:

* An open `<think>` defers JSON answer constraints and required/named-tool
  constraints until `</think>`.
* A closed reasoning block starts in the answer phase, so those
  constraints apply from the first generated token.
* With no generation prompt or no recognized open/closed reasoning
  suffix, Dynamo retains the request-based decision.

A `max_thinking_tokens` budget also enables the reasoning gate when the
rendered prompt leaves reasoning open, even without JSON or
required/named-tool constraints. The budget caps reasoning tokens;
JSON and tool constraints still apply in the answer phase. Plain chat
without constraints or a thinking budget does not request this gate.

TensorRT-LLM also supports Dynamo's reasoning/content separation. The
native grammar-gate behavior described here is specific to SGLang and
vLLM; it does not configure TensorRT-LLM guided decoding.

#### Nemotron

#### Nemotron-3 / Mini

**Parser:** `nemotron3`

**Upstream name:** vLLM: `nemotron_v3`

**Force-reasoning:**

Yes

**Notes:** Auto pairs `qwen3_coder` tools with `nemotron_v3` / `nemotron3` reasoning on Unified; reasoning-only auto stays on V1. Explicit V2 selects Unified. V1 forces think-tag reasoning with tool boundaries.

#### Nemotron-Super / -Ultra / -Deci and Llama-Nemotron

**Parser:** `nemotron_deci`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

No

**Notes:** `<think>...</think>`

#### Nemotron-Nano

**Parser:** `nemotron_nano`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

Yes

**Notes:** Alias for `deepseek_r1`

#### Gemma

#### Google Gemma 4 thinking models

**Parser:** `gemma4`

**Upstream name:** vLLM: `gemma4`

**Force-reasoning:**

No

**Notes:** `<\|channel>thought\n...<channel\|>` with `thought\n` role label stripped. Aliases: `gemma-4`

#### Beam

#### Beam channel-grammar models

**Parser:** `beam`

**Upstream name:** none (Dynamo-native unified family)

**Force-reasoning:**

No

**Notes:** `<\|channel\|>analysis<\|message\|>...<\|end\|>` is reasoning; the final channel is the answer. Pair with `--dyn-tool-call-parser beam` (both flags required). Supplied prior reasoning is always rendered back into the history (`preserve_thinking: true` and omitted are the same; `false` is accepted and has no effect); history turns without reasoning render an empty analysis block (`allow_missing_thinking` defaults to true on this route).

#### gpt-oss

#### gpt-oss-20b and gpt-oss-120b

**Parser:** `gpt_oss`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

No

**Notes:** Harmony channel reasoning format

#### Mistral

#### Magistral

**Parser:** `mistral`

**Upstream name:** Same name across Dynamo, vLLM, and SGLang

**Force-reasoning:**

Yes

**Notes:** `[THINK]...[/THINK]`

#### Granite

#### IBM Granite 3.x / Granite 3.2 language models

**Parser:** `granite`

**Upstream name:** Same name across Dynamo, vLLM, and SGLang

**Force-reasoning:**

No

**Notes:** `Here's my thought process:` / `Here's my response:`

#### Step

#### Step-3 / Step-3-Reasoning

**Parser:** `step3`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

Yes

**Notes:** `<think>...</think>`

#### Muse Glimmer

**Parser:** `muse_glimmer` (Dynamo alias `muse`)

**Notes:** Unified recipient-routed channels; `to=self` carries reasoning. No V1 reasoning parser exists.

#### Muse Spark

**Parser:** `muse_spark` (alias `muse_spark_open`)

**Notes:** Unified recipient-routed channels: `to=self` carries reasoning and `commentary` remains visible text. No V1 reasoning parser exists.

#### Inkling

**Parser:** `inkling`

**Notes:** V1 block/channel reasoning parser. This name does not select a Unified family; auto uses the legacy route and explicit V2 rejects it.

#### Generic

#### Generic chain-of-thought models

**Parser:** `basic`

**Upstream name:**

Dynamo-only

**Force-reasoning:**

No

**Notes:** Plain `<think>...</think>`