## TL;DR

Retrying a payout after a timeout without checking its status sends the money twice: the first attempt often succeeded despite the timeout. Make the agent check-then-act: look up the payout by idempotency key or provider reference before any retry, and only re-issue when the provider confirms the first attempt failed. Recover the duplicate by reversing it with the recipient, and put the check before every money-moving retry.

```text
agent retried a payout after a timeout without checking status: duplicate payout sent
```

## Use this when

- An agent retried a payout after a timeout and sent a duplicate
- Payout retries lack a status check
- You need a check-then-act payout pattern

## Not for this skill when

- The payout failed definitively before any money moved (safe to retry)
- The duplicate came from two different agents racing (needs locking)
- You are debugging the payout provider's API

## Steps

1. Halt further retries immediately and list all payouts for the recipient in the window.
   Expected: The duplicate is confirmed and contained.
2. Recover the duplicate: request a return from the recipient or reverse via the provider where supported.
   Expected: The money is recovered or recovery is underway.
3. Add a pre-retry status check: query the payout by idempotency key or provider reference.
   Expected: The agent knows the true state before acting.
4. Only re-issue when the provider confirms the original failed; if its state is unknown, wait and re-check rather than resending.
   Expected: Retries are safe.
5. Make idempotency keys mandatory on every payout the agent creates.
   Expected: Duplicates are structurally impossible.
6. Require human approval for payouts above a threshold, especially retries.
   Expected: A human gates the riskiest retries.

## Tool compatibility

Payout provider APIs with idempotency keys (Stripe, Wise, Airwallex, PayPal Payouts); agent payout loops.

## Variant phrasings

### agent duplicate payout timeout retry

The incident described directly.

### payout retry without status check

The missing-guardrail phrasing.

### check then act payout idempotency

The pattern as a search phrase.

## Why it happens

A timeout means the response was lost, not that the action failed: the provider may have executed the payout and then the network dropped the confirmation. An agent that treats timeout as failure and retries unconditionally will eventually double-pay. This is the canonical exactly-once delivery problem, and the fix is check-then-act: the payout's idempotency key makes the status query authoritative. Money movement is the highest-stakes agent action, which is why the persona brief makes human-in-the-loop and idempotency first-class: the retry policy is a guardrail, not an optimization.

## Edge cases / pitfalls

- Some providers take minutes to settle a payout's status; poll with backoff rather than deciding on the first unknown.
- Two agents paying the same recipient need a distributed lock in addition to idempotency keys.
- Log every retry decision with the status observed; the audit trail is your defense in a dispute.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_o6oOf6M5BSTgGscsMWTMDw
