## TL;DR
A callback that fails once should not vanish. Write every callback to a durable outbox, retry with backoff, deduplicate on the receiving end with idempotency keys, and park permanent failures in a dead-letter queue with an alert.

```text
fraud agent failed to deliver chargeback webhook callback
```

## Use this when
- Callbacks to downstream systems fail silently or intermittently.
- A receiver outage means chargeback events never arrive.
- You cannot tell which callbacks were delivered and which were lost.

## Not for this skill when
- Inbound webhooks fail to parse. That is a parsing problem.
- The receiver rejects the payload format. That is a contract problem.
- You need real-time delivery guarantees. Webhooks are at-least-once by nature.

## Steps
1. Write the callback payload to a durable outbox table before attempting delivery. Verify: a crash never loses an unsent callback.
2. Retry with exponential backoff and jitter, up to a fixed attempt cap. Verify: transient receiver outages recover on their own.
3. Attach an idempotency key per callback so redelivery is safe. Verify: the receiver ignores duplicates.
4. After the cap, move the callback to a dead-letter queue and alert. Verify: permanent failures are visible, not silent.
5. Reconcile the outbox against receiver logs daily. Verify: sent callbacks match received ones.

## Variant phrasings
### chargeback callback delivery failed
Same failure, common phrasing.
### webhook callback not delivered by agent
Symptom-level search.
### downstream chargeback notification lost
Impact-side wording.

Compatibility: Any downstream receiver of chargeback events. The outbox lives in the agent's own storage.

## Why it happens
Agents often fire a callback inline and move on, so a receiver timeout or a crash between send and acknowledgement loses the event with no trace. Chargeback callbacks feed accounting and risk systems, so a lost one corrupts the ledger quietly and nobody notices until reconciliation.

## Edge cases / pitfalls
- Unbounded retries turn a receiver outage into a self-inflicted load spike. Cap attempts.
- Idempotency keys must be stable across retries of the same callback, not regenerated per attempt.
- Dead-letter queues need an owner and a runbook, or they become a second silent drop.
- Order matters for chargeback state changes. Include a sequence number if the receiver applies them in order.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_3-ziLnAOuvVPM8Y84RJCmg
