Reasoning Models

How PraisonAI handles OpenAI o1/o3/o4/gpt-5.x reasoning models automatically

Reasoning models (OpenAI o1, o3, o4, gpt-5.x) accept a different set of parameters — PraisonAI detects them automatically and normalises your Agent(...) config so the same code just works.

Diagram

Reasoning Model Normalization

Yes

No

🤖 Agent

🔍 Reasoning
model?

🛠️ Rename max_tokens
Drop sampling params

📤 Send as-is

💬 LLM Call

Quick Start

  1. Use a reasoning model
    python
    from praisonaiagents import Agent
    
    agent = Agent(
        name="Reasoner",
        instructions="Solve the problem step by step.",
        llm="gpt-5",   # or "o1", "o3-mini", "o4-mini", etc.
    )
    agent.start("Design a caching layer for a high-traffic API.")

    No extra flags. PraisonAI detects reasoning models and normalises parameters for you.

  2. Cap the response length
    python
    from praisonaiagents import Agent
    
    agent = Agent(
        name="Reasoner",
        instructions="Solve the problem step by step.",
        llm="o3-mini",
        max_tokens=4000,  # Automatically sent as max_completion_tokens
    )
    agent.start("Explain the CAP theorem with an example.")

    You can keep writing max_tokens=... — on reasoning models it is rewritten to max_completion_tokens before the request.


How It Works

PraisonAI checks the model before every call and rewrites parameters only when the model is a reasoning model.

Diagram
OpenAI / LiteLLMllm.py_build_completion_paramsopenai_client_normalize_chat_paramsAgentUserOpenAI / LiteLLMllm.py_build_completion_paramsopenai_client_normalize_chat_paramsAgentUseralt[Native OpenAI client path][LiteLLM path]agent.start(“…”)build request paramsomit temperature=None, max_tokens=Nonereasoning? max_tokens → max_completion_tokenschat.completions.create(…)build request paramsreasoning? max_tokens → max_completion_tokensdrop temperature, top_p, penalties, logit_biascompletion(…)responseanswer
StepBehaviour
Detectionis_reasoning_model(model) decides the path
Reasoning modelmax_tokens renamed on both paths; sampling params dropped on the LiteLLM path
Chat modelParameters sent unchanged
Responses API pathAlready uses max_output_tokens — unchanged

Recognised Models

Detection uses two paths, in order:

  1. Primary: litellm.supports_reasoning(model=model_name) when litellm is installed and exposes the helper.
  2. Fallback: strip the provider prefix (e.g. openai/, azure/) and match the lowercase prefix — o1, o3, o4, or gpt-5.

Results are cached with functools.lru_cache(maxsize=256).

Model familyExample idsDetection
OpenAI o1o1, o1-mini, o1-previewprefix + litellm
OpenAI o3o3, o3-miniprefix + litellm
OpenAI o4o4-miniprefix + litellm
OpenAI gpt-5.xgpt-5, gpt-5-mini, gpt-5-nano, gpt-5.6-luna, …prefix + litellm

Parameter Behaviour

On a reasoning model, PraisonAI rewrites and drops parameters as follows. Which rules apply depends on the path the request takes.

RuleNative OpenAI client pathLiteLLM path
max_tokens → max_completion_tokensRenamedRenamed
max_completion_tokens (explicit)Wins over max_tokensWins over max_tokens
temperature / max_tokens left unsetOmitted from the requestOmitted from the request
temperature set explicitlySent as-is — the provider decidesDropped
top_p, presence_penalty, frequency_penalty, logit_biasSent as-is — the provider decidesDropped
Chat models (non-reasoning)UnchangedUnchanged
Responses API pathUnchanged (already uses max_output_tokens)—

Which Parameters Should I Set?

Pick your parameters based on the model you chose.

Diagram

No

Yes

Yes

No

🎯 I want to configure my model

Is my model
o1/o3/o4/gpt-5.x?

✅ Set temperature, top_p,
max_tokens as usual

Need to cap
response length?

✅ Set max_tokens
auto-mapped to max_completion_tokens

✅ Just set llm=… — nothing else


Common Patterns

Mix reasoning and chat models in one team — each agent normalizes independently based on its own model.

python
from praisonaiagents import Agent, Task, PraisonAIAgents

planner = Agent(name="Planner", instructions="Plan step by step.", llm="o3-mini")
writer = Agent(name="Writer", instructions="Write clearly.", llm="gpt-4o", temperature=0.7)

agents = PraisonAIAgents(
    agents=[planner, writer],
    tasks=[
        Task(description="Plan an article on vector databases.", agent=planner),
        Task(description="Write the article from the plan.", agent=writer),
    ],
)
agents.start()

Be explicit with max_completion_tokens when you want it to win over max_tokens.

python
from praisonaiagents import Agent

agent = Agent(
    name="Reasoner",
    instructions="Solve the problem step by step.",
    llm="o3-mini",
    max_completion_tokens=2000,  # Wins; max_tokens (if set) is dropped
)
agent.start("Prove that the square root of 2 is irrational.")

Migrate from a chat model to a reasoning model with no code changes.

python
from praisonaiagents import Agent

# Was: llm="gpt-4o" with temperature and max_tokens
agent = Agent(
    name="Reasoner",
    instructions="Solve the problem step by step.",
    llm="gpt-5",       # swap the model — sampling params are dropped automatically
    max_tokens=3000,   # still works, mapped to max_completion_tokens
)
agent.start("Compare quicksort and mergesort.")

Best Practices

Don't set temperature or top_p on reasoning models

They have no useful effect — dropped on the LiteLLM path, forwarded to the provider on the native OpenAI client path. If you rely on determinism or creative sampling, prefer a chat model such as gpt-4o.

Prefer max_completion_tokens when you want to be explicit

It always wins over max_tokens on reasoning models, so there is no ambiguity about which limit applies.

Test model swaps before deploying

Swapping gpt-4o → gpt-5 silently drops your sampling params. Behaviour differs even though no error is raised — verify output quality first.

Use LiteLLM's latest release when possible

Detection prefers litellm.supports_reasoning(). The prefix fallback only covers the o1/o3/o4/gpt-5 families, so newer models are recognised sooner with an up-to-date litellm.


Related