> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# ExecutionConfig

> Configure agent execution limits including iterations, rate limits, and timeouts

Control agent execution behavior with limits on iterations, rate limiting, timeouts, and retries.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Execution Limits"
        A[⚡ Start] --> B{Check Limits}
        B -->|OK| C[🔄 Execute]
        C --> B
        B -->|Limit| D[🛑 Stop]
    end
    
    classDef start fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef check fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef execute fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef stop fill:#10B981,stroke:#7C90A0,color:#fff
    
    class A start
    class B check
    class C execute
    class D stop
```

## Quick Start

<Steps>
  <Step title="Using Presets">
    Use string presets for common configurations:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent

    # Fast execution (fewer iterations)
    agent = Agent(
        name="Fast Agent",
        instructions="Quick tasks",
        execution="fast"
    )

    # Thorough execution (more iterations)
    agent = Agent(
        name="Thorough Agent",
        instructions="Complex analysis",
        execution="thorough"
    )
    ```
  </Step>

  <Step title="With Configuration">
    Fine-grained control:

    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent
    from praisonaiagents.config import ExecutionConfig

    agent = Agent(
        name="Custom Agent",
        instructions="Custom execution limits",
        execution=ExecutionConfig(
            max_iter=50,
            max_rpm=100,
            max_execution_time=300,
            max_retry_limit=5,
            max_tool_calls_per_turn=10
        )
    )
    ```
  </Step>
</Steps>

***

## Configuration Options

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.config import ExecutionConfig

config = ExecutionConfig(
    # Iteration limits
    max_iter=20,
    
    # Rate limiting (requests per minute)
    max_rpm=None,
    
    # Time limits (seconds)
    max_execution_time=None,
    
    # Retry settings
    max_retry_limit=2,
    
    # Tool call limits (loop protection)
    max_tool_calls_per_turn=10
)
```

| Parameter                 | Type                              | Default  | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ------------------------- | --------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `max_iter`                | `int`                             | `20`     | Maximum tool-calling iterations. Now propagated to the `LLM` instance, so it controls every internal loop (previously some loops were hardcoded to 5/10/20/50). Both the `ExecutionConfig` default and the `LLM`-direct-construction default are `20` (aligned as of PR #1898). When the loop reaches this cap, the agent performs one bounded LLM call with tools disabled to synthesise a wrap-up summary instead of returning the old `"Task completed."` placeholder (as of PR #2577). |
| `max_rpm`                 | `int \| None`                     | `None`   | Max requests per minute (rate limit)                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `max_execution_time`      | `int \| None`                     | `None`   | Max execution time in seconds                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `max_retry_limit`         | `int`                             | `2`      | Max retries for retryable tool failures and guardrail validation failures. Total attempts = `1 + max_retry_limit`. Retries use exponential backoff with jitter (see `retry_initial_delay`, `retry_backoff_factor`, `retry_jitter`).                                                                                                                                                                                                                                                        |
| `retry_initial_delay`     | `float`                           | `1.0`    | First retry delay in seconds. Subsequent delays grow exponentially. Must be `> 0`.                                                                                                                                                                                                                                                                                                                                                                                                         |
| `retry_backoff_factor`    | `float`                           | `2.0`    | Multiplier applied each attempt (`base = initial × factor^(attempt−1)`). Must be `>= 1.0`.                                                                                                                                                                                                                                                                                                                                                                                                 |
| `retry_jitter`            | `float`                           | `0.1`    | Random jitter added as a fraction of the base delay. Must be `>= 0`.                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `max_tool_calls_per_turn` | `int`                             | `10`     | Maximum tool calls allowed in a single chat turn. When exceeded, execution stops with a clear message instead of looping forever.                                                                                                                                                                                                                                                                                                                                                          |
| `context_compaction`      | `bool \| ContextCompactionPolicy` | `False`  | Proactive context-overflow protection. `True` uses the `BALANCED_POLICY` preset. Pass a `ContextCompactionPolicy` instance for custom routing. **Default flips to `True` in the next release** — a `DeprecationWarning` is emitted today when left at `False`. See [Context Compaction Policy](/features/context-compaction-policy).                                                                                                                                                       |
| `max_budget`              | `float \| None`                   | `None`   | Hard USD cap per agent run. `None` = no limit.                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `on_budget_exceeded`      | `str \| callable`                 | `"stop"` | Action when limit is hit after an LLM call returns. `"stop"` raises `BudgetExceededError`. `"warn"` logs a warning and continues. `callable(total_cost, max_budget)` is invoked; return value is ignored.                                                                                                                                                                                                                                                                                  |

<Note>
  For budget limits, use `execution=ExecutionConfig(max_budget=...)` on your Agent. See [Agent max\_budget](/docs/features/agent-max-budget) for details.

  These retry settings apply to both tool execution and guardrail validation retries.
</Note>

<Warning>
  Invalid values raise `ValueError`: `retry_initial_delay` must be `> 0`, `retry_backoff_factor` must be `>= 1.0`, `retry_jitter` must be `>= 0`.
</Warning>

***

## Execution Presets

| Preset        | max\_iter | Description                    |
| ------------- | --------- | ------------------------------ |
| `"fast"`      | 10        | Quick tasks, fewer iterations  |
| `"balanced"`  | 20        | Default, balanced approach     |
| `"thorough"`  | 50        | Complex tasks, more iterations |
| `"unlimited"` | 1000      | Long-running tasks             |

***

## Iteration Propagation

`ExecutionConfig.max_iter` is now the single source of truth for iteration limits, replacing previously hardcoded internal caps.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Unified Iteration Control"
        Config[📋 ExecutionConfig.max_iter] --> Agent[🤖 Agent]
        Agent --> LLM[⚙️ LLM]
        LLM --> Loops[🔄 All Internal Tool Loops]
    end
    
    classDef config fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff
    
    class Config config
    class Agent,LLM process
    class Loops output
```

**Before**: Internal LLM loops were hardcoded to different limits (5, 10, 20, 50)
**After**: All loops respect the configured `max_iter` value

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonaiagents.config import ExecutionConfig

# This now controls ALL iteration loops, not just agent-level loops
agent = Agent(
    name="Unified Control",
    instructions="Respect iteration limits everywhere",
    execution=ExecutionConfig(max_iter=15)
)
# The agent's LLM will respect 15 iterations in all internal loops
```

### When the limit is reached

When the tool-calling loop reaches `max_iter`, the agent performs one final LLM call with `tool_choice="none"` and every advertised tool stripped, asking the model to summarise **what it accomplished, what remains unfinished, and any suggested next steps** using the tool results already in context. That synthesised text becomes the final answer.

The extra call is bounded to exactly one non-tool completion and is routed through the same retry / failover wrappers as every other completion, so a transient rate-limit error doesn't drop straight to a placeholder. If the call still fails, the agent falls back to the last-turn text, then to `"Reached the step limit before finishing this task."` — behaviour never regresses.

There is no opt-out. To avoid truncation, increase `max_iter` so the agent can finish normally.

***

## Tool Retry & Exponential Backoff

Tool and guardrail retries use exponential backoff with jitter so transient failures recover without hammering APIs.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Agent
    participant Tool
    Agent->>Tool: Call
    Tool-->>Agent: Retryable failure
    Note over Agent: wait delay₁ (~1.0s)
    Agent->>Tool: Retry
    Tool-->>Agent: Retryable failure
    Note over Agent: wait delay₂ (~2.0s)
    Agent->>Tool: Retry
    Tool-->>Agent: Success
```

Delay formula: `delay = min(initial_delay × factor^(attempt−1), 60s) + random(0, jitter × base)`.

With defaults (`retry_initial_delay=1.0`, `retry_backoff_factor=2.0`), three retries wait roughly **1.0s**, **2.0s**, **4.0s** (plus up to 10% jitter).

See [Tool Retry & Backoff](/docs/features/tool-retry-backoff) for retry classification and patterns.

***

## Proactive Context Compaction

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Context Protection Flow"
        Config[📋 ExecutionConfig] --> Policy[🛡️ Policy]
        Policy --> Routes[📊 Routes]
        Routes --> LLM[🤖 LLM Call]
    end
    
    classDef config fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff
    
    class Config config
    class Policy,Routes process
    class LLM output
```

Context compaction proactively prevents overflow before LLM calls instead of reacting after errors.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, ExecutionConfig, BALANCED_POLICY

agent = Agent(
    name="Researcher",
    execution=ExecutionConfig(
        max_iter=30,
        context_compaction=BALANCED_POLICY,  # explicit preset
    ),
)
```

See [Context Compaction Policy](/features/context-compaction-policy) for detailed configuration options.

***

## Common Patterns

### Pattern 1: Rate-Limited Agent

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonaiagents.config import ExecutionConfig

agent = Agent(
    name="Rate Limited Agent",
    instructions="Respect API limits",
    execution=ExecutionConfig(
        max_rpm=60,  # 60 requests per minute
        max_retry_limit=3
    )
)
```

### Pattern 2: Time-Bounded Agent

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonaiagents.config import ExecutionConfig

agent = Agent(
    name="Timed Agent",
    instructions="Complete within time limit",
    execution=ExecutionConfig(
        max_execution_time=60,  # 60 seconds max
        max_iter=100
    )
)
```

### Pattern 3: Resilient Agent

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonaiagents.config import ExecutionConfig

agent = Agent(
    name="Resilient Agent",
    instructions="Handle failures gracefully",
    execution=ExecutionConfig(
        max_retry_limit=5,
        retry_initial_delay=0.5,
        retry_backoff_factor=2.0,
        retry_jitter=0.2,
    )
)
```

### Pattern 4: Loop-Protected Agent

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent
from praisonaiagents.config import ExecutionConfig

agent = Agent(
    name="Protected Agent",
    instructions="Agent with experimental tools",
    execution=ExecutionConfig(
        max_tool_calls_per_turn=5,  # Lower limit for potentially noisy tools
        max_iter=20
    )
)
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Set Iteration Limits">
    Always set `max_iter` to prevent runaway agents consuming resources.
  </Accordion>

  <Accordion title="Use Rate Limiting for APIs">
    Set `max_rpm` when calling external APIs to avoid rate limit errors.
  </Accordion>

  <Accordion title="Set Timeouts for Production">
    Use `max_execution_time` in production to prevent hung processes.
  </Accordion>

  <Accordion title="Configure Loop Protection">
    Adjust `max_tool_calls_per_turn` based on your tools: lower for experimental tools (3-5), higher for complex multi-tool workflows (20-30).
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Context Compaction Policy" icon="shield-check" href="/docs/features/context-compaction-policy">
    Proactive context overflow protection
  </Card>

  <Card title="LLM Error Classification" icon="circle-alert" href="/docs/features/llm-error-classification">
    Iteration control and error handling integration
  </Card>

  <Card title="Async Execution" icon="clock" href="/docs/features/async">
    Async agent execution
  </Card>

  <Card title="Background Tasks" icon="list-check" href="/docs/features/background-tasks">
    Run agents in background
  </Card>

  <Card title="Structured LLM Errors" icon="circle-alert" href="/docs/features/structured-llm-errors">
    LLM error handling and retry policies
  </Card>

  <Card title="Tool Retry & Backoff" icon="rotate" href="/docs/features/tool-retry-backoff">
    Exponential backoff for tool and guardrail retries
  </Card>
</CardGroup>
