Retry Logic
Retry logic automatically re-executes a failed step after a delay. Good retry logic uses exponential backoff, respects rate limits, and has a hard maximum retry count.
8 min•By Priygop Team•Updated 2026
Complete Retry Implementation
Complete Retry Implementation
import time
import random
def retry_with_backoff(
fn,
args: dict,
max_retries: int = 3,
base_delay: float = 1.0,
jitter: bool = True,
retryable_errors: set = None
) -> dict:
"""
Execute a function with exponential backoff retry.
jitter: adds random delay to prevent all agents retrying at the same time
retryable_errors: set of error types that should be retried
"""
retryable = retryable_errors or {"timeout", "network", "server", "rate_limit"}
last_error = None
for attempt in range(max_retries + 1):
try:
result = fn(**args)
# Check if the tool itself returned an error
if isinstance(result, dict) and result.get("status") == "error":
error_type = result.get("error_type", "unknown")
if error_type not in retryable:
# Non-retryable error — return immediately
print(f" Non-retryable error ({error_type}) — giving up")
return result
if attempt < max_retries:
delay = base_delay * (2 ** attempt)
if jitter:
delay += random.uniform(0, delay * 0.1) # ±10% jitter
print(f" Retryable error ({error_type}). Attempt {attempt+1}/{max_retries}. Waiting {delay:.1f}s")
time.sleep(delay)
last_error = result
continue
return result # Success
except Exception as e:
if attempt < max_retries:
delay = base_delay * (2 ** attempt)
print(f" Exception: {e}. Retry {attempt+1}/{max_retries} in {delay:.1f}s")
time.sleep(delay)
last_error = {"status": "error", "error_type": "exception", "error": str(e)}
else:
return {"status": "error", "error_type": "exception", "error": str(e)}
return last_error or {"status": "error", "error": "Max retries exceeded"}
# Example: a flaky tool that fails the first 2 times
call_count = [0]
def flaky_tool(query: str) -> dict:
call_count[0] += 1
if call_count[0] < 3:
return {"status": "error", "error_type": "timeout", "error": "Timed out"}
return {"status": "success", "result": f"Results for: {query}"}
result = retry_with_backoff(flaky_tool, {"query": "Python frameworks"}, max_retries=3, base_delay=0.1)
print(f"Final: {result['status']} (took {call_count[0]} attempts)")