Skip to content

Idempotency

Idempotency is a cross-cutting guarantee, not one decorator. It prevents a retry, redelivery, process restart, or duplicate request from repeating an effect whose first outcome is already known or indeterminate.

Choose the relevant layer

Boundary Mechanism Reference
Model-request retry Retry only normalized transient failures; do not repeat unsafe post-tool turns Retry and resilience
Tool call Declare read-only, idempotent, or effectful policy and use a durable store Tool idempotency
Run checkpoint/resume Persist the frontier and resolve dispatched calls before continuing Checkpointing
Event consumer Deduplicate by event identity before applying the effect Idempotent consumption
State plus event Commit state and an outbox record in one transaction Transactional outbox
Workflow activity Keep provider/tool calls outside replayed workflow code and record results Replay safety
Dead-letter replay Re-enter through the live idempotent handler under a bounded replay plan Dead letters
Peer/A2A task Bind idempotency to authenticated caller, tenant, task/request identity, and operation Official A2A

Rules

  • A generated retry key must cover tenant, agent/tool operation, normalized arguments, and the caller-visible request identity.
  • The store must atomically distinguish absent, in-flight, completed, and abandoned work.
  • The retention window is part of the guarantee. A request after expiry is not known to be a duplicate.
  • A timeout after dispatch is indeterminate unless the downstream system exposes a status/read-back operation.
  • Never turn an unknown outcome into “safe to retry” merely because the local call raised.
  • Event acknowledgement happens only after the dedupe decision and effect are durable.
  • Replays use the normal authorization, validation, and idempotency path.
  • Metrics distinguish suppressed duplicates, in-flight collisions, indeterminate work, expired records, and real failures.

For a new side effect, start with Tool idempotency and add fault-injection tests for a crash before dispatch, after dispatch, after commit, and before the response reaches the caller.