Skip to content

Learn AI · Guides

Idempotency and Retries for LLM Workflows

How to retry failed LLM and tool calls without double-charging customers, sending duplicate emails, or corrupting agent state.

7 min readPublished Jun 2026Updated Jun 2026
AutomationAgentsProductionReliability
Edited by The AIKnowHub team · Editorial team

Key takeaways

  • 1Classify every step as read-only or mutating before writing retry logic.
  • 2Idempotency keys on mutating tools prevent duplicate charges, emails, and tickets.
  • 3LLM timeouts are ambiguous — the model may have started; use request IDs and dedupe tables.
  • 4LangGraph checkpoints let you resume mid-agent without re-running expensive steps.
  • 5Log retry count and final outcome in observability — retry storms are a smell.

Read-only vs mutating steps

Step typeRetry policy
LLM classify / extractRetry freely with backoff
Vector searchRetry freely
HTTP GETRetry with caution on large payloads
Send emailIdempotency key required
Charge cardIdempotency key required
Create ticketDedupe on business key (e.g. source event ID)
Delete recordDo not auto-retry — require human

Idempotency key pattern

def charge_refund(order_id: str, idempotency_key: str, amount: cents):
    existing = db.get_idempotent_result(idempotency_key)
    if existing:
        return existing
    result = payment_api.refund(order_id, amount, idempotency_key)
    db.store_idempotent_result(idempotency_key, result)
    return result

Pass the same key from the agent tool call. Store in your DB, not just the payment provider.

LLM timeout ambiguity

When an HTTP call times out, the model may still have completed. Mitigations:

  1. Request ID — pass provider request ID; query status if supported
  2. Dedupe table — hash (user_id, task_id, step) to stored output
  3. Checkpoint before expensive calls — LangGraph or custom state

Retry backoff

attempt 1: immediate
attempt 2: 2s + jitter
attempt 3: 4s + jitter
attempt 4: 8s + jitter
cap at 60s, max 5 attempts on 429

Route to fallback model after 2 failures on primary.

Agent checkpointing

LangGraph persists state at node boundaries. On failure, resume from last checkpoint instead of re-running retrieval and prior tool calls.

For n8n/Zapier: use execution IDs and step-level error workflows; avoid blind full-rerun on partial success.

Observability

Log in Langfuse:

  • retry_count
  • failure_reason (timeout, 429, validation, tool error)
  • idempotency_key on mutating tools
  • checkpoint_id on agent resume

Retry storms often mean rate limits too tight or prompts too large — fix root cause, not just retry count.

Common misconceptions

The wrong-but-common takes worth correcting.

Myth

Retrying the whole agent run is always safe.

Reality

If step 3 sent an email and step 5 failed, a full retry sends twice. Checkpoint or make step 3 idempotent.

Myth

LLM outputs are deterministic enough to dedupe by prompt hash.

Reality

Temperature above zero means different outputs. Dedupe on business keys, not prompt text.

Real-world use cases

Frequently asked questions

A unique client-generated ID sent with a mutating request. The server stores key to result mapping and returns the same result on duplicate submits instead of executing twice.