Back to blog

Building Production-Grade AI Agents · Part 7 of 15

Reliability: Idempotency, Retries, and Partial Failure

Agentic systems inherit every distributed-systems failure mode—plus a probabilistic decision-maker on top.

Chris Eberl

Chris Eberl

Founder • Engineering Leader, GenAI, Data, ML

Production AI AgentsSep 14, 20266 min read
Reliability: Idempotency, Retries, and Partial Failure

The question to ask about every side-effecting tool is brutally simple: what happens if it executes zero times, once, twice, or halfway? If the answer is unclear, the tool is not ready for production.

Models do not remove distributed-systems uncertainty. They make it easier to generate actions, which means retries, ambiguous timeouts, duplicate side effects, and partial failures matter even more.

Tool retry is not model retry

A transient 503 from a downstream service should normally be handled in the deterministic tool/runtime layer. There is no reason to ask the model to rediscover that it should retry a network request. By contrast, a semantic result such as “tracking number not found” may genuinely require model reasoning about what to do next.

Idempotency is the default for writes

Any side-effecting tool should be idempotent or sit behind an idempotent service. The client generates or reuses a stable operation ID. If a timeout occurs, the system can retry without creating a second refund, a second ticket, or a duplicate CRM update.

System flow
1operation_id = 8f1c...2        ↓3write request4        ↓5timeout6        ↓7retry with SAME operation_id8        ↓9backend returns original result

Timeout does not mean failure

If a downstream call times out, the true state may be success, failure, or unknown. A robust system represents UNKNOWN explicitly and tries to reconcile against authoritative state. Blindly converting timeout to FAILED is how duplicate side effects happen.

Exactly once is usually a contract, not a wish

If the downstream system supports an idempotency key or a queryable operation status, safe retry is straightforward. If it supports neither, you may have to choose between at-most-once delivery (duplicates avoided, work may be lost) and at-least-once delivery (work eventually happens, duplicates possible unless the consumer deduplicates). Do not claim exactly-once semantics without the primitives to implement them.

Partial failure should be reported precisely

Suppose Salesforce updates successfully but Slack notification fails. Do not roll back the CRM simply because notification failed, and do not tell the user the entire operation failed. Preserve the successful state, retry the notification according to policy, then report exactly what succeeded and what did not.

PFPLabs takeaways

  • Make write tools idempotent.
  • Represent ambiguous outcomes as UNKNOWN, not FAILED.
  • Retry transient infrastructure failures below the model layer.
  • Treat partial success as a first-class state. Truthful user experience depends on authoritative backend state.

Further reading

AWS Step Functions: Handling errors and retriesAWS Step Functions and EventBridge integration

Read next

Newsletter

New posts, straight from Chris

A short note from me whenever a new article goes live — product engineering, AI workflows, IoT, indie apps, and engineering leadership. No spam, unsubscribe anytime.

By subscribing, you agree to our Privacy Policy. We do not share your email.