> ## Documentation Index
> Fetch the complete documentation index at: https://docs.naga.ac/llms.txt
> Use this file to discover all available pages before exploring further.

# Reasoning

> Set how long a model thinks before it answers, read its reasoning and keep it across turns.

Reasoning models work through a problem before they answer. You choose how much effort they spend, read the reasoning next to the answer, and pay for its tokens at the output price.

> [tab] Responses
>
> ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> import os
> from openai import OpenAI
>
> client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])
>
> response = client.responses.create(
>     model="deepseek-v4.1-flash",
>     input="A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?",
>     reasoning={"effort": "high", "summary": "auto"},
> )
>
> for item in response.output:
>     if item.type == "reasoning":
>         for part in item.summary:
>             print("Reasoning:", part.text)
> print("Answer:", response.output_text)
> print("Reasoning tokens:", response.usage.output_tokens_details.reasoning_tokens)
> ```
>
> ```javascript Node.js theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> import OpenAI from "openai";
>
> const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });
>
> const response = await client.responses.create({
>   model: "deepseek-v4.1-flash",
>   input: "A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?",
>   reasoning: { effort: "high", summary: "auto" },
> });
>
> for (const item of response.output) {
>   if (item.type === "reasoning") item.summary.forEach((part) => console.log("Reasoning:", part.text));
> }
> console.log("Answer:", response.output_text);
> console.log("Reasoning tokens:", response.usage.output_tokens_details.reasoning_tokens);
> ```

> [tab] Chat Completions
>
> ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> import os
> from openai import OpenAI
>
> client = OpenAI(base_url="https://api.naga.ac/v1", api_key=os.environ["NAGA_API_KEY"])
>
> completion = client.chat.completions.create(
>     model="deepseek-v4.1-flash",
>     messages=[{"role": "user", "content": "A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?"}],
>     reasoning_effort="high",
> )
>
> message = completion.choices[0].message
> print("Reasoning:", getattr(message, "reasoning_content", None))
> print("Answer:", message.content)
> print("Reasoning tokens:", completion.usage.completion_tokens_details.reasoning_tokens)
> ```
>
> ```javascript Node.js theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> import OpenAI from "openai";
>
> const client = new OpenAI({ baseURL: "https://api.naga.ac/v1", apiKey: process.env.NAGA_API_KEY });
>
> const completion = await client.chat.completions.create({
>   model: "deepseek-v4.1-flash",
>   messages: [{ role: "user", content: "A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?" }],
>   reasoning_effort: "high",
> });
>
> const message = completion.choices[0].message;
> console.log("Reasoning:", message.reasoning_content);
> console.log("Answer:", message.content);
> console.log("Reasoning tokens:", completion.usage.completion_tokens_details?.reasoning_tokens);
> ```
>
> ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> curl https://api.naga.ac/v1/chat/completions \
>   -H "Authorization: Bearer $NAGA_API_KEY" \
>   -H "Content-Type: application/json" \
>   -d '{
>     "model": "deepseek-v4.1-flash",
>     "messages": [{"role": "user", "content": "A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?"}],
>     "reasoning_effort": "high"
>   }'
> ```

> [tab] Messages
>
> ```python Python theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> import os
> from anthropic import Anthropic
>
> client = Anthropic(base_url="https://api.naga.ac", api_key=os.environ["NAGA_API_KEY"])
>
> message = client.messages.create(
>     model="deepseek-v4.1-flash",
>     max_tokens=4096,
>     thinking={"type": "enabled", "budget_tokens": 2048},
>     messages=[{"role": "user", "content": "A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?"}],
> )
>
> for block in message.content:
>     if block.type == "thinking":
>         print("Thinking:", block.thinking)
>     elif block.type == "text":
>         print("Answer:", block.text)
> ```
>
> ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
> import Anthropic from "@anthropic-ai/sdk";
>
> const client = new Anthropic({ baseURL: "https://api.naga.ac", apiKey: process.env.NAGA_API_KEY });
>
> const message = await client.messages.create({
>   model: "deepseek-v4.1-flash",
>   max_tokens: 4096,
>   thinking: { type: "enabled", budget_tokens: 2048 },
>   messages: [{ role: "user", content: "A bat and a ball cost 1.10 in total. The bat costs 1.00 more than the ball. What does the ball cost?" }],
> });
>
> for (const block of message.content) {
>   if (block.type === "thinking") console.log("Thinking:", block.thinking);
>   if (block.type === "text") console.log("Answer:", block.text);
> }
> ```

The example prints the reasoning, the answer and, for Responses and Chat Completions, the number of reasoning tokens.

## Effort levels

Responses and Chat Completions share one scale: `none`, `minimal`, `low`, `medium`, `high`, `xhigh` and `max`. You set it with `reasoning.effort` in Responses and `reasoning_effort` in Chat Completions. Models don't all support every level, so NagaAI sends the nearest level the model has. You can keep one setting in your code and switch models freely.

Messages takes `output_config.effort` from `low` to `max`, or the older `thinking` object with a token budget. NagaAI turns the budget into one of its effort levels and translates that level for the provider serving the model:

| `thinking.budget_tokens` | Effort |
| - | - |
| Under 1024 | `400` error |
| 1024 to 8191 | `low` |
| 8192 to 32767 | `medium` |
| 32768 to 65535 | `high` |
| 65536 or more | `xhigh` |

`thinking: {"type": "adaptive"}` sets no level and leaves the choice to the model. When you send both `thinking` and `output_config.effort`, the effort wins. The budget doesn't cap the thinking exactly.

A model without reasoning lacks `reasoning_effort` in the `parameters` of its `chat` operation in [`/v1/models`](https://docs.naga.ac/get-started/models). NagaAI removes the setting from requests to such a model, so the request still succeeds.

## Reasoning in the response

| | Responses | Chat Completions | Messages |
| - | - | - | - |
| Reasoning | Output item of type `reasoning` | `reasoning_content` and `reasoning_details` on the assistant message | `thinking` and `redacted_thinking` blocks |
| Reasoning tokens | `usage.output_tokens_details.reasoning_tokens` | `usage.completion_tokens_details.reasoning_tokens` | Part of `usage.output_tokens` |

In Responses, `reasoning.summary` in the request asks for a summary of the reasoning: `auto`, `concise` or `detailed`. A `reasoning` item holds `summary`, a list of `summary_text` parts, and `content` with the full reasoning as `reasoning_text` parts when the model returns it. A model that seals its reasoning returns `encrypted_content` instead. NagaAI always includes it, so you don't need `include: ["reasoning.encrypted_content"]`. In a stream the reasoning arrives as `response.reasoning_summary_text.delta` and `response.reasoning_text.delta` events.

The official Chat Completions API has no reasoning fields, so NagaAI adds two to the message and to stream deltas. `reasoning_content` is the reasoning as plain text, often a summary. `reasoning_details` lists typed entries: `reasoning.text` with the full text and a `signature` when the model signs it, `reasoning.summary`, or `reasoning.encrypted` with sealed reasoning in `data`. On input NagaAI also accepts `reasoning` in place of `reasoning_content`.

Some models hide their reasoning and return only a summary or sealed data. You still pay for every reasoning token at the output price, because the model generated them.

## Keep the reasoning across turns

Some models need their earlier reasoning to continue a chain of tool calls. Send each assistant turn back unchanged: the Chat Completions message with its `reasoning_details`, the Responses `reasoning` items in `input`, or the Messages `content` with its `thinking` blocks and their `signature`. In the Python SDK, append `message.model_dump(exclude_none=True)` for Chat Completions; in Node.js, append the message object itself.

A signature only works with the provider that issued it. NagaAI removes signatures and sealed reasoning from other providers before it sends the request, so a conversation can move between providers without an error.

## Troubleshooting

### `400` with `thinking.budget_tokens must be >= 1024`

The Messages format requires a budget of at least 1024 tokens. Raise the budget, or set `output_config.effort` to a level instead.

### The reasoning is empty

The model hides its reasoning. Look for a summary in `reasoning_details` or in the `summary` of the Responses item. The reasoning tokens in `usage` show that the model did reason.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.