Making tool calls safe to repeat
18 September 2026
If an agent can be retried or resumed, then any tool it calls can run more than once. For a read, that is harmless. For a write, such as creating a ticket or sending an email, it is a bug waiting to happen.
The fix is to make the call idempotent. Running it twice with the same input should have the same effect as running it once.
Use a stable key
Build a key from things that do not change between attempts. A run id plus a step id works well. Do not use a timestamp or a random value, because they differ on every attempt.
def create_ticket(args, run_id, step_id):
key = f"{run_id}:{step_id}"
existing = store.get(key)
if existing is not None:
return existing
result = api.create_ticket(**args, idempotency_key=key)
store.put(key, result)
return result
If the external API accepts an idempotency key, pass it along. Many payment and ticketing APIs do. If it does not, check for an existing record before you create a new one.
Record the result
Storing the result matters as much as the key. When the call is repeated, return the saved result so the agent sees the same answer as the first time.
Which calls need this
- Anything that creates, updates or deletes data
- Anything that sends a message or triggers a payment
- Anything with a cost you do not want to pay twice
Pure reads can usually run again without any special handling.