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

# Execution Time Caps

> Bound a chat turn or an autonomous run with max_execution_time and timeout_seconds

Cap how long one chat turn runs with `ExecutionConfig(max_execution_time=...)`, or how long a whole autonomous run takes with `run_autonomous(timeout_seconds=...)` — a timed-out turn stops at its next loop boundary and reports `last_stop_reason == "timeout"`.

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

agent = Agent(
    name="Researcher",
    instructions="Research the topic within the time budget.",
    execution=ExecutionConfig(max_execution_time=30),  # 30s per turn
)

agent.start("Summarise today's AI news.")

if agent.last_stop_reason == "timeout":
    print("Turn cut by max_execution_time")
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Start[📝 start / chat] --> Loop[⚙️ LLM + tool loop]
    Loop --> Check{⏰ Past deadline?}
    Check -->|No| Loop
    Check -->|Yes| Stop[🛑 Stop turn]
    Stop --> Report[📬 last_stop_reason = timeout]

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef stop fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class Start input
    class Loop process
    class Check decision
    class Stop stop
    class Report result
```

> [!NOTE]
>
> Shipped in [PR #6062](https://github.com/MervinPraison/PraisonAI/pull/6062). Before it, `max_execution_time` only halted at tool calls, and a `run_autonomous` turn that overran `timeout_seconds` could still finish and be reported as `"goal"`. No new parameters, and no overhead when neither cap is set.

## Quick Start

**1. Bound a single chat turn**

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

agent = Agent(
    instructions="Answer briefly.",
    execution=ExecutionConfig(max_execution_time=30),
)
agent.start("Explain quantum computing.")
print(agent.last_stop_reason)  # "completed" or "timeout"
```

**2. Bound a whole autonomous run**

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

agent = Agent(
    name="Worker",
    instructions="Complete the task autonomously.",
    autonomy=True,
)

result = agent.run_autonomous(
    "Clean up the repo and open a PR.",
    max_iterations=20,
    timeout_seconds=600,  # 10 minutes total
)

if result.completion_reason == "timeout":
    print("Run cut by the run deadline")
```

***

## Which cap do I want?

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What should be bounded?}
    Q -->|One chat turn| T[ExecutionConfig max_execution_time]
    Q -->|Whole autonomous run| R[run_autonomous timeout_seconds]
    Q -->|Both| B[Set both - the earlier deadline wins]

    classDef q fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef pick fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef both fill:#189AB4,stroke:#7C90A0,color:#fff

    class Q q
    class T,R pick
    class B both
```

| Cap | Scope | When it fires |
| - | - | - |
| `ExecutionConfig.max_execution_time` | Each chat turn (`chat()` / `start()` / `achat()` / `astart()`) | Turn stops; `agent.last_stop_reason == "timeout"` |
| `run_autonomous(timeout_seconds=...)` | The whole autonomous run (sync and async) | Returns `AutonomyResult(completion_reason="timeout", success=False)` |

They compose: with `timeout_seconds=600` and `max_execution_time=120`, any single turn stops after 2 minutes and the whole run after 10. In an autonomous run, a turn cut by `max_execution_time` is also reported as `completion_reason="timeout"`.

***

## What a timeout stops

| In flight when the deadline passes | Behaviour |
| - | - |
| An LLM request | Not interrupted mid-request — the turn stops at the next loop boundary after it returns |
| The step between tool calls | Stops at the next boundary |
| A Python tool that is running | **Not** interrupted — bound it with [`ToolConfig(timeout=...)`](https://praison.ai/docs/features/tool-timeout) |
| The autonomous loop between turns | The next turn only gets the time that remains |

> [!NOTE]
>
> The deadline is checked at loop boundaries, not inside running code. Pair `max_execution_time` with `tool_config=ToolConfig(timeout=...)` on slow tools, and with an [LLM timeout](https://praison.ai/docs/features/llm-timeouts.md) on slow providers, to keep the overall cap tight.

***

## Best Practices

> [accordion] Branch on the stop reason, not the text
>
> Check `agent.last_stop_reason == "timeout"` or `result.completion_reason == "timeout"` instead of parsing the reply. See [Agent Run Outcomes](https://praison.ai/docs/features/agent-run-outcomes.md) for every stop reason.

> [accordion] Leave headroom for wrap-up
>
> A turn stops at the next boundary, so actual elapsed time can run past the cap by one LLM call or tool call. Set the cap a little below your hard limit.

***

## Related

> [card] [Execution](https://praison.ai/docs/features/execution.md)
>
> Full `ExecutionConfig` overview

> [card] [Loop Guard](https://praison.ai/docs/features/loop-guard.md)
>
> Tool-boundary halt that also reads `max_execution_time`

> [card] [LLM Timeouts](https://praison.ai/docs/features/llm-timeouts.md)
>
> Per-request timeout on each LLM call

> [card] [Autonomy Loop](https://praison.ai/docs/features/autonomy-loop.md)
>
> `run_autonomous` iterations and completion reasons


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.