Voice AI Retry Design — retryOnFail, Idempotency Keys, and onError
Retrying a failed voice AI request can execute the same operation twice. This covers how retryOnFail, idempotency keys, and onError=continueErrorOutput work together.
When a voice AI fails mid-request, the instinct is to retry. If that retry can execute the same operation twice, the design has to account for it.
When retrying is safe and when it is not
Read requests are safe to repeat — the result is the same every time. Requests that change state, like creating a booking or processing a payment, are not. Running one twice can produce two results.
When an agent receives an error, it often cannot tell whether the operation failed before completing or completed but the response was lost. Retrying without handling that distinction leads to double bookings or duplicate charges.
Using idempotency keys to prevent duplicate execution
An idempotency key is a unique identifier attached to a request. When the server sees the same key again, it returns the previous result instead of re-executing the operation.
If the agent retries after a lost response, the same key prevents a second execution. Generate one key per customer request and use it across every retry. Generating a new key on each retry defeats the purpose.
retryOnFail configuration
retryOnFail controls whether the agent automatically retries a failed tool call. Enabled, it recovers from transient network errors and timeouts.
On its own, retryOnFail creates a risk on APIs without idempotency handling. The setting and the key have to be designed together.

onError=continueErrorOutput
How the agent continues the conversation after an error is also a design decision. onError=continueErrorOutput passes error information to the agent so it can use it in the next response.
Without this, the agent knows a failure occurred but not what kind. With continueErrorOutput, the agent receives the error content and can give a contextually appropriate response. A temporary service error leads to a retry suggestion; a permissions error routes elsewhere.
Where this approach breaks down
Attaching a key does not close every duplicate.
The most common is a downstream system that does not accept an idempotency key. You can send one, but if the server never reads it, duplicate requests stay indistinguishable. You need a separate read to check state before retrying.
Keys also expire. When a server remembers a processed key only for a limited window, a retry arriving after that window is handled as a fresh request. The longer the retry interval, the wider that gap gets.
Chained systems are the hardest. Making the first API idempotent does not help when the call behind it is not, and the duplicate surfaces further down the chain.
How to handle low-confidence situations in voice AI is covered in Voice AI Low-Confidence Escalation Design.
- Read requests: safe to retry, idempotency key not needed
- State-changing requests: design retryOnFail and idempotency key together
- Error handling: onError=continueErrorOutput lets the agent act on error content
The question is not whether to retry but whether the retry is safe. Idempotency handling is what makes retrying meaningful.
