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.
On the CLI
A step-limit-truncated run throughpraisonai run / praisonai-code run exits 2 and emits status: "truncated" under --output json, preserving the wrap-up summary in result.
praisonai run → Exit Codes for the full CLI contract.
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
Turn Completion Notes
Surface the reason to chat users when a turn hits the step limit
praisonai run → Exit Codes
How a truncated run maps to exit
2 and status: "truncated" on the CLI
