Failed payments are the silent revenue tax of subscription businesses. A meaningful share of what gets called "churn" is actually involuntary: a card expired, a soft decline never recovered, an insufficient-funds retry that nobody noticed had ended unsuccessfully. An agent designed for this workflow can recover a non-trivial fraction of that revenue, provided it does not become an email-spam machine in the process.

This walkthrough covers the setup that pairs cleanly with Stripe Smart Retries. The agent classifies failures, picks per-type outreach, escalates the cases a human should see, and respects per-customer rate limits.

What this agent does

The agent listens to two Stripe webhook events: invoice.payment_failed for subscription invoices and charge.failed for one-time payments. For each event, it:

  1. Reads the failure code (card_declined, expired_card, insufficient_funds, do_not_honor, fraudulent, etc.).
  2. Classifies into a recovery bucket.
  3. Picks an outreach path matched to the bucket and customer profile.
  4. Either schedules an action (email, retry, escalation) or hands off to a human.

It does not bypass Stripe's own retry logic, does not charge cards out-of-band, and does not modify subscription state without explicit configuration.

For broader webhook-driven agent patterns, see how to write a prompt for a recurring agent and how to give agent multiple tools.

Failure classifier

Stripe surfaces two useful fields: failure_code and decline_code. Group them into four buckets.

The classifier is deterministic and small; the LLM is not the right tool for this step. A switch statement on Stripe's documented decline codes is sufficient.

Recovery paths by failure type

Each bucket has a different path.

Each path has its own template set, calibrated against your tone. The customer who has paid for two years deserves softer copy than the customer who joined yesterday.

Working with Stripe Smart Retries

Stripe Smart Retries already retry payments on a learned schedule that outperforms naive fixed schedules. The agent's job is not to replace this; it is to wrap it with customer-facing outreach.

Configure your Stripe account to use Smart Retries (or your own scheduled retries if you have a reason). The agent reads invoice.payment_failed and invoice.paid events to understand whether the retry succeeded. Outreach is timed against retry attempts, not against arbitrary calendar days.

For more on agent-tool boundaries, see AI agent tool use explained.

When to escalate to a human

Five triggers escalate immediately, regardless of failure code:

The handoff includes failure context, customer history, and a recommended next action. The human's job is to decide, not to gather context.

Guardrails

For broader operational guardrails, see AI agent safety and guardrails. For monitoring patterns, see how to monitor agent activity.

Common mistakes

Frequently asked questions

What does a Stripe failed-payment recovery agent do?

It listens for invoice.payment_failed and charge.failed webhooks from Stripe, classifies the failure (insufficient funds, expired card, do not honour, soft decline, hard decline), and picks the right outreach: a retry on a smarter schedule for soft declines, an update-payment-method email for expired cards, an immediate human handoff for high-value or fraud-flagged failures.

Should the agent retry on its own?

Stripe Smart Retries already handles a lot of this; the agent's job is to wrap it with the customer-facing outreach piece. For soft declines, let Stripe retry on its schedule. For expired cards, the agent emails the customer with a one-click update link. For hard declines (do not honour, fraudulent), the agent escalates to a human and disables further retries.

How do I prevent the agent from spamming a customer with retry emails?

Per-customer rate limits. No more than two failure emails per 30 days. Group multiple failed invoices into a single message rather than sending one per invoice. The agent dedupes by customer ID and bundles. Spam fatigue causes voluntary churn worse than the original failure.

What signals tell the agent to escalate to a human?

Invoice value above your VIP threshold, customer flagged as enterprise, fraud signal from Stripe Radar, second consecutive failure on the same card, or an inbound support ticket related to the failure. Any of these triggers a human handoff. The agent provides context (failure code, history, customer LTV) so the human does not have to dig.

Does this work for one-time payments or only subscriptions?

Both. For subscriptions, the agent reads invoice.payment_failed and works the recovery loop. For one-time payments (charge.failed), the agent emails the customer with a re-pay link that re-uses the original payment intent or creates a new one. The classifier and outreach paths are similar; only the retry mechanics differ.

Three takeaways before you close this tab

Sources