The ambiguous write is the important case
Read retries are often easier to reason about than write retries. When a tool sends a mutation and the connection closes, the downstream service may have rejected it, committed it or still be processing it. A model that sees “timeout” may reasonably try again; the execution system must make that recovery safe for the business operation.
AWS’s idempotent API guidance treats repeated requests as an expression of client intent and discusses how to avoid repeating the same side effect. For agent tools, the application should create and preserve that intent identity independently of a new model response.[1]
| Identity | Meaning |
|---|---|
| Task ID | The broader user objective or workflow. |
| Operation ID | One intended business mutation within that task. |
| Attempt ID | One transport or execution attempt for that operation. |
Several attempts can belong to one operation, and several operations can belong to one task. Reusing a task ID for every write can suppress legitimate different actions; generating a new operation ID on every retry can duplicate one action.
Bind the key to the actual operation
Scope the idempotency key to the tenant or business boundary and record a canonical payload representation or digest. If the key is reused with a different payload, return a conflict. Otherwise the caller may receive a previous result for an action it did not intend.
The executor needs concurrency protection. A check-then-write sequence without a transaction or uniqueness constraint can let two simultaneous requests both pass the check. Where the mutation and operation record share one database, committing them atomically can establish one recorded mutation per key within that database.
begin transaction
find (tenant, operation_key)
if found: compare payload, return recorded result
otherwise: validate current policy and resource version
apply mutation
record operation result under a unique key
commitThis is a conceptual sequence. Exact transaction isolation, locking and failure behavior depend on the storage system. The downloadable example demonstrates a small SQLite case and states its scope.
Worked scenario: the commit succeeds, the response is lost
- The caller creates operation op-42 for a specific account change.
- The service commits the account mutation and the operation result in one transaction.
- The response connection fails before the caller receives confirmation.
- The task records outcome unknown for op-42.
- A retry or status lookup uses the same tenant and op-42.
- The service returns the recorded result without applying the mutation again.
If the caller changes the payload from one amount to another while retaining op-42, the service rejects the conflict. If the user intentionally requests a second action, the application creates a new operation after the appropriate validation and approval. The model should not improvise that distinction from wording alone.
Inspect source, tests and recorded outcomes for duplicate requests and conflicting payloads.
External side effects need an end-to-end contract
A database record cannot atomically commit an unrelated external payment or email unless the external system participates in a suitable protocol. Recording “sent” before the call risks losing the action; recording it afterward risks repeating it after a crash. An outbox can durably record intent, but its dispatcher still needs downstream duplicate handling or reconciliation.
| Operation | Requirement to investigate | Remaining limit |
|---|---|---|
| Provider supports idempotency | Pass a stable key and understand its scope and retention. | Behavior after key expiry may differ. |
| Provider exposes operation status | Store the provider reference and reconcile uncertain outcomes. | Lookup may be delayed or unavailable. |
| No duplicate or status contract | Use a conservative workflow and an explicit recovery process. | Automatic retries may be unsafe. |
Do not promise globally exactly-once behavior because one service deduplicates requests. The business effect is only as strong as the contracts across the complete path.
Define retry and retention behavior
Retry only the failures the service classifies as retryable, within a bounded time and attempt budget. Preserve the operation key. Respect denied actions and validation errors; switching tools or models is not a legitimate way to bypass them.
- Define how long operation results and keys remain available.
- Reject or reconcile a retry that arrives outside the supported retention window.
- Distinguish in-progress, committed, rejected and unknown states.
- Specify what a concurrent duplicate observes while the first attempt is executing.
- Record enough evidence to connect an approval to the actual committed operation.
MCP can carry a tool call, but the business operation’s duplicate semantics still need to be designed and exposed clearly. A protocol message identifier is not automatically the same thing as the intended domain-operation key.[2]
What a buyer should ask to see
Request a demonstration that loses the response after commit, retries concurrently, reuses a key with a different payload and sends the same key from another tenant. Inspect the resulting business records and operation records, not only the HTTP responses.
The result should establish the tested boundary precisely: for example, one recorded mutation per tenant and operation key in a given database. That is a useful, inspectable claim. Extend it to external effects only when the downstream contract and failure tests support it.
Sources and scope
Technical references inform the cited statements. The decision frameworks and synthetic examples are TeqEngine’s editorial guidance.
- AWS Builders’ Library: Making retries safe with idempotent APIshttps://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/
- Model Context Protocol: tools, 2026-07-28https://modelcontextprotocol.io/specification/2026-07-28/server/tools