Every agent framework worth using retries tool calls on transient failure, and that is the right default: dropping a request silently is worse than repeating it. The trouble is where the retry lives. The model sees a timeout, reasons "I did not get a result, so I should try again," and calls the tool a second time. Nothing in that loop knows whether the first call already charged the card or wrote the row in this analysis of agentic tool calling.
The failure window is narrow and easy to picture. The tool commits order 123, then the response is lost on the way back, then the agent retries and the tool commits order 124. The same pattern produces duplicate support tickets from one complaint, double refunds, and stock deducted twice from one order in the same write-up. Prompt engineering does not fix it: an instruction like "only call the payment tool once" cannot help, because the agent genuinely does not know the first call succeeded as described here.
HTTP semantics make this concrete. GET is naturally idempotent, PUT is intended to be, and POST means "create something new," so calling it twice legitimately creates two resources. The server sees no difference between a client retry, a double click and a duplicate request per this idempotency guide. Retries are also not only user-driven: SDKs, reverse proxies, service meshes and SDK backoff all resend requests on their own as listed here.
The decision rule that follows: any tool call with an external side effect (money moves, a row is created, a message is sent) must be idempotent at the tool boundary, because you cannot make the agent layer reliably "call once." Retries are the recovery path you want to keep. The job is to make replaying them harmless.



