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

# Reasoning

> Let ASI:One models think before they answer, and read the reasoning they produce

## Overview

ASI:One models can reason before they answer. When reasoning is on, the model
produces a train of thought first, then writes its actual reply. You get both
back: the reasoning in `reasoning_content`, the answer in `content`.

Reasoning helps on problems with several steps, ambiguous requirements, or a
chain of logic to follow. It costs extra tokens and adds latency, so how much of
it you get is worth choosing per request.

`asi1` and `asi1-ultra` always reason, at the deepest depth unless you ask for
a lighter one. `asi1-mini` does not reason unless you turn it on. See [Model support](#model-support).

How you ask for reasoning depends on the endpoint:

* On **`/v1/chat/completions`**, use `reasoning_effort` for depth, plus the
  ASI:One parameters `enable_thinking`, `thinking_budget` and
  `use_reasoning_history`, described below.
* On **`/v1/responses`**, use OpenAI's standard [`reasoning` object](#reasoning-on-the-responses-api). If you are already writing against the
  OpenAI Responses API, nothing changes.

## Turning reasoning on

Set `enable_thinking` to `true`. It is a top-level field, honored on
`asi1-mini`. On `asi1` and `asi1-ultra` the model always thinks, so the flag is
accepted but does not switch reasoning off. Control the depth with
`reasoning_effort` instead.

#### cURL

```bash
curl -X POST https://api.asi1.ai/v1/chat/completions \
  -H "Authorization: Bearer $ASI_ONE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "asi1",
    "messages": [
      {"role": "user", "content": "A train leaves at 14:05 and arrives at 17:40, stopping twice for 12 minutes each. How long is it moving?"}
    ],
    "enable_thinking": true
  }'
```

#### Python

```python
import os

from openai import OpenAI

client = OpenAI(
    api_key=os.getenv("ASI_ONE_API_KEY"),
    base_url="https://api.asi1.ai/v1"
)

response = client.chat.completions.create(
    model="asi1",
    messages=[
        {"role": "user", "content": "A train leaves at 14:05 and arrives at 17:40, stopping twice for 12 minutes each. How long is it moving?"}
    ],
    extra_body={"enable_thinking": True}
)

print(response.choices[0].message.content)
```

The OpenAI SDK does not know about `enable_thinking`, so pass it through
`extra_body`. With raw HTTP it is a normal top-level field.

## Reading the reasoning

The reasoning arrives in a `reasoning_content` field alongside the usual
`content`.

On a normal response it sits on the message:

```json
{
  "choices": [
    {
      "message": {
        "role": "assistant",
        "reasoning_content": "Total elapsed is 3h35m. Two stops of 12 minutes each is 24 minutes...",
        "content": "The train is moving for 3 hours and 11 minutes."
      }
    }
  ]
}
```

When streaming, it arrives in the delta, generally before any `content` deltas:

```
data: {"choices":[{"delta":{"reasoning_content":"Total elapsed is 3h35m..."}}]}

data: {"choices":[{"delta":{"content":"The train is moving"}}]}
```

Treat `reasoning_content` as display-only and always optional. It is there for
transparency and debugging; you should not parse it for structured values, and
you should not assume it is present. It is `null` when reasoning is off, and an
empty string when the model reasoned without producing text, which is common at
the lowest depths. Handle both.

## Choosing a reasoning depth

`reasoning_effort` is a top-level field that controls how deeply the model
thinks. Its values map to three depths:

| `reasoning_effort` | What you get                                                                                                             |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `low`              | Light reasoning: fastest and cheapest, for simple tasks                                                                  |
| `medium`           | Balanced reasoning: a good fit for everyday work                                                                         |
| `high`             | Deep reasoning: most thorough, for hard or multi-step problems. **The default when the request sets no depth parameter** |

```json
{
  "model": "asi1-ultra",
  "messages": [{ "role": "user", "content": "..." }],
  "reasoning_effort": "low"
}
```

Those three are the scale to write against. A client built on OpenAI's SDK may
send `minimal` or `xhigh` instead, and those are accepted too rather than
failing the request: `minimal` gives the same depth as `low`, and `xhigh` the
same as `high`.

Deep reasoning is not free: `high` spends substantially more output tokens than
`medium` for a modest gain in quality. The depth a request gets when it sets
none of the depth parameters is the **deep** one, so an unconfigured request is
also the most expensive one. Send `medium` or `low` explicitly on everyday
work, and keep `high` for hard multi-step problems and code audits.

Notes:

* On `asi1` and `asi1-ultra`, `reasoning_effort` is the primary way to control
  reasoning. Omit both `reasoning_effort` and `thinking_budget` and the request
  runs at the deep depth.
* On `asi1-mini`, `reasoning_effort` has no effect; use `enable_thinking`
  there.
* `reasoning_effort` takes precedence over `thinking_budget` when both are
  sent.

## Legacy depth control

`thinking_budget` is the older way to size reasoning, kept working for clients
already using it. It is not a token cap: the value selects one of the same three
depths, so only the band matters, not the exact number.

| `thinking_budget` | Depth    |
| ----------------- | -------- |
| `4096` or less    | `low`    |
| up to `12288`     | `medium` |
| above `12288`     | `high`   |

Omit both depth parameters and the deep default applies. On new code reach for
[`reasoning_effort`](#choosing-a-reasoning-depth) instead: it is the direct
control, and it wins when both are sent.

To stop the model reasoning, set `enable_thinking` to `false` on `asi1-mini`.
That is the only model where reasoning can be switched off; on `asi1` and
`asi1-ultra` it always runs, and the flag only leaves it at its shallowest.

```json
{
  "model": "asi1",
  "messages": [{ "role": "user", "content": "..." }],
  "thinking_budget": 2048
}
```

A lower band trims latency and cost but gives the model less room on hard
problems. `asi1-mini` accepts the field but its depth does not change with it.
See [Model support](#model-support).

## Carrying reasoning across turns

`use_reasoning_history` decides whether the model sees its own reasoning from
earlier turns. Set it to `true` on `asi1` and `asi1-ultra` and each turn starts
with what the model concluded in the last one; leave it unset and prior
reasoning is stripped, so the model re-derives those conclusions from scratch.

It is worth turning on for agentic and tool-calling work, where a run depends on
conclusions reached several steps earlier. When you do, replay each assistant
message's `reasoning_content` back verbatim - do not reorder, truncate or edit
it, or the model sees a history it did not produce.

`asi1-mini` accepts the field; whether it changes anything there is not
something we have measured.

## Reasoning on the Responses API

`/v1/responses` also takes OpenAI's standard `reasoning` object, so a client
already written against OpenAI's API needs no changes to control reasoning here.

```json
{
  "model": "asi1",
  "input": "A train leaves at 14:05 and arrives at 17:40...",
  "reasoning": { "effort": "medium" }
}
```

`effort` accepts the same three depths, plus `none`:

| `effort` | What you get                                             |
| -------- | -------------------------------------------------------- |
| `none`   | Reasoning off on `asi1-mini`; shallowest depth otherwise |
| `low`    | Light reasoning                                          |
| `medium` | Balanced reasoning                                       |
| `high`   | Deep reasoning                                           |

`none` turns reasoning off on `asi1-mini`. `asi1` and `asi1-ultra` always
think, so there it leaves the model at its shallowest depth rather than
switching reasoning off.

`minimal` and `xhigh` are accepted too, so a client built on OpenAI's SDK works
unchanged: `minimal` gives the same depth as `low`, and `xhigh` the same as
`high`. Any value outside OpenAI's scale is rejected with a `400`.

If you omit `reasoning` entirely, or send it without an `effort`, the request
falls back to `enable_thinking` and `thinking_budget`, so both styles work on
this endpoint and you can migrate at your own pace.

On this endpoint the reasoning comes back as a `reasoning` output item rather than
a `reasoning_content` field, with the text in that item's `content`. It streams as
`response.reasoning_text.delta` events, followed by `response.reasoning_text.done`.

The same per-model support applies: on `asi1` and `asi1-ultra` the effort sets
the reasoning depth, and on `asi1-mini` it turns reasoning on or off.

## Model support

Not every parameter applies to every model.

| Parameter                            | `asi1`                                                        | `asi1-ultra`                                                  | `asi1-mini`                 |
| ------------------------------------ | ------------------------------------------------------------- | ------------------------------------------------------------- | --------------------------- |
| `enable_thinking`                    | Cannot switch reasoning off; `false` selects the lowest depth | Cannot switch reasoning off; `false` selects the lowest depth | Yes                         |
| `thinking_budget`                    | Selects a depth tier                                          | Selects a depth tier                                          | No effect                   |
| `reasoning_effort`                   | Yes                                                           | Yes                                                           | No effect                   |
| `use_reasoning_history`              | Yes                                                           | Yes                                                           | Accepted; effect unmeasured |
| `reasoning.effort` (`/v1/responses`) | Yes                                                           | Yes                                                           | On or off only              |

You can send the same request body to any of the three models without branching
your code: no parameter ever turns a request into an error. Only the controls
differ: use `reasoning_effort` for depth on `asi1` and `asi1-ultra`, and
`enable_thinking` to switch reasoning on and off on `asi1-mini`.

> **Tip**
>
> Reasoning costs latency and tokens, so it is worth controlling per request.
> Send your reasoning parameters explicitly wherever the difference matters to
> you rather than leaving it to a default.

## Next steps

1. **[Responses API](/documentation/build-with-asi-one/responses#streaming)** - Where OpenAI's `reasoning` object applies, and how reasoning streams there
2. **[Chat Completions API](/documentation/build-with-asi-one/chat-completions#streaming)** - Where `enable_thinking` applies, and how reasoning streams there
3. **[Planner Mode](/documentation/build-with-asi-one/planner)** - Break complex requests into steps executed against tools and agents
4. **[ASI:One Models](/documentation/models)** - Which model to reach for
5. **[Tuning](/documentation/build-with-asi-one/tuning)** - Where depth sits in the order of things to try