How we win back subscription payments that fail

Plenty of customers who "churn" never meant to go anywhere. Their card hit its expiry date. Their bank got nervous about a charge. The payment bounced for a reason unrelated to how much they like your product. Nobody notices, and a few weeks later the subscription is simply gone. That's involuntary churn, and you can win most of it back if you spot the failure early and follow up the same way every time.
So we put an agent on Machine in charge of it. It keeps an eye on each Stripe invoice that fails and moves it up a set ladder: smart retry, then a reminder, then a "please update your card" note, then a final notice. When the customer pays, it stops right there. Cancelling, crediting and refunding are never its call. A person on the team makes those.
The problem
Think of a declined charge as a clock starting, not a single moment. Stripe does try again on its own for a while. But its schedule is one size for everyone. It has no idea a customer's bank just put a fraud hold on their card, or that someone else stopped reading email a week ago. Send everyone the same flat nudge and you lose people who would have paid with a better-timed ask. Send nothing and the plan expires, and support only hears about it when an angry customer writes in asking where their access went.
The usual fixes forget things. Stripe's own retries help, yet they never pull in a person, never get firmer as days go by, and never warn revenue which accounts are close to dropping off. A spreadsheet of who got what email is out of date by Friday. And an automatic "cancel after so many failures" rule gives you a tidy list by throwing away customers you could have kept.
What we built
Once an hour, a cron on Machine wakes up a single persistent session. That session holds a ledger with one line per subscription, showing which rung each failed invoice has reached: smart retry, reminder, update-your-card, or final notice. On each pass the agent pulls failed invoices and subscription status from Stripe. If a subscription has waited long enough, it moves up a rung and the customer gets that rung's email. Then the agent drops a rundown of everything still open into the revenue team's Slack channel. The minute a subscription pays, its line on the ledger is closed and nobody emails that customer again.
How it works
Wake the same session every hour
An hourly cron trigger starts the run. Most of our agents get a brand new session each time, but this one goes back to the same session on every pass. Its memory is where the ledger lives: each subscription's current rung and the time it's due to move. That's how the agent knows exactly what has already gone out, so it never sends a step twice or jumps one.
Pull the failures from Stripe
Stripe is reached through a scoped connector. Machine holds the key on its own servers, so the model never sees a raw key. From there the agent reads failed invoices, subscription status and the state of each payment method. That's all it needs to choose a next move, and the same read picks up brand new failures alongside subscriptions already partway up the ladder.
Hand it the ladder as a playbook
The steps and their timing are written down as a skill, the agent's playbook. Rung one is a smart retry. Rung two is a friendly reminder about the payment. Rung three is a firmer note asking the customer to update their card, with a link to do it. Rung four is the final notice. Each rung has to wait a minimum time after the last, so nobody gets two emails on the same day.
Email the customer, then tell revenue
The agent sends whichever email matches the rung, straight to the customer, with no approval step. A retry or a dunning email is expected and easy to undo, so holding it for sign-off would only slow recovery. It also posts to Slack: which accounts moved up today, which are now on final notice, and which ones paid since last time.
Stop at the top rung
The final notice is as far as the agent goes. Getting there does not cancel anything, refund anything or credit anything. The account simply waits, flagged in the Slack rundown, for someone on revenue to pick the next step. The Stripe and email credentials are stored encrypted in the Secrets Manager, added at run time, and only handed to the agents you grant them to.
Close it out as soon as money lands
On every pass the agent checks whether anything on the ladder has paid in the meantime. If it has, the ledger marks it recovered, the emails stop, and the Slack rundown lists it as a win. No follow-up, no stray reminder a day later.
The pattern
One reusable session, woken every hour by a cron, keeps a ledger with a line per subscription. A Stripe connector that mostly reads tells it what changed. A skill holds the escalation ladder. It can only ever write email and Slack. At the final notice it stops, and cancellations, credits and refunds stay with a person every time.
Guardrails
Retrying a charge and sending an email are things the agent may do alone. Anything that moves money or ends a subscription is not:
- Retries and reminders, nothing else. It can try a failed charge again and send the four ladder emails. Cancelling, crediting and refunding always go to a person. There are no exceptions.
- A rung at a time. The playbook sets a minimum gap between rungs, so no customer hears from us twice in quick succession. Each subscription climbs on its own clock instead of the whole list moving together.
- Paid means done. When an invoice clears, its ledger line closes and the emails end.
- Locked-down keys. The Stripe credential is stored encrypted in the Secrets Manager, added to the sandbox at run time, and only handed to the agents you grant them to.
- All of it lives in code. The ladder, the waiting times and what the agent is allowed to touch sit as files in the repo. They're versioned, and you change them with a reviewed change request, not a toggle on a dashboard.
The outcome
A failed payment used to sit untouched until the plan quietly ran out. Now it starts climbing a steady, firmer-each-time ladder the hour it fails, and the revenue team can see what's open and what's waiting on them. The agent does the chasing. People still decide when it's time to let a customer go.
More use cases
How we answer GDPR data-subject requests before the deadline
Our Machine agent checks each GDPR access or deletion request, finds the person's data across our product database, builds the report well within the SLA and hands it to legal before anything is sent.

How we keep our docs matching what the code does
Once a day a Machine agent reads every commit merged since its last pass, finds the doc pages those changes made wrong, rewrites them and sends you one pull request to review.

How we test every pull request without lifting a finger
Our Machine QA agent works with GitHub and our test environment. For each pull request it checks out the branch, runs the tests, tries the change for real, and posts what it found.
Put your first agentto work today.
- SSO
- RBAC
- Governed agents
- Full audit trail