Replaces the deprecated
allow_code_execution, code_execution_mode, and rate_limiter kwargs — see Legacy Agent Parameters.The string form of
execution= must name a valid preset (fast, balanced, thorough, …). A typo raises ValueError at construction time with a “Did you mean …?” suggestion — see Fail-Loud Defaults. Matching is case-insensitive, whitespace-tolerant, and treats -/_ interchangeably.Before PraisonAI PR #4186, hyphen / uppercase / padded variants were accepted by the validator but silently fell back to the default
max_iter. Upgrade to a build that includes PR #4186 to get the behaviour shown above.Quick Start
1
Level 1 — String (preset)
Pick a named execution profile — the shortest way to set sensible limits.
2
Level 2 — Config class (full control)
Use
ExecutionConfig to set exact iteration, time, and retry limits.Execution Presets
How It Works
Configuration Options
Full list of options, types, and defaults —
ExecutionConfigPrefer
max_steps for the tool-use budget — it’s the unified knob honoured by both execution loops, and you can detect truncation with agent.last_stop_reason. See Step Budget.Code-execution options
Settingcode_execution=True appends a real tool named execute_code to the agent’s tool list — it is not just a flag. Because the tool is named execute_code, the approval registry classes it critical, so it is approval-gated under every preset except "full".
The code executor runs a trailing expression exactly once. Earlier builds re-evaluated it, so
print(x) printed twice and a trailing my_tool(...) in code mode fired the tool twice. If you worked around that double execution, you no longer need to.Common Patterns
Pattern 1 — Budget-capped agent
Pattern 2 — Code execution agent
code_execution=True gives this agent an execute_code tool. That tool is classed critical, so under any approval preset except "full" the first execute_code call triggers an approval prompt before the code runs. In "safe" mode (shown here) the timeout on the ExecutionConfig is enforced per call by the subprocess. See Code Execution with Tools for the "unsafe" (tool-capable) path.Pattern 3 — Parallel tool calls for speed
ExecutionConfig.parallel_tool_calls is the single source of truth for running batched LLM tool calls in parallel. It applies uniformly to agent.start() / agent.chat() (sync) and agent.astart() / agent.achat() (async) as of PraisonAI PR #4634; earlier releases silently ignored the setting on the async path and ran tools sequentially. ToolConfig.parallel is a deprecated alias for it — prefer this spelling, and never set both to conflicting values (that raises TypeError).Pattern 4 — Code that calls your tools
Pattern 5 — The execute_code tool and its approval gate
Setting code_execution=True appends an execute_code tool to the agent. Because that tool is classed "critical", the approval framework prompts before it runs under every preset except "full".
Best Practices
Use presets as a starting point
Use presets as a starting point
execution="thorough" works well for most research and multi-step tasks. Only switch to custom ExecutionConfig when you need specific limits like budget caps or code execution.Set max_budget for cost control
Set max_budget for cost control
For any agent making many API calls, set
max_budget=0.50 to cap spend at 50 cents per run. Use on_budget_exceeded="warn" in development and "stop" in production.Enable parallel_tool_calls for speed
Enable parallel_tool_calls for speed
When your agent calls multiple independent tools per turn (e.g., search + fetch + calculate), enable
parallel_tool_calls=True to run them concurrently and cut latency. This is the single source of truth for parallel tool calls; ToolConfig.parallel is a deprecated alias for it. Parallel tool calls apply to both sync (chat() / start()) and async (achat() / astart()) tool loops as of PR #4634 — before that, async ran tools sequentially even with parallel_tool_calls=True. Concurrent writes to the same file fall back to sequential — see the write-conflict guard.Code execution safety
Code execution safety
code_mode="safe" is the right default for code_execution=True. It runs code in a subprocess with resource limits, and the timeout on your ExecutionConfig is enforced there as a hard per-call limit. "unsafe" mode runs in the current process — it enforces no hard timeout, so a runaway loop can block the worker; only choose it when code must reach your tools, and prefer "safe" whenever the timeout must be a guarantee. Agent(sandbox=…) only isolates explicit agent.execute_code(...) calls — it does not give the model a tool. For isolation of code the model runs, use AgentFlow(run_on="docker") / run_on="e2b" (whole workflow) or LocalAgent(compute="docker") (per-agent). See Placement.Scope code_tools with an explicit allow-list
Scope code_tools with an explicit allow-list
When
code_tools=True, always set code_tools_allow to the exact tool names code may call. Leaving it None exposes no tools (the safe default), so name only what the task needs — never grant blanket access.Detecting truncated runs
Detecting truncated runs
Set
max_steps and check agent.last_stop_reason == "max_steps" to detect truncation — no string-matching needed. The returned text is a real LLM-authored wrap-up (“Here’s what I accomplished… here’s what remains…”), not a placeholder. See Step Budget.Related
Where Does It Run
Ask any agent where its thinking and tools actually execute
Step Budget — cap tool-use steps and detect truncation
Output — control verbosity and response format
Step Budget — cap tool-use steps and detect truncation
Caching — avoid redundant LLM API calls

