How to Prevent an AI Agent From Performing the Same Action Twice
A practical idempotency pattern for preventing duplicate AI-agent refunds, orders, messages, and other consequential actions across retries and parallel runs.
Short answer
Give every consequential action a stable identity, acquire one atomic lock before execution, and mark the action complete afterward. The agent should execute only when the lock service returns safe_to_execute: true.
The failure this prevents
An agent submits a refund, loses the network response, and retries. A prompt instruction such as “do not retry” cannot prove whether the first request succeeded. The safety state must live outside the model and outside one short-lived process.
Recommended workflow
- Describe the action with a stable action name, scope, and identity-defining JSON arguments.
- Fingerprint and atomically lock that intent before calling the external system.
- Execute only when safe_to_execute is exactly true; treat every other result as blocked.
- Complete the lock with the returned key and lock_id after the external result is known.
- On an uncertain outcome, check and reconcile instead of inventing a new action identity.
Working starting point
curl https://api.scrubmytext.com/v1/actions/lock-intent \
-H "Authorization: Bearer smt_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"action":"refund_order","scope":"production","arguments":{"order_id":"82731","amount_minor":72500}}'Relevant product: LockMyAction · REST + MCP
Decision rule
Proceed only when safe_to_execute is true. Reuse the same identity-defining arguments for retries. A fingerprint identifies an action; it does not authorize it or prove the external action succeeded.
Good fit
- Retries could charge, refund, send, delete, publish, or provision twice.
- More than one worker or agent may race to perform the same action.
- The process may crash between an external side effect and receipt of its response.
Use another approach when
- The operation is naturally read-only and harmless to repeat.
- The external provider already supplies durable idempotency with the exact retention you require.
- You need business authorization; add an approval or policy control rather than treating idempotency as permission.
Options compared
| Option | Strength | Important limitation | Best fit |
|---|---|---|---|
| Prompt-only instruction | Easy to add | No durable state; disappears on restart | Never as the only duplicate-action control |
| In-process flag | Fast within one process | Fails across workers, restarts, and parallel runs | Single-process prototypes only |
| Provider idempotency key | Close to the actual side effect | Coverage and retention vary by provider | Use it whenever available |
| LockMyAction | Stable fingerprint plus external atomic state | Caller still owns authorization and outcome reconciliation | Cross-agent or cross-provider workflows |
Implementation cautions
- Do not generate a fresh key for a retry.
- Do not mark complete before the external outcome is known.
- Use completion retention long enough to cover realistic delayed retries.
Frequently asked questions
Is an action fingerprint the same as authorization?
No. It identifies equivalent action intent; it does not prove that the caller is allowed to execute it.
Should I still use a provider idempotency key?
Yes. Layer provider-native protection with an independent workflow lock when the action crosses agents, providers, or processes.
What if the result is unknown?
Keep the action blocked, inspect the current state, and reconcile the external outcome before retrying.
Related decisions
Next step
Use the product page for exact limitations and access requirements, then copy the corresponding REST or MCP workflow.