# How to Configure ModelRetrySettings and Custom Retry Policies in openai-agents-python

> Learn to configure ModelRetrySettings and custom retry policies in openai-agents-python. Control failed model calls with max retries, backoff, and custom policies.

- Repository: [OpenAI/openai-agents-python](https://github.com/openai/openai-agents-python)
- Tags: how-to-guide
- Published: 2026-04-17

---

**Configure `ModelRetrySettings` with `max_retries`, `backoff`, and a custom `policy` callback to control how the OpenAI Agents Python SDK handles failed model calls.**

The `openai-agents-python` SDK provides a declarative retry system that lets you define both the timing and the logic for re-attempting failed model requests. Understanding how to configure `ModelRetrySettings` and implement custom retry policies ensures your agents remain resilient against transient failures without overwhelming the API.

## Understanding the Retry Architecture

The retry system operates in two distinct layers orchestrated by the runner.

### Runner-Managed Retry Settings

The first layer defines *how many* retries occur and the *back-off* timing between attempts. This is configured via `ModelRetrySettings` in [`src/agents/retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/retry.py), which supports an optional `policy` callback that determines *if* a retry should be performed at all.

### Policy Evaluation Layer

The second layer provides the decision logic. The runtime evaluates errors—examining status codes, `Retry-After` headers, network failures, and provider-suggested advice—to return a `RetryDecision`. This logic resides in [`src/agents/retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/retry.py) and is applied at runtime in [`src/agents/run_internal/model_retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/run_internal/model_retry.py).

## Configuring ModelRetrySettings

`ModelRetrySettings` accepts three key parameters that control retry behavior.

| Field | Type | Description | Default |
|-------|------|-------------|---------|
| `max_retries` | `int \| None` | Additional attempts after the initial request. `None` means no limit. | `None` |
| `backoff` | `ModelRetryBackoffSettings \| dict \| None` | Controls delay between retries when the policy does not supply an explicit `delay`. | `None` (SDK defaults: 0.25s initial, 2s max, multiplier 2, jitter True) |
| `policy` | `Callable[[RetryPolicyContext], bool \| RetryDecision]` | User-defined callback inspecting the error and deciding whether to retry. Runtime-only, not serialized. | `None` |

### Fine-Tuning Backoff Behavior

Use `ModelRetryBackoffSettings` to customize exponential back-off parameters.

```python
from agents import ModelRetryBackoffSettings

backoff = ModelRetryBackoffSettings(
    initial_delay=0.5,   # seconds before first retry

    max_delay=5.0,       # ceiling for the delay

    multiplier=2.0,      # exponential factor

    jitter=True,         # random ±25% jitter

)

```

Implementation reference: [`src/agents/retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/retry.py) lines 15-31 and the `to_json_dict` helper.

## Using Built-in Retry Policies

The SDK provides a `retry_policies` DSL in [`src/agents/retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/retry.py) for constructing composable policies without writing custom logic.

| Policy | Description |
|--------|-------------|
| `never()` | Never retry failed requests. |
| `provider_suggested()` | Follow the provider's `ModelRetryAdvice` (e.g., `x-should-retry` header). |
| `network_error()` | Match network-level failures (`APIConnectionError`, `APITimeoutError`, etc.). |
| `retry_after()` | Respect `Retry-After` headers or provider advice delays. |
| `http_status(codes)` | Target specific HTTP status codes (e.g., 429, 503). |
| `any(*policies)` | Succeed if any policy indicates retry (short-circuit). |
| `all(*policies)` | Require all policies to agree on retrying. |

### Combining Multiple Policies

Use `retry_policies.any()` to create a fallback chain that checks multiple conditions.

```python
from agents import ModelRetrySettings, retry_policies

retry = ModelRetrySettings(
    max_retries=3,
    policy=retry_policies.any(
        retry_policies.provider_suggested(),
        retry_policies.retry_after(),
        retry_policies.network_error(),
        retry_policies.http_status([408, 409, 429, 500, 502, 503, 504]),
    ),
)

```

Reference: `retry_policies` DSL implementation in [`src/agents/retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/retry.py) lines 31-60.

## Implementing Custom Retry Policies

For fine-grained control, implement a custom policy callback that receives a `RetryPolicyContext` and returns a `bool` or `RetryDecision`.

### Understanding the Policy Context

The `RetryPolicyContext` provides rich information about the failure:

- `normalized`: A `ModelRetryNormalizedError` with boolean flags like `is_timeout`, `is_network_error`, `is_rate_limit`.
- `attempt`: The current retry attempt number.
- `provider_advice`: Optional `ModelRetryAdvice` from the provider (e.g., `retry_after` seconds).
- `http_status`: The HTTP status code if applicable.

### Writing a Custom Policy

```python
from agents import ModelRetrySettings, RetryDecision, RetryPolicyContext

def timeout_only_policy(context: RetryPolicyContext) -> RetryDecision:
    """Only retry on timeout errors with a fixed 2-second delay."""
    if context.normalized.is_timeout:
        return RetryDecision(retry=True, delay=2.0, reason="timeout")
    return RetryDecision(retry=False, reason="non-timeout")

retry = ModelRetrySettings(
    max_retries=5,
    policy=timeout_only_policy,
)

```

### Supporting Async Policies

The runner automatically detects async callbacks in `_call_retry_policy` ([`src/agents/run_internal/model_retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/run_internal/model_retry.py) lines 51-58). You can use `async def` for policies that require asynchronous operations (e.g., fetching dynamic back-off values from an external service).

```python
async def async_policy(context: RetryPolicyContext) -> RetryDecision:
    # Perform async work here if needed

    if context.attempt > 3:
        return RetryDecision(retry=False, reason="Too many attempts")
    return RetryDecision(retry=True, delay=1.0)

```

## Complete Configuration Example

Combine built-in policies with a custom wrapper to enforce application-specific constraints.

```python
from agents import (
    ModelRetrySettings,
    RetryDecision,
    retry_policies,
    ModelSettings,
    RunConfig,
)

# 1. Combine built-in policies

base_policy = retry_policies.any(
    retry_policies.provider_suggested(),
    retry_policies.retry_after(),
    retry_policies.network_error(),
    retry_policies.http_status([408, 409, 429, 500, 502, 503, 504]),
)

# 2. Wrap with custom logic to cap delays and log attempts

async def policy_wrapper(context):
    raw = base_policy(context)
    decision = await raw if hasattr(raw, "__await__") else raw
    
    if isinstance(decision, RetryDecision) and decision.delay:
        # Cap backoff at 4 seconds

        decision.delay = min(decision.delay, 4.0)
        print(f"Retry {context.attempt}: waiting {decision.delay}s due to {decision.reason}")
    return decision

# 3. Configure settings

retry_cfg = ModelRetrySettings(
    max_retries=4,
    backoff={"initial_delay": 0.5, "max_delay": 5.0, "multiplier": 2.0, "jitter": True},
    policy=policy_wrapper,
)

run_config = RunConfig(model_settings=ModelSettings(retry=retry_cfg))

```

Apply `retry_cfg` globally via `RunConfig` or override per-agent via `Agent.model_settings`. The SDK merges configurations with per-agent values taking precedence.

Reference implementation: [`examples/basic/retry.py`](https://github.com/openai/openai-agents-python/blob/main/examples/basic/retry.py) lines 21-84.

## Runtime Implementation

When executing model requests, `get_response_with_retry` and `stream_response_with_retry` in [`src/agents/run_internal/model_retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/run_internal/model_retry.py) orchestrate the retry flow:

1. **Initial Request**: Calls the model with provider-managed retries disabled when necessary.
2. **Error Analysis**: On exception, builds a `ModelRetryAdviceRequest` and queries the model adapter for provider-specific advice.
3. **Policy Evaluation**: Invokes `_evaluate_retry` which normalizes the error (`ModelRetryNormalizedError`), applies the user's `policy`, and falls back to default back-off (`_default_retry_delay`).
4. **State Reset**: If retrying, rewinds conversation state and sleeps for the computed delay before re-attempting.

See the core loop around lines 31-71 in [`src/agents/run_internal/model_retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/run_internal/model_retry.py).

## Summary

- **ModelRetrySettings** controls retry count, back-off timing, and policy logic in [`src/agents/retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/retry.py).
- **Built-in policies** via `retry_policies` provide declarative matching for network errors, HTTP statuses, provider advice, and `Retry-After` headers.
- **Custom policies** receive `RetryPolicyContext` and return `bool` or `RetryDecision`, supporting both sync and async implementations.
- **Configuration hierarchy** applies settings via `RunConfig` for global defaults or `Agent.model_settings` for per-agent overrides.
- **Runtime** execution occurs in [`src/agents/run_internal/model_retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/run_internal/model_retry.py), which normalizes errors and applies your policy before each retry attempt.

## Frequently Asked Questions

### What is the default retry behavior if I don't configure ModelRetrySettings?

If you do not provide `ModelRetrySettings`, the SDK uses an unlimited retry count (`max_retries=None`) with default back-off parameters (0.25s initial delay, 2s maximum, multiplier of 2, and jitter enabled). The default policy defers to the provider's suggestion via `retry_policies.provider_suggested()`, falling back to standard back-off for rate limits and transient errors.

### How do I disable retries entirely for a specific agent?

Pass `ModelRetrySettings` with `max_retries=0` and `policy=retry_policies.never()` to ensure the runner makes only a single attempt. Attach this to the agent's `model_settings` parameter: `Agent(..., model_settings=ModelSettings(retry=ModelRetrySettings(max_retries=0, policy=retry_policies.never())))`.

### Can I use async functions for custom retry policies?

Yes, the runner automatically detects async callbacks in `_call_retry_policy` within [`src/agents/run_internal/model_retry.py`](https://github.com/openai/openai-agents-python/blob/main/src/agents/run_internal/model_retry.py) (lines 51-58). You can define `async def my_policy(context: RetryPolicyContext) -> RetryDecision` to perform asynchronous operations like fetching dynamic back-off values from external configuration services.

### Where can I find working examples of retry configuration?

The repository includes a complete runnable example at [`examples/basic/retry.py`](https://github.com/openai/openai-agents-python/blob/main/examples/basic/retry.py) (lines 21-84). This script demonstrates combining multiple built-in policies with `retry_policies.any()`, overriding back-off values via dictionary syntax, and logging each retry attempt. Additionally, the reference documentation in [`docs/ref/retry.md`](https://github.com/openai/openai-agents-python/blob/main/docs/ref/retry.md) provides auto-generated API details for all retry-related classes.