> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mixlayer.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mixlayer.com/_mcp/server.

# Reasoning

> Enable extended chain-of-thought reasoning and read the model's thinking

Some Mixlayer models support an extended **thinking mode** where the model produces reasoning before its visible answer. Chat Completions returns this in a separate `reasoning_content` field on the assistant message. The Responses API returns reasoning as separate output items and streams it through `response.reasoning_text.delta` events.

## Enabling thinking

Use `reasoning_effort` with Chat Completions:

```json
{ "reasoning_effort": "high" }
```

Use `reasoning.effort` with the Responses API:

```json
{ "reasoning": { "effort": "high" } }
```

Both APIs recognize `default`, `none`, `minimal`, `low`, `medium`, `high`, `xhigh`, and `max`. Mixlayer maps these standardized values to each model's reasoning capabilities and rejects values the model cannot support. An accepted value does not necessarily represent a distinct native effort level or a fixed token budget.

Omit the effort or send `"default"` to use the model's default.

### Model mappings

For the models in the [model catalog](/models):

| Requested effort     | Qwen 3.5/3.6 | GLM 5.2       | [GLM 5.3](/glm-5-3) | Kimi K2.7 Code | [DeepSeek V4.1 Flash](/deepseek-v4-1-flash) |
| -------------------- | ------------ | ------------- | ------------------- | -------------- | ------------------------------------------- |
| Omitted or `default` | Thinking on  | Native `Max`  | Native `Max`        | Thinking on    | Native `High` (75)                          |
| `none`               | Thinking off | Thinking off  | Rejected            | Rejected       | Thinking off                                |
| `minimal`            | Thinking on  | Native `High` | Native `Low`        | Thinking on    | Native `Low` (50)                           |
| `low`                | Thinking on  | Native `High` | Native `Low`        | Thinking on    | Native `Low` (50)                           |
| `medium`             | Thinking on  | Native `High` | Native `High`       | Thinking on    | Native `High` (75)                          |
| `high`               | Thinking on  | Native `High` | Native `High`       | Thinking on    | Native `High` (75)                          |
| `xhigh`              | Thinking on  | Native `Max`  | Native `Max`        | Thinking on    | Native `High` (75)                          |
| `max`                | Thinking on  | Native `Max`  | Native `Max`        | Thinking on    | Native `Max` (100)                          |

Native effort levels all enable thinking. Qwen 3.5/3.6 and Kimi K2.7 Code map every non-`none` effort to their default thinking behavior. GLM 5.3 and Kimi K2.7 Code always reason and reject `none`. Budget enough output tokens for both reasoning and the final answer.

DeepSeek V4.1 Flash also accepts an integer from 1 to 100 directly through `reasoning_effort` in Chat Completions or `reasoning.effort` in Responses. Numeric values are passed through to the model's native effort scale, not interpreted as token budgets. See [DeepSeek V4.1 Flash](/deepseek-v4-1-flash#reasoning-behavior) for examples.

### Legacy boolean controls

Chat Completions still accepts `thinking` (or its boolean alias `reasoning`). When `reasoning_effort` is omitted or `default`, `true` maps to `medium` and `false` maps to `none`. An explicit non-default effort takes precedence over either boolean. These values then follow the model mappings above, so `thinking: false` is rejected by GLM 5.3 and Kimi K2.7 Code. Prefer the effort field for new integrations.

## Reading reasoning\_content

A non-streaming response with thinking enabled includes both fields on the assistant message:

```json
{
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "reasoning_content": "Let me work through this. The user is asking about...",
      "content": "The answer is 42."
    },
    "finish_reason": "stop"
  }]
}
```

`content` is the visible answer you'd typically show to the user. `reasoning_content` is the model's chain of thought — useful for debugging, evaluation, or building "show your work" UI.

> **Info**
>
> Mixlayer extracts reasoning from `<think>...</think>` tags in the model's
> raw output and routes it to `reasoning_content` automatically. You will
> never see the tags in either field.

## Examples

#### curl

**`file=`**

```bash file=reasoning.sh
curl https://mixlayer.ai/v1/chat/completions \
  -H "Authorization: Bearer $MIXLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen/qwen3.6-27b",
    "reasoning_effort": "high",
    "messages": [
      {"role": "user", "content": "If a train leaves at 3pm going 60mph and another leaves at 4pm going 80mph, when do they meet?"}
    ]
  }'
```

#### Python

**`file=`**

```python file=reasoning.py
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["MIXLAYER_API_KEY"],
    base_url="https://mixlayer.ai/v1",
)

response = client.chat.completions.create(
    model="qwen/qwen3.6-27b",
    messages=[{"role": "user", "content": "What is 17 * 23?"}],
    reasoning_effort="high",
)

message = response.choices[0].message
# `reasoning_content` is a Mixlayer extension; access via model_extra.
reasoning = getattr(message, "reasoning_content", None) or message.model_extra.get("reasoning_content")
print("Reasoning:", reasoning)
print("Answer:   ", message.content)
```

#### TypeScript

**`file=`**

```typescript file=reasoning.ts
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env["MIXLAYER_API_KEY"]!,
  baseURL: "https://mixlayer.ai/v1",
});

const response = await openai.chat.completions.create({
  model: "qwen/qwen3.6-27b",
  messages: [{ role: "user", content: "What is 17 * 23?" }],
  reasoning_effort: "high",
});

const message = response.choices[0].message as typeof response.choices[0].message & {
  reasoning_content?: string;
};
console.log("Reasoning:", message.reasoning_content);
console.log("Answer:   ", message.content);
```

#### Rust

**`file=`**

```rust file=src/main.rs
// Use reqwest to read the Mixlayer-specific `reasoning_content` field directly.
use reqwest::Client;
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let api_key = std::env::var("MIXLAYER_API_KEY")?;

    let body = json!({
        "model": "qwen/qwen3.6-27b",
        "reasoning_effort": "high",
        "messages": [{"role": "user", "content": "What is 17 * 23?"}]
    });

    let response: Value = Client::new()
        .post("https://mixlayer.ai/v1/chat/completions")
        .bearer_auth(api_key)
        .json(&body)
        .send()
        .await?
        .json()
        .await?;

    let message = &response["choices"][0]["message"];
    println!("Reasoning: {}", message["reasoning_content"]);
    println!("Answer:    {}", message["content"]);
    Ok(())
}
```

## Streaming reasoning

When `stream: true`, reasoning arrives in `delta.reasoning_content` chunks alongside `delta.content` chunks. They interleave in the order the model produces them — typically reasoning first, then visible content.

```
data: {"choices":[{"delta":{"role":"assistant"}}]}
data: {"choices":[{"delta":{"reasoning_content":"Let me think. "}}]}
data: {"choices":[{"delta":{"reasoning_content":"17 * 23 = 17 * 20 + 17 * 3 = 340 + 51."}}]}
data: {"choices":[{"delta":{"content":"17 * 23 = 391."},"finish_reason":"stop"}]}
```

To render reasoning and content in separate UI areas, route each delta based on which field is set:

```python
for chunk in stream:
    delta = chunk.choices[0].delta
    extra = delta.model_extra or {}
    if extra.get("reasoning_content"):
        update_reasoning_pane(extra["reasoning_content"])
    if delta.content:
        update_answer_pane(delta.content)
```

## Structured output

Set `response_format` alongside `reasoning_effort` in [Chat Completions](/chat-completions), or `text.format` alongside `reasoning.effort` in the [Responses API](/responses).

```bash
curl https://mixlayer.ai/v1/chat/completions \
  -H "Authorization: Bearer $MIXLAYER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen/qwen3.6-27b",
    "reasoning_effort": "high",
    "messages": [{"role": "user", "content": "What is 17 * 23?"}],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "answer",
        "schema": {
          "type": "object",
          "properties": {"answer": {"type": "integer"}},
          "required": ["answer"],
          "additionalProperties": false
        },
        "strict": true
      }
    }
  }'
```