Skip to content

Retry Strategies

Model providers occasionally encounter errors such as rate limits, service unavailability, or network timeouts. By default, the agent retries throttled responses automatically with exponential backoff. The Agent.retry_strategyAgent.retryStrategy parameter lets you customize this behavior.

Without configuration, agents retry throttling errors up to 5 times (6 total attempts) with exponential backoff starting at 4 seconds:

Attempt 1: fails → wait 4s
Attempt 2: fails → wait 8s
Attempt 3: fails → wait 16s
Attempt 4: fails → wait 32s
Attempt 5: fails → wait 64s
Attempt 6: fails → exception raised

To adjust retry parameters, pass a configured strategy to the agent constructor.

from strands import Agent, ModelRetryStrategy
agent = Agent(
retry_strategy=ModelRetryStrategy(
max_attempts=3, # Total attempts (including first try)
initial_delay=2, # Seconds before first retry
max_delay=60 # Cap on backoff delay
)
)
ParameterTypeDefaultDescription
max_attemptsint6Total number of attempts including the initial call. Set to 1 to disable retries.
initial_delayfloat4Seconds to wait before the first retry. Subsequent retries double this value.
max_delayfloat128Maximum seconds to wait between retries. Caps the exponential growth.

In TypeScript, the delay between retries is delegated to a BackoffStrategy passed via the backoff parameter. The Python SDK does not expose a separate backoff interface; configure exponential backoff through the initial_delay and max_delay parameters above.

Configure backoff through ModelRetryStrategy parameters in Customizing Retry Behavior.

To disable automatic retries entirely:

from strands import Agent
agent = Agent(
retry_strategy=None
)

Default retry strategies handle throttling errors (ModelThrottledExceptionModelThrottledError) raised by model providers for rate-limiting. Other exceptions propagate immediately without retry.

To extend or narrow the retryable set, see Custom Retry Logic.

For more control over retry decisions, such as validating model responses or handling additional error types, two paths are available:

  1. Subclass the retry strategy class to own the full decision shape and reuse hook plumbing.
  2. Use a hook on AfterModelCallEvent to set event.retry = true directly.

To extend or narrow which errors are retryable, subclass ModelRetryStrategy and override is_retryable. The default implementation retries ModelThrottledException only; super().is_retryable(exception) preserves that base behavior so you can opt additional error types in (or specific ones out) without reimplementing the rest of the retry policy.

from strands import Agent, ModelRetryStrategy
from strands.types.exceptions import ModelThrottledException
class MyRetryStrategy(ModelRetryStrategy):
def is_retryable(self, exception: Exception) -> bool:
return super().is_retryable(exception) or isinstance(exception, TimeoutError)
agent = Agent(
retry_strategy=MyRetryStrategy(max_attempts=4, initial_delay=2, max_delay=60)
)

A retry-strategy instance carries per-turn state and must not be shared across agents. Create a new instance per agent.

Hooks are simpler when you only need to inspect a model error and request a retry. Set event.retry = true from an AfterModelCallEvent callback. Hooks do not introduce delays automatically; the example below adds a 2-second wait.

import asyncio
from strands import Agent
from strands.hooks import HookProvider, HookRegistry, AfterModelCallEvent
class CustomRetry(HookProvider):
def __init__(self, max_retries: int = 3, delay: float = 2.0):
self.max_retries = max_retries
self.delay = delay
self.attempts = 0
def register_hooks(self, registry: HookRegistry) -> None:
registry.add_callback(AfterModelCallEvent, self.maybe_retry)
async def maybe_retry(self, event: AfterModelCallEvent) -> None:
if event.exception and self.attempts < self.max_retries:
self.attempts += 1
await asyncio.sleep(self.delay)
event.retry = True
agent = Agent(hooks=[CustomRetry()])

See Hooks for more examples.