Idempotency and Error Propagation
Idempotent tool calls survive retries safely; error handling should match response severity to failure criticality.
Two related reliability concepts govern how an agentic system behaves when things go wrong or get repeated: idempotency, which governs what happens when an action runs more than once, and error propagation, which governs how a failure in one step should affect the rest of the system.
Idempotency: running twice equals running once
A tool call is idempotent if executing it multiple times produces the same end state as executing it once. This property is required for any action that might be automatically retried, whether by your own orchestration logic after a timeout, by a network layer resending a request, or by an agent itself re-attempting a step it isn't sure succeeded. If a tool call is not idempotent, an automatic retry can cause real, sometimes costly, damage: sending a duplicate notification, charging a customer's card twice, creating two identical support tickets, or double-decrementing inventory.
The design fix is not "avoid retries" — retries are essential for reliability against transient failures — but to make actions safe to retry. The standard technique is an idempotency key: a unique identifier attached to a logical operation (not to each individual HTTP attempt) so that the receiving system can recognize "I've already done this exact operation" and return the prior result instead of executing it again. Reads are naturally idempotent. Writes that use "set to value X" semantics are often naturally idempotent. Writes that use "increment by X" or "send a message" semantics are not, and need explicit guarding — an idempotency key, a check-before-act pattern, or a dedup table — before they're safe to expose to a retry-capable agent loop.
Which actions need explicit guards
Not every tool call needs this treatment equally. The judgment call is identifying which actions are non-idempotent and consequential enough to guard explicitly. Sending an email, charging a payment method, posting a public message, or triggering an irreversible external side effect are the clearest cases: these need an idempotency key or equivalent guard before they're wired into any agent that might retry automatically. A read-only lookup or a query against a cache needs no such guard, because repeating it changes nothing.
Error propagation: match response to criticality
When a step in an agent's workflow fails, the correct response depends entirely on what kind of failure it is, and a single blanket policy applied to every error is a design flaw the exam tests directly. There are three broad categories worth distinguishing. First, errors that invalidate the task entirely — a required input turns out to be malformed in a way that makes the rest of the plan meaningless — should halt execution rather than continuing on a broken premise. Second, transient errors — a rate limit, a timeout, a momentary network blip — should trigger a retry, typically with backoff, because the same call is likely to succeed shortly after. Third, non-critical errors — a supplementary lookup fails but the core task can still complete with slightly reduced quality — should trigger degrade-and-continue behavior, where the agent proceeds without that piece of information rather than stopping the whole task over it.
Applying one policy uniformly — always retry everything, or halt on any error, or silently swallow every failure — produces systems that either loop forever on unrecoverable errors, stop unnecessarily on minor hiccups, or silently produce degraded output without any signal that something went wrong.
Scenario: An agent's workflow has three steps: (1) look up a customer's account, (2) validate a discount code against a rules engine, (3) apply the discount and email the customer a confirmation. The rules engine call in step 2 times out. What should happen? Because step 2's failure is transient (a timeout, not a data problem) and step 3 depends on its result, the correct response is retry with backoff on step 2, not halt and not skip. If instead step 1 failed because the customer ID doesn't exist, that invalidates the whole task and should halt immediately — retrying it will never succeed. And if step 3's email confirmation fails after the discount was successfully applied, that's non-critical relative to the core task (the discount is applied, which is the business-critical outcome) — log the failure and degrade-and-continue rather than rolling back or halting, though the email step itself should still use an idempotency key so a retry there doesn't send two confirmations.
Try it
Pick a tool you'd expose to an agent that has a real side effect (sending a message, writing a record, charging something). Design an idempotency key for it: decide what identifies "the same logical operation" across retries (not the same HTTP request, the same intended action), where that key would be generated, and how the receiving system would check it before executing.