Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/openai/openai-cookbook/llms.txt

Use this file to discover all available pages before exploring further.

OpenAI’s o-series models — o1, o3, and o4-mini — are trained to think for longer before responding. Rather than generating an answer token by token in a single forward pass, they produce an internal chain of thought before committing to a final output. This makes them significantly more capable on tasks that require sustained multi-step reasoning: mathematics, competitive programming, scientific analysis, and complex agentic workflows.

The o-series model lineup

o1

The first reasoning model. Best for structured tasks with clear correct answers. Strong on math and coding benchmarks. Use o3 or o4-mini for new projects where possible.

o3

The most capable reasoning model. Top of the line for difficult multi-step problems, long agentic rollouts, and tasks requiring deep exploration. Higher latency and cost than o4-mini.

o4-mini

A smaller, faster, cheaper reasoning model that retains most of o3’s capability on coding and math tasks. The recommended starting point for most latency-sensitive reasoning applications.

When to use reasoning models

Reasoning models outperform standard models most clearly when the task requires:
  • Multi-step arithmetic or algebra — problems where intermediate results feed into later steps.
  • Competitive programming — algorithm design and implementation under constraints.
  • Formal reasoning — logic puzzles, proof verification, structured inference.
  • Long-horizon agentic tasks — workflows where the model must plan and execute across many tool calls without losing track of the goal.
  • Scientific or technical analysis — interpreting experimental results, reviewing code for subtle bugs, or drafting technical documents where accuracy is paramount.
For straightforward tasks — translation, summarization, simple question answering — standard models like GPT-4o are faster and cheaper. Use reasoning models when accuracy on hard tasks justifies the additional cost and latency.

Calling a reasoning model

The Responses API is the recommended interface for o-series models. It persists reasoning tokens between tool calls within a turn, which leads to better decisions about when and how to use tools.
from openai import OpenAI
import json
import requests

client = OpenAI()


def get_weather(latitude: float, longitude: float) -> float:
    """Fetch current temperature in Celsius for a coordinate pair."""
    url = (
        f"https://api.open-meteo.com/v1/forecast"
        f"?latitude={latitude}&longitude={longitude}"
        f"&current=temperature_2m"
    )
    data = requests.get(url).json()
    return data["current"]["temperature_2m"]


tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "Get current temperature for provided coordinates in Celsius.",
        "parameters": {
            "type": "object",
            "properties": {
                "latitude": {"type": "number"},
                "longitude": {"type": "number"},
            },
            "required": ["latitude", "longitude"],
            "additionalProperties": False,
        },
        "strict": True,
    }
]

context = [{"role": "user", "content": "What's the weather like in Paris today?"}]

# First turn: model decides to call the tool
response = client.responses.create(
    model="o3",
    input=context,
    tools=tools,
    store=False,
    include=["reasoning.encrypted_content"],  # persist reasoning across turns
)

# Append the model's output (including encrypted reasoning) to context
context += response.output

tool_call = response.output[1]
args = json.loads(tool_call.arguments)
result = get_weather(args["latitude"], args["longitude"])

context.append(
    {
        "type": "function_call_output",
        "call_id": tool_call.call_id,
        "output": str(result),
    }
)

# Second turn: model synthesizes the tool result into a final answer
response_2 = client.responses.create(
    model="o3",
    input=context,
    tools=tools,
    store=False,
    include=["reasoning.encrypted_content"],
)

print(response_2.output_text)
Passing reasoning.encrypted_content back into subsequent requests lets the model refer to its previous reasoning trace without reconstructing a plan from scratch after each tool call. This improves both accuracy and latency.

Reasoning effort

All o-series models expose a reasoning_effort parameter with three settings:
SettingUse when
lowLatency matters more than peak accuracy; task is well-defined and relatively straightforward
mediumDefault; suitable for most production use cases
highAccuracy matters most; task is complex, ambiguous, or requires deep exploration
response = client.responses.create(
    model="o4-mini",
    input=[{"role": "user", "content": "Solve this system of differential equations..."}],
    reasoning={"effort": "high"},
)
Start with medium and tune from there. Many workflows achieve consistent results at low reasoning effort, which substantially reduces latency and cost.

Writing effective developer prompts

In o-series models, the system prompt is automatically converted to a developer message internally. For clarity and correctness, treat all top-level instructions as the developer prompt.

Context and role setting

Begin with a clear role and the set of actions available to the model:
You are an AI retail agent.

As a retail agent, you can help users cancel or modify pending orders,
return or exchange delivered orders, modify their default user address,
or provide information about their own profile, orders, and related products.

Tool call ordering

Reasoning models are trained to accomplish goals with tools but can make mistakes in ordering. For well-defined workflows, specify the sequence explicitly:
To process a refund for a delivered order, follow these steps in order:
1. Confirm the order was delivered. Use: order_status_check
2. Check the refund eligibility policy. Use: refund_policy_check
3. Create the refund request. Use: refund_create
4. Notify the user of refund status. Use: user_notify
For less structured workflows, a lighter reminder is often enough:
Check to see if directories exist before creating files.

Tool use boundaries

Define when the model should and should not use tools:
Use tools when:
- The user wants to cancel or modify an order.
- The user wants to return or exchange a delivered product.
- The user asks for current or personalized order or profile information.

Do not use tools when:
- The user asks a general question like "What's your return policy?"
- The user asks something outside your retail role.

If a task is not possible due to real constraints (for example, trying to
cancel an already-delivered order), explain why clearly and do not call
tools blindly.

Writing effective function descriptions

A function’s description is the primary signal the model uses to decide when and how to call it. Put the most important constraints first:
# Good — key rules are front and center
Creates a new file with the specified name and contents in a target directory.
- Only call this function if the target directory exists. Check first using directory_check.
- Do not use for temporary content — prefer direct responses for those cases.
- Do not overwrite existing files. Always ensure the file name is unique.
# Worse — important rules are buried after verbose description
Performs a fast regex-based text search that looks for exact pattern matches
within files or entire directories, leveraging the ripgrep tool for high-speed
scanning. Output follows ripgrep formatting and can optionally display line
numbers and matched lines. To manage verbosity, results are limited to 50 hits.
You can fine-tune the search by specifying inclusion or exclusion rules...
[the crucial escape-character rule appears much later]
In testing, placing the critical argument-construction rule first produced 6% higher accuracy on a function-calling evaluation.

Avoiding common pitfalls

Unlike standard models, reasoning models already produce an internal chain of thought. Asking them to “plan extensively before each step” or “think step by step” adds overhead without improving results — and may hurt performance by interfering with the model’s internal reasoning process.
o3 in particular can occasionally promise to call a function in a future turn without actually doing so. Add an explicit instruction to prevent this:
Do NOT promise to call a function later. If a function call is required,
emit it now; otherwise respond normally.
Also enable strict: true on all tool schemas to ensure the model always produces valid arguments.
If the conversation history grows very long with tool call outputs that are no longer relevant, the model may produce terse or incomplete responses. Prune stale tool outputs from the context and replace them with a concise summary in the user message. Starting a new conversation thread for unrelated topics also helps.
Deeply nested parameter objects can cause the model to omit or misuse arguments. Prefer flat schemas where all fields are at the top level. When nesting is necessary for domain reasons (configuration payloads, rich search filters), use strict schemas and clear field descriptions to guard against invalid combinations.

Tool count and schema complexity

As of mid-2025, o3 and o4-mini handle up to approximately 100 tools with up to 20 arguments each within their training distribution. Beyond those limits, performance degrades. Even within those bounds:
  • Clear function descriptions become more critical as the tool list grows.
  • Overlapping tool purposes introduce ambiguity — disambiguate them in the developer prompt.
  • Adding an explicit rule like “Only use tools X, Y, Z. Do not invent tool calls or defer them to future turns.” prevents hallucination as tool sets grow.

Choosing between o3 and o4-mini

Start with o4-mini for most reasoning tasks. It is faster and cheaper than o3 and retains most of its capability on coding and math. Move to o3 when:
  • The task requires sustained deep exploration across many reasoning steps.
  • You are running long agentic rollouts where the model needs to revisit and revise earlier decisions.
  • Accuracy on very hard problems (top-tier math olympiad, complex proof verification) is the primary requirement and latency is acceptable.

Build docs developers (and LLMs) love