Quick answer: AI agents retry a tool call whenever the result is ambiguous, timed out, or an error, and the tool has to tell the agent whether that retry is safe. Read-only tools and keyed, idempotent writes can be replayed without changing the outcome. Unkeyed destructive tools cannot, so they need an idempotency key and clear annotations. If the tool gives no signal, the agent either retries blindly and duplicates work or refuses to retry at all, both of which show up as failures.

Why the agent cannot just infer safety

The agent calling a tool does not see what the server did after a lost response. It only knows the answer did not come back. Whether resending is safe depends on the operation's semantics, which the agent has no reliable way to guess from a name like createOrder.

MCP carries tool annotations that describe behavior, including whether a tool is read-only or destructive, and whether it is safe to call repeatedly. Those hints exist precisely so the client's retry logic is based on declared behavior rather than a heuristic that a well-named method is probably safe.

The tool categories and how each retries

Group tools by their replay behavior, then handle retries differently per group.

Tool type Retry behavior Required signal
Read-only query Safe to replay, no state change Read-only annotation
Keyed write with idempotency key Replay collapses to the same result Key plus idempotent annotation
Unkeyed create Replay may duplicate Key required before safe retry
Destructive delete Safe only if keyed or target-based Destructive annotation
Long-running job Retry returns job status, not a new job Stable job id

The long-running case deserves attention. A retry of a started job should ask for the status of the existing job rather than launching a second one, which is the same idempotency principle applied to asynchronous work.

How to make a write tool safe to replay

The mechanism is the same one used across reliable APIs: the caller sends a unique key, and the server stores it with the result so a replayed call returns the original outcome.

  1. The agent generates a key for the logical action and includes it on the tool call.
  2. The server processes the work once and persists the key alongside the result.
  3. On a timeout, the agent retries with the same key rather than a new one.
  4. The server recognizes the key and returns the stored result, doing no second side effect.
  5. A genuinely new action uses a fresh key, so unrelated calls never merge.

The key travels with the logical request, not the individual network attempt. That distinction is what makes a retry a replay of the same intent rather than a new action.

What the annotations should actually communicate

Use the MCP tool metadata to make the retry path explicit instead of leaving it to the caller. A built client such as Powerduck reads these hints when it decides whether an automatic retry is safe, which is why the declarations have to be accurate.

  • Mark read-only tools as such so the agent retries them freely.
  • Mark destructive tools so the agent asks for confirmation and does not auto-replay an unkeyed call.
  • Declare idempotency on keyed writes so the agent knows a resend with the same key is safe.
  • Describe the parameter that carries the key in the tool's input schema, including it as required for write operations, so the agent cannot omit it.

A loose input schema that treats the key as optional leaves the agent unable to guarantee safe retry and pushes the problem back to guesswork.

Frequently asked questions

What happens if the agent retries with a new key by mistake? The server treats it as a new action and can duplicate the work. The key must be generated once per logical task and reused across every retry of that task, which is why the client, not the server, owns generating it.

Are read-only tools always safe to retry? They do not change state, but they can still hit rate limits or return different data if the underlying resource changes. The annotation means no write side effect, not that the response is byte-identical.

How should a tool signal a still-running job? Return a stable job id and a status the agent can poll. A retry of the same call should read that job, never start a parallel one, and the agent should poll rather than resubmit.

Does idempotency remove the need for confirmation on destructive tools? No. Idempotency protects retries; the destructive annotation protects the user from an unintended action. Keep both, and still confirm actions such as deleting data.

The bottom line

Retries are guaranteed once an agent works over a network, so a tool's safety on replay is part of its contract, not an implementation detail. Read-only tools declare themselves and replay freely; write tools take a stable key and collapse retries onto one result; destructive tools stay marked and confirmed. Get the annotations and the key into the schema up front, and the agent's automatic retry becomes a safe no-op rather than a source of duplicate orders. The full set of conventions is in the MCP server guide.