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.
Quick Start
- 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.
- 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 tomax_completion_tokensbefore the request.
How It Works
PraisonAI checks the model before every call and rewrites parameters only when the model is a reasoning model.
| Step | Behaviour |
|---|---|
| Detection | is_reasoning_model(model) decides the path |
| Reasoning model | max_tokens renamed on both paths; sampling params dropped on the LiteLLM path |
| Chat model | Parameters sent unchanged |
| Responses API path | Already uses max_output_tokens — unchanged |
Recognised Models
Detection uses two paths, in order:
- Primary:
litellm.supports_reasoning(model=model_name)when litellm is installed and exposes the helper. - Fallback: strip the provider prefix (e.g.
openai/,azure/) and match the lowercase prefix —o1,o3,o4, orgpt-5.
Results are cached with functools.lru_cache(maxsize=256).
| Model family | Example ids | Detection |
|---|---|---|
| OpenAI o1 | o1, o1-mini, o1-preview | prefix + litellm |
| OpenAI o3 | o3, o3-mini | prefix + litellm |
| OpenAI o4 | o4-mini | prefix + litellm |
| OpenAI gpt-5.x | gpt-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.
| Rule | Native OpenAI client path | LiteLLM path |
|---|---|---|
max_tokens → max_completion_tokens | Renamed | Renamed |
max_completion_tokens (explicit) | Wins over max_tokens | Wins over max_tokens |
temperature / max_tokens left unset | Omitted from the request | Omitted from the request |
temperature set explicitly | Sent as-is — the provider decides | Dropped |
top_p, presence_penalty, frequency_penalty, logit_bias | Sent as-is — the provider decides | Dropped |
| Chat models (non-reasoning) | Unchanged | Unchanged |
| Responses API path | Unchanged (already uses max_output_tokens) | — |
Which Parameters Should I Set?
Pick your parameters based on the model you chose.
Common Patterns
Mix reasoning and chat models in one team — each agent normalizes independently based on its own model.
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.
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.
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.