The mechanism
A timeout does not tell you whether an operation happened. The server may have committed a change before the response was lost. Retrying the same request without an idempotency design can create duplicate notes, payments or deployments. Agent loops amplify this problem because a model may independently decide to repeat a tool call after seeing an ambiguous error.
Idempotency means repeated requests for the same intended operation produce one effective business change. It is usually implemented at the service boundary with a stable request key, a stored outcome and an atomic transaction. A Python set inside one worker is useful for a teaching exercise but cannot provide durable guarantees across crashes and replicas.
A worked local simulation
Offline, standard library only. This in-memory example illustrates key reuse and payload consistency. It deliberately does not claim crash safety or multi-process correctness.
import hashlib
import json
completed = {}
notes = []
def append_note(request_key, incident_id, text):
payload = {"incident_id": incident_id, "text": text}
digest = hashlib.sha256(json.dumps(payload, sort_keys=True).encode()).hexdigest()
if request_key in completed:
prior_digest, prior_result = completed[request_key]
if prior_digest != digest:
raise ValueError("Idempotency key reused with different intent")
return prior_result
notes.append(payload)
result = {"note_number": len(notes), "outcome": "recorded"}
completed[request_key] = (digest, result)
return result
first = append_note("request-001", "INC-104", "Check carrier scan")
second = append_note("request-001", "INC-104", "Check carrier scan")
assert first == second and len(notes) == 1
Generate the request key in trusted application code for the intended action. If the model invents a new key on every retry, deduplication cannot connect those attempts. Bind the key to the authenticated tenant and operation, and reject reuse with a different payload as this simulation does.
Practice: reason through a crash
Offline. Place a hypothetical crash at three points: before appending the note, after appending but before storing the result, and after storing the result but before responding. Write what a retry would do in the simulation above.
Expected observation: the middle crash exposes the weakness of two separate in-memory updates. A real implementation needs an atomic transaction or a destination API with an idempotency contract. The exercise succeeds when you can identify this failure, not when the simple example appears to work twice in one process.
Next, test reusing the key with different text. It should fail rather than quietly return the previous result. Then distinguish an unknown outcome from a definite failure in your tool envelope. An unknown outcome should trigger status reconciliation using the same request reference before any new mutation is proposed.
Troubleshooting and trade-offs
A retry policy around the entire agent invocation may repeat successful tool actions even if only the final response failed. Recover at the smallest appropriate boundary. An idempotency key with an expiry that is shorter than your retry window can reintroduce duplicates. An unbounded key store creates a retention problem. Define both lifetime and reconciliation behavior.
Idempotency does not replace authorization. A replayed request from another principal must not be accepted merely because its key exists. Store enough identity and intent metadata to enforce the original scope without retaining unnecessary private content.
Interview practice
Why is “retry on every timeout” unsafe for writes?
The write may have completed before the timeout. Without stable idempotency and reconciliation, a retry can duplicate the effect. A timeout is uncertainty about the response, not proof that no change occurred.
What is wrong with the in-memory example in a multi-worker service?
Workers do not share the dictionary, crashes lose it, and concurrent requests can pass the check simultaneously. Durable atomic deduplication must live at the authoritative service boundary.
Completion check
Describe the lost-response case and show how a stable request key follows it. Identify exactly which guarantees the local simulation lacks. Never report its passing assertions as production idempotency evidence.
Sources and version notes
Checked 6 October 2026. Python examples target strands-agents==1.58.0 unless labelled otherwise. Live documentation can change; compare your installed version before adapting an example.
Make the understanding yours.
Use the completion check above. Mark this chapter when you can explain the mechanism and its limits.
Self-assessed reading progress. This does not certify that a lab ran or a system is secure.