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

# Reasoning Effort

> One graded knob (off → high) that maps to each provider's native reasoning control and persists across sessions

Set how hard the model thinks with one graded level; PraisonAI translates it to each provider's native reasoning control.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    instructions="Solve tricky problems step by step.",
    llm="openai/gpt-5",
    reasoning_effort="high",
)
agent.start("Design a load balancer for a spiky workload.")
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Reasoning Effort"
        Level[📊 Level] --> Core[🧠 PraisonAI Core]
        Core --> OpenAI[🤖 OpenAI/xAI<br/>reasoning_effort]
        Core --> Anthropic[💭 Anthropic/Gemini<br/>thinking budget]
        Core --> Other[⚪ Others<br/>no-op]
    end

    classDef level fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef core fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef provider fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef noop fill:#10B981,stroke:#7C90A0,color:#fff

    class Level level
    class Core core
    class OpenAI,Anthropic provider
    class Other noop
```

## Quick Start

**1. Enable with a level**

Pass a graded level to the agent.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    instructions="Solve tricky problems step by step.",
    llm="openai/gpt-5",
    reasoning_effort="high",
)
agent.start("Design a load balancer for a spiky workload.")
```

**2. Switch provider, same level**

The same level works on Anthropic and produces an extended-thinking budget under the hood.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    instructions="Solve tricky problems step by step.",
    llm="anthropic/claude-3-7-sonnet",
    reasoning_effort="high",
)
agent.start("Design a load balancer for a spiky workload.")
```

**3. Turn it off**

`off` is a zero-overhead no-op.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    instructions="Answer directly.",
    llm="openai/gpt-5",
    reasoning_effort="off",
)
agent.start("What is the capital of France?")
```

**4. Change it after construction**

The setter keeps a cached LLM in sync.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(instructions="Reason carefully.", llm="openai/gpt-5")
agent.reasoning_effort = "low"
agent.start("Summarise this in one line.")
```

The setter also updates an already-built LLM in place, so a change after the instance materialises still lands on the next request.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(instructions="Reason carefully.", llm="openai/gpt-5")

# Force the LLM to materialise (as `.start()` would).
_ = agent.llm_instance

# Change effort after materialisation — the very next request emits `high`.
agent.reasoning_effort = "high"
agent.start("Design a load balancer for a spiky workload.")
```

The CLI `--thinking <level>` flag uses this same setter path internally, so the flag takes effect even when it is applied after the LLM has been built.

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant Core
    participant Provider
    participant LLM

    User->>Agent: reasoning_effort="high"
    Agent->>Core: resolve_reasoning_params(effort, model)
    Core->>Provider: native param (reasoning_effort / thinking)
    Provider->>LLM: request
    LLM-->>User: Response
```

| Phase | What happens |
| - | - |
| 1. Set | You pass a graded level to the agent |
| 2. Resolve | Core maps the level to the model's native control |
| 3. Request | The provider receives its native reasoning parameter |

***

## Streaming

`start(stream=True)` (and `iter_stream()`) honour `reasoning_effort` on both streaming branches.

Since [PR #4780](https://github.com/MervinPraison/PraisonAI/pull/4780), streaming and non-streaming produce identical provider requests for reasoning-effort semantics. The same `resolve_reasoning_params` mapping runs on both paths, so `"off"` stays a zero-overhead no-op, unset stays absent, and a model without a native reasoning control is untouched. Tool follow-up turns inherit the knob.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    instructions="Solve tricky problems step by step.",
    llm="o4-mini",
    reasoning_effort="high",
)

for chunk in agent.start("Design a load balancer for a spiky workload.", stream=True):
    print(chunk, end="", flush=True)
```

> [!NOTE]
>
> Before [PR #4780](https://github.com/MervinPraison/PraisonAI/pull/4780), `reasoning_effort` was silently dropped on both streaming branches — every level from `minimal` to `high` produced a byte-identical provider request under `stream=True`. Since #4780 the graded level reaches the provider on the streaming path too. See [Streaming → Sampling knobs on the streaming path](https://praison.ai/docs/features/streaming.md#sampling-knobs-on-the-streaming-path).

***

## Levels

Each level maps to a native parameter per provider family.

| Level | OpenAI/xAI request | Anthropic/Gemini request | Non-reasoning models |
| - | - | - | - |
| `off` | — | — | — |
| `minimal` | `reasoning_effort="minimal"` | `thinking={"type":"enabled","budget_tokens":2000}` | ignored |
| `low` | `reasoning_effort="low"` | `budget_tokens=4000` | ignored |
| `medium` | `reasoning_effort="medium"` | `budget_tokens=8000` | ignored |
| `high` | `reasoning_effort="high"` | `budget_tokens=16000` | ignored |

***

## Provider Coverage

Which model families the level affects.

| Model family | Native control |
| - | - |
| OpenAI o-series (`o1`, `o3`, `o3-mini`) and GPT‑5 | `reasoning_effort` |
| xAI Grok reasoning models (`xai/grok-*`) | `reasoning_effort` |
| Anthropic Claude 3.7+ reasoning models | extended-thinking `thinking` budget |
| Gemini 2.5+ reasoning models | extended-thinking `thinking` budget |
| Everything else (e.g. `gpt-4o`, `gpt-4o-mini`) | silently ignored |

***

## Which Level Should I Pick?

Match the level to the task.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q[What kind of task?] -->|Quick lookup / one-liner| M[minimal]
    Q -->|Simple reasoning| L[low]
    Q -->|Default / balanced| Med[medium]
    Q -->|Complex analysis / planning / long code| H[high]
    Q -->|Not a reasoning task| Off[off]

    classDef question fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef option fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef noop fill:#10B981,stroke:#7C90A0,color:#fff

    class Q question
    class M,L,Med,H option
    class Off noop
```

***

## Four Ways to Set It

The same level is available in Python, YAML, the CLI, and the Desktop app.

```python Python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(instructions="Solve tricky problems.", llm="openai/gpt-5", reasoning_effort="high")
agent.start("Design a load balancer for a spiky workload.")
```

```yaml YAML theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
agent:
  reasoning_effort: high
```

```bash CLI theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai run --thinking high "Design a load balancer for a spiky workload."
```

**Desktop app:** Open **Settings → Models → Reasoning effort** and pick a level. `Off` is the default and leaves the provider default in place; any other level is forwarded on the next turn (same rule as `temperature` / `top_p`). The choice round-trips through `settings.json`, so it persists across restarts. It is app-wide, not per-chat. See [Desktop → Models & API Keys](https://praison.ai/docs/features/desktop/models.md#reasoning-effort).

> [!NOTE]
>
> `--thinking <level>` is applied to the agent after construction. It reaches the request pipeline even when the LLM instance has already been materialised — no rebuild required.

***

## Session Persistence

The effort you were running is persisted on the session and restored on resume — you do not need to pass `--thinking` again.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai run --thinking high "start work"
# later:
praisonai run --continue "keep going"     # still runs at high
```

> [!NOTE]
>
> A per-invocation `--thinking <level>` on resume overrides the persisted value.

***

## Backward Compatibility

`thinking_budget` remains a supported alias that folds into `reasoning_effort`.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

# Graded string alias.
agent = Agent(instructions="x", llm="openai/gpt-5", thinking_budget="high")

# Legacy int budget — normalised to the nearest level (8000 -> medium).
agent = Agent(instructions="x", llm="openai/gpt-5", thinking_budget=8000)

# Post-construction int still routes through the effort setter.
agent.thinking_budget = 16000
```

The graded value is what gets persisted, so the effort stays provider-portable.

`agent.thinking_budget` reads back the last **integer** budget that was set (or `None`); the graded string level always lives on `agent.reasoning_effort`. Assigning a graded string (`agent.thinking_budget = "high"`) still routes through the effort setter, but `agent.thinking_budget` continues to report `None` in that case — read `agent.reasoning_effort` for the current level.

***

## Best Practices

> [accordion] Match effort to task complexity
>
> Start at `medium` and raise to `high` for planning, analysis, or long code.

> [accordion] Use off on non-reasoning models
>
> `reasoning_effort="off"` is a no-op with no runtime cost.

> [accordion] Change effort mid-session
>
> Assign `agent.reasoning_effort` at any time; the setter updates a cached LLM in place.

> [accordion] Prefer the graded level over the legacy int
>
> Use a level (not a raw token budget) so the value stays provider-portable.

> [accordion] Works with stream=True
>
> Since [PR #4780](https://github.com/MervinPraison/PraisonAI/pull/4780), the graded level reaches the provider on the streaming path too — no need to disable streaming to get reasoning behaviour.

***

## Related

> [card] [Thinking Budgets](https://praison.ai/docs/features/thinking-budgets.md)
>
> Legacy alias and token-budget helper

> [card] [Reflection](https://praison.ai/docs/features/reflection.md)
>
> Self-review loops for higher-quality outputs

> [card] [Streaming](https://praison.ai/docs/features/streaming.md#sampling-knobs-on-the-streaming-path)
>
> `reasoning_effort` reaches the provider on both streaming branches


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