# Reasoning

> Control reasoning with reasoning_effort or the reasoning object, and read reasoning output.

Reasoning models think before they answer. Clonvo gives you one way to control that across providers, and returns the reasoning text when the provider shares it. Filter the [catalogue](https://clonvo.com/models.md) by **Reasoning** to find these models.

## Setting the effort

Use OpenAI’s `reasoning_effort`:

```python
completion = client.chat.completions.create(
    model="anthropic/claude-opus-5-5",
    messages=[{"role": "user", "content": "Plan a database migration with zero downtime."}],
    reasoning_effort="high",
)
```

Or the OpenRouter-style `reasoning` object, which takes precedence when both are present:

```python
completion = client.chat.completions.create(
    model="deepseek/deepseek-v4-pro",
    messages=[{"role": "user", "content": "Is 2,147,483,647 prime?"}],
    extra_body={"reasoning": {"effort": "medium", "exclude": False}},
)
```

| Field | Type | Description |
| --- | --- | --- |
| `reasoning.effort` | string | Same values as `reasoning_effort`. |
| `reasoning.max_tokens` | integer | Token budget for reasoning, on models that take a budget. |
| `reasoning.exclude` | boolean | Reason, but leave the reasoning text out of the response. |
| `reasoning.enabled` | boolean | `false` turns reasoning off. `true` on its own asks for `medium` effort. |

### Effort values

`none`, `minimal`, `low`, `medium`, `high`, `xhigh` and `max`. Each model accepts a subset, listed under **Reasoning efforts** on its [model page](https://clonvo.com/models.md). Clonvo maps the value to the provider’s own control, such as Anthropic’s effort setting or a thinking budget, or Gemini’s thinking configuration.

A value the model doesn’t accept isn’t an error. Clonvo uses the nearest supported effort: the next higher one, or the model’s highest if there’s nothing higher. `none` is never raised to a higher effort; on models that can’t turn reasoning off, the model uses its lowest effort or its default.

When you don’t ask for reasoning, each model uses its provider default. Some models (for example DeepSeek and Kimi) only reason when asked.

Qwen models think by default. `none` (or `reasoning.enabled: false`) turns thinking off, `reasoning.max_tokens` sets Qwen’s thinking budget, and Qwen 3.8 also takes `low`, `medium` and `xhigh` efforts.

## Reading the reasoning

When the provider returns reasoning text, it’s in `message.reasoning` (or `delta.reasoning` when streaming):

```json
{
  "role": "assistant",
  "content": "No. 2,147,483,647 is prime.",
  "reasoning": "It's the Mersenne number 2^31 − 1…"
}
```

Some models don’t return their reasoning text at all; `reasoning` is then left out of the message, but you’re still billed for the reasoning tokens. Set `reasoning.exclude` to `true` to leave it out yourself.

## Reasoning tokens and cost

Reasoning tokens are output tokens. They’re included in `usage.completion_tokens`, broken out in `usage.completion_tokens_details.reasoning_tokens`, and charged at the model’s output price. Leave room for them in `max_completion_tokens`.

## Multi-turn conversations

Pass earlier assistant messages back as you received them, including any `reasoning` field. What happens to it depends on the provider:

-   **Anthropic and Gemini** need their own signed thinking data between tool calls, which OpenAI-style messages can’t carry. Clonvo keeps Anthropic’s thinking blocks and Gemini’s thought signatures for 24 hours, keyed by the tool call ids, and adds them back automatically when you send the tool results. You don’t need to do anything, and the `reasoning` text itself isn’t sent back.
-   **DeepSeek and Moonshot (Kimi)** receive the `reasoning` of assistant turns with tool calls back as `reasoning_content`, which their thinking modes require. A `reasoning_content` field on your messages is accepted too.
-   **Free models** receive `reasoning` as you sent it.

If a tool loop continues more than 24 hours later, Anthropic requests are sent without the earlier thinking and Gemini requests use Google’s documented placeholder signature, so the request still works.