Idempotency is the critical boundary condition for retries. Retrying non-mutating search or schema validation queries is completely safe, but retrying state-changing operations like API payments or database migrations without transactional rollback guarantees risks duplicate side effects.
When should an AI agent be allowed to retry?
11 Comments
I'd stop a retry the moment the agent changes the arguments. The same call with the same arguments after a 503, or a 429 with Retry-After, is a retry. A rewritten query, a different recipient or a bigger amount after a 400 or 403 is a new action, and it should go back through the same permission check as the first attempt instead of spending the retry budget.
The other stop is a write that timed out. RFC 9110 already sets the rule: no automatic retry of a non-idempotent request unless the client knows it's idempotent or can detect that the original was never applied. For an agent, that means the next step after a payment POST goes quiet is a read that checks whether it landed, or a resend under the same idempotency key, never a fresh call.
Please log in to add a comment.
I keep one retry budget shared across every layer. If the HTTP client already retries and the agent loop retries on top of it, one bad call multiplies quietly and the limit you wrote down stops being the real one. For the recovery signal, an identical error body on consecutive attempts tells me nothing upstream has changed, so that's where I stop.
Please log in to add a comment.
Great article! I think retry logic is one of the most important parts of building reliable AI agents. Retrying can help recover from temporary failures, but without proper limits, it can also waste resources and create unexpected problems. I especially like the idea of making retries depend on the type of failure rather than treating every error the same way. How would you handle retries when an agent is performing an action that cannot easily be reversed.
Please log in to add a comment.
I figured actual code might be useful here.
import os
import time
from tenacity import (
retry,
stop_after_attempt,
wait_exponential,
retry_if_exception_type,
before_sleep_log
)
import logging
import openai
from openai import RateLimitError, APIConnectionError, InternalServerError
# Optional: Set up basic logging so you can see the retries happening in your console
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Initialize the LLM client
# Ensure you have your environment variable set: export OPENAI_API_KEY="sk-..."
client = openai.OpenAI(api_key=os.environ.get("OPENAI_API_KEY", "your_dummy_key_here"))
# Configure the robust retry decorator:
# 1. retry_if_exception_type: ONLY retries on transient network errors or rate limits.
# (It will immediately fail on AuthenticationError or BadRequestError so you don't waste time/money).
# 2. wait_exponential: Waits 2^x * 1 second between retries (e.g., 2s, 4s, 8s...). Max wait is 10s.
# 3. stop_after_attempt: Gives up completely after 5 tries to prevent infinite loops.
# 4. reraise=True: If it fails 5 times, it throws the actual LLM error rather than a Tenacity error.
@retry(
retry=retry_if_exception_type((RateLimitError, APIConnectionError, InternalServerError)),
wait=wait_exponential(multiplier=1, min=2, max=10),
stop=stop_after_attempt(5),
before_sleep=before_sleep_log(logger, logging.WARNING),
reraise=True
)
def generate_text_with_retry(prompt: str, model: str = "gpt-3.5-turbo") -> str:
print(f"\n[Action] Sending prompt to {model}...")
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
timeout=15.0 # Always set a timeout so hanging requests trigger the retry!
)
return response.choices[0].message.content
if __name__ == "__main__":
user_prompt = "Explain the importance of exponential backoff in API calls."
try:
# Call the decorated function exactly as you normally would
result = generate_text_with_retry(user_prompt)
print("\n✅ Success! LLM Response:")
print(result)
except Exception as e:
# If it reaches here, it either hit an unrecoverable error (like a bad API key)
# OR it failed 5 times in a row due to rate limits.
print(f"\n❌ Operation failed. Final error: {e}")
Please log in to add a comment.
Please log in to comment on this post.
More Posts
- © 2026 Coder Legion
- Feedback / Bug
- Privacy
- About Us
- Contacts
- You Tube
- Tiktok
- Premium Subscription
- Terms of Service
- Early Builders
Currently a Staff Software Engineer at Walmart Inc. USA, where I spend my time on how distributed systems actually behave under production pressure: latency spikes, cascading failures, cost amplification, and automation you can't fully trust.
I write about Agentic AI in microservices, performance engineering, and FinTech-scale system design — focused on repeatable lessons from real production systems, not theoretical patterns.
19+ years across Walmart, IBM, and AT&T platforms. Show less
More From sibasispadhi
Related Jobs
- Technical Engineering Lead (Runtime Agent)Sysdig · Full time · Italian Republic
- Ontology Agentic Software EngineerLockheed Martin · Full time · Puerto Rico
- Spanish Educational Video Scriptwriter / Instructional Content DeveloperIdlewild Co · Full time · Charleston, WV
Commenters (This Week)
Contribute meaningful comments to climb the leaderboard and earn badges!