Retry Strategies
Some API failures are transient — a retry after a short wait will succeed. Retry strategies make agents resilient to temporary failures without flooding the API with requests.
8 min•By Priygop Team•Updated 2026
Exponential Backoff
Exponential Backoff
import time
import requests
def api_call_with_retry(
url: str,
headers: dict,
max_retries: int = 3,
initial_delay: float = 1.0
) -> dict:
"""
Call an API with exponential backoff retry.
Retries only on transient errors (5xx, timeout, network).
"""
delay = initial_delay
for attempt in range(max_retries + 1):
try:
response = requests.get(url, headers=headers, timeout=10)
if response.status_code == 200:
return {"status": "success", "data": response.json()}
if response.status_code == 429:
# Rate limited — wait for server's suggested time
retry_after = int(response.headers.get("Retry-After", delay))
print(f"Rate limited. Waiting {retry_after}s...")
time.sleep(retry_after)
continue
if 400 <= response.status_code < 500:
# Client error — do NOT retry
return {"status": "error", "error_type": "client",
"error": f"HTTP {response.status_code} — not retrying"}
# 5xx — retry with backoff
if attempt < max_retries:
print(f"Server error {response.status_code}. Retry {attempt+1}/{max_retries} in {delay:.1f}s")
time.sleep(delay)
delay *= 2 # exponential backoff: 1s, 2s, 4s...
except (requests.Timeout, requests.ConnectionError) as e:
if attempt < max_retries:
print(f"Network error. Retry {attempt+1}/{max_retries} in {delay:.1f}s")
time.sleep(delay)
delay *= 2
else:
return {"status": "error", "error_type": "network",
"error": f"Failed after {max_retries} retries: {str(e)}"}
return {"status": "error", "error_type": "max_retries",
"error": f"Gave up after {max_retries} retries"}
# Test
result = api_call_with_retry(
"https://api.example.com/data",
headers={"Authorization": "Bearer test-key"}
)
print(result["status"])