max_steps is the unified outer-loop step budget honoured identically by both tool-execution loops (OpenAI-native and LiteLLM). On the final permitted step the model is asked to wrap up, so you get a coherent answer instead of a hard cut.
Quick Start
1
Raise the budget with a scalar
2
Detect truncation with last_stop_reason
How It Works
On the final permitted step both loops inject an internal user-role message so the model produces a coherent final answer:“You are approaching the maximum number of tool-use steps for this task. Stop calling tools now and provide your best final answer, summarising the work completed so far and clearly noting anything left incomplete.”The wrap-up message works on a local copy of the conversation, so it never leaks into the caller’s history.
Choosing a Value
Configuration Options
Full list of options, types, and defaults —
ExecutionConfig
Two helpers resolve the effective values:
How it relates to max_tool_calls_per_turn
max_steps bounds outer-loop iterations — one LLM round-trip each. max_tool_calls_per_turn caps how many tool calls the model can fire inside one response. They are independent on purpose: if they were coupled, a single parallel-tool response could exhaust the whole step budget (e.g. max_steps=5 truncating after one round of 5 parallel calls). Set them separately when you need both a long overall budget and a small per-turn burst.
Safe to read on any agent, including LiteLLM-only ones — reading
agent.last_stop_reason never lazily creates the OpenAI client. Returns "completed" by default when no run has finished yet.Common Patterns
Pattern 1 — Raise the budget for long runs
Pattern 2 — Detect and continue after truncation
Pattern 3 — Independent per-turn guardrail
Best Practices
Set an explicit budget for long agentic runs
Set an explicit budget for long agentic runs
The default (20, via
max_iter) is fine for short tasks but truncates deep refactors and multi-step research. Raise max_steps to 50–100 for those.Branch on last_stop_reason, not on message content
Branch on last_stop_reason, not on message content
Check
agent.last_stop_reason == "max_steps" instead of parsing the answer text. The old magic "Tool call limit reached" string is now suppressed when a genuine final answer exists.Keep max_tool_calls_per_turn independent
Keep max_tool_calls_per_turn independent
max_steps and max_tool_calls_per_turn govern different things — a per-turn cap of 5 does not halve your step budget. Coupling them would let one parallel-tool response exhaust the whole budget.max_steps is validated at construction
max_steps is validated at construction
max_steps must be >= 1 when set, otherwise ExecutionConfig raises ValueError. Catch it in config-driven setups.Related
Execution
Iteration limits, retries, rate limiting, and code execution
Error Handling
Catch and recover from agent, tool, and LLM errors

