Reasoning Models

Configure native reasoning models, separate response models, and provider-exposed reasoning events.

Setup

In an activated virtual environment:

uv pip install -U agno openai
export OPENAI_API_KEY="your_openai_api_key"

Native reasoning is configured on the model. Providers differ in supported effort settings, tools, streaming, and the content they expose. OpenAI returns optional reasoning summaries rather than raw hidden reasoning; request summaries explicitly. See the OpenAI reasoning guide.

Examples

gpt-5.2

gpt_5_2.py
from agno.agent import Agent
from agno.models.openai import OpenAIResponses

# Setup your Agent using a reasoning model
agent = Agent(model=OpenAIResponses(id="gpt-5.2", reasoning_effort="medium", reasoning_summary="auto"))

# Run the Agent
agent.print_response(
    "Solve the trolley problem. Evaluate multiple ethical frameworks. Include an ASCII diagram of your solution.",
    stream=True,
    show_full_reasoning=True,
)

gpt-5.2 with tools

gpt_5_2_with_tools.py
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.hackernews import HackerNewsTools

# Setup your Agent using a reasoning model
agent = Agent(
    model=OpenAIResponses(id="gpt-5.2", reasoning_effort="medium", reasoning_summary="auto"),
    tools=[HackerNewsTools()],
    markdown=True,
)

# Run the Agent
agent.print_response("Compare the topics of the top five Hacker News stories using their titles and URLs.", stream=True)

gpt-5.2 with reasoning effort

gpt_5_2_with_reasoning_effort.py
from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.hackernews import HackerNewsTools

# Setup your Agent using a reasoning model with high reasoning effort
agent = Agent(
    model=OpenAIResponses(id="gpt-5.2", reasoning_effort="high", reasoning_summary="auto"),
    tools=[HackerNewsTools()],
    markdown=True,
)

# Run the Agent
agent.print_response("Compare the topics of the top five Hacker News stories using their titles and URLs.", stream=True)

DeepSeek thinking

The hosted legacy deepseek-reasoner alias has been retired. This sample uses the V4 Flash thinking mode. See DeepSeek's migration notice.

export DEEPSEEK_API_KEY="your_deepseek_api_key"
deepseek_thinking.py
from agno.agent import Agent
from agno.models.deepseek import DeepSeek

# Setup your Agent using a reasoning model
agent = Agent(
    model=DeepSeek(id="deepseek-v4-flash", use_thinking=True),
    markdown=True,
)

# Run the Agent
agent.print_response("9.11 and 9.9 -- which is bigger?", stream=True)

Reasoning Model + Response Model

Configure a supported native reasoning_model for a separate stage, then a main model for response generation. This adds model calls and latency; compare its benefit on your own tasks.

DeepSeek thinking + Claude Sonnet

Install the Anthropic client and set its key in addition to the DeepSeek setup above:

uv pip install anthropic
export ANTHROPIC_API_KEY="your_anthropic_api_key"
deepseek_plus_claude.py
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.models.deepseek import DeepSeek

# Setup your Agent using an extra reasoning model
deepseek_plus_claude = Agent(
    model=Claude(id="claude-sonnet-4-5"),
    reasoning_model=DeepSeek(id="deepseek-v4-flash", use_thinking=True),
)

# Run the Agent
deepseek_plus_claude.print_response("9.11 and 9.9 -- which is bigger?", stream=True)

Streaming Reasoning Content

When using a reasoning_model, you can stream the reasoning content as it's being generated. Only content exposed by the provider is available; it may be a summary or may be absent.

To enable streaming reasoning, set stream=True and stream_events=True when running the agent:

streaming_reasoning.py
from agno.agent import Agent
from agno.models.anthropic import Claude

# Create an agent with a reasoning model
agent = Agent(
    reasoning_model=Claude(
        id="claude-sonnet-4-5",
        thinking={"type": "enabled", "budget_tokens": 1024},
    ),
    model=Claude(id="claude-sonnet-4-5"),
    instructions="Think step by step about the problem.",
)

# Stream the response with reasoning events
agent.print_response(
    "What is 25 * 37? Show your reasoning.",
    stream=True,
    stream_events=True,
)

Capturing Reasoning Events

You can also capture individual reasoning events. This gives you fine-grained control over how reasoning content is displayed:

capture_reasoning_events.py
from agno.agent import Agent
from agno.models.anthropic import Claude
from agno.run.agent import RunEvent

agent = Agent(
    reasoning_model=Claude(
        id="claude-sonnet-4-5",
        thinking={"type": "enabled", "budget_tokens": 1024},
    ),
    model=Claude(id="claude-sonnet-4-5"),
    instructions="Think step by step about the problem.",
)

for run_output_event in agent.run(
    "What is 25 * 37? Show your reasoning.",
    stream=True,
    stream_events=True,
):
    if run_output_event.event == RunEvent.run_started:
        print(f"EVENT: {run_output_event.event}")
    elif run_output_event.event == RunEvent.reasoning_started:
        print(f"EVENT: {run_output_event.event}")
        print("Reasoning started...\n")
    elif run_output_event.event == RunEvent.reasoning_content_delta:
        # Stream reasoning content as it's being generated
        print(run_output_event.reasoning_content, end="", flush=True)
    elif run_output_event.event == RunEvent.run_content:
        if run_output_event.content:
            print(run_output_event.content, end="", flush=True)
    elif run_output_event.event == RunEvent.run_completed:
        print(f"EVENT: {run_output_event.event}")

The key events for streaming reasoning are:

EventDescription
RunEvent.reasoning_startedEmitted when reasoning begins
RunEvent.reasoning_content_deltaEmitted for each chunk of reasoning content as it streams
RunEvent.run_contentEmitted for the final response content

Developer Resources