Skip to main content
Execution configuration controls how long an agent runs, how many times it retries, and what code it can execute.
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.
The user sends a research prompt; iteration limits, retries, and rate limits govern how long the agent runs.

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 — ExecutionConfig
Prefer 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.
The most common options at a glance:

Code-execution options

Setting code_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".
  • Unknown code_mode raises ValueError at Agent(...) construction. Only "safe" and "unsafe" are valid.
  • code_tools=True without code_mode="unsafe" emits a UserWarning. Safe mode runs in a subprocess where the agent’s tools do not exist, so code_tools_allow is ignored there.
  • timeout is only a hard guarantee in "safe" mode. In "unsafe" mode a runaway loop can block the worker — use "safe" when the timeout must be enforced.
An unknown code_mode raises ValueError at Agent construction — only "safe" and "unsafe" are valid. Setting code_tools=True without code_mode="unsafe" emits a UserWarning: safe mode runs in a subprocess where the agent’s tools do not exist, so code_tools_allow is ignored there.
ExecutionConfig(timeout=...) is a per-call timeout for execute_code only in "safe" mode (the subprocess). In "unsafe" mode there is no hard timeout — code runs in the current process, so a runaway loop can block the worker. Use code_mode="safe" when the timeout must be a hard guarantee.
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.
context_compaction currently defaults to False but will default to True in the next release. To opt in early, set context_compaction=True in your ExecutionConfig. This provides automatic protection against context window overflow.

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

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.
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.
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_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.
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.
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.

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