All workflows

Win back canceled customers with an offer for why they left

Reads why each Stripe subscription was canceled, sorts the reason with Jev, and emails a win-back offer that fits it with Resend.

Outcome

  • A table of every recent cancellation with its reason, whether it leaves the door open, the offer picked and Jev's confidence.

  • An approved win-back email sent to each customer who got an offer and opted in to marketing email.

  • The customers left out, with why.

How it works

  1. 1

    Pull cancellations

    Stripe

    List subscriptions with status canceled, each customer expanded, and page through them. Keep those whose ended_at falls in the last lookback_days and whose cancellation_details.reason is cancellation_requested, with each customer's name and email, the plan, how long they subscribed, and the cancellation feedback and comment; list the rest as left out.

  2. 2

    Sort the reasons

    TypeSafe AI

    Send each cancellation's feedback, comment, plan and tenure as the state, with a choice reason of too_expensive (price or budget), missing_feature (needs something the product lacks), low_usage (did not use it enough), switched_to_competitor (moved to another product), too_complex (hard to set up or use), support_problem (unhappy with help received), temporary_need (a project or season ended), business_closed (the company closed or was acquired) and other, and a noul door_open (the comment names something that would bring them back). Keep each reason, its confidence and door_open.

  3. 3

    Pick the offers

    Your agent

    Show the user every cancellation whose reason confidence is below min_confidence or whose door_open is unsure, and keep what the user decides. Give each customer the offer in offers for their reason. Leave out business_closed, switched_to_competitor unless door_open is yes, anyone with no offer for their reason and anyone consent_source doesn't show as opted in, and list each with why. Confirm the consent list with the user.

  4. 4

    Write the emails

    Your agent

    For each customer, draft a subject line and three or four plain sentences: say what they told you in their own words, make the one offer for their reason, link to comeback_link, and end with a line to opt out of these emails and postal_address. Show the drafts to the user.

  5. 5

    Send

    Resend

    After the user approves, send each email from from_address to its customer, with an idempotency key per customer.

You'll be asked for

  • How recent a cancellation counts

    e.g. 14

  • The offer for each reason, with any promotion code already created in Stripe

    e.g. too_expensive: 30% off for three months with the code COMEBACK30; low_usage: a free setup call; too_complex: a free setup call; missing_feature: a note when it ships; temporary_need: a free month when they return

  • The page where a customer restarts their subscription

    e.g. https://app.acme.com/billing

  • Where you record who opted in to marketing email

    e.g. a Stripe customer metadata field, or an export of opted-in addresses from your email tool

  • The verified Resend sender the emails come from

    e.g. Sam at Acme <sam@acme.com>

  • The mailing address every marketing email carries

    e.g. Acme Inc., 1 Main St, Springfield, IL 62701

  • How sure Jev must be before its answer is used without you

    e.g. 0.8; a yes-or-no answer counts as yes at or above it and as no at or below 1 minus it

The file your agent runs

cancellation-winback.md

Win back canceled customers with an offer for why they left

Reads why each Stripe subscription was canceled, sorts the reason with Jev, and emails a win-back offer that fits it with Resend.

Set up the tools below, then run the steps in order for the user, carrying each step's results into the next. The run is done when the user has the outcome below.

Outcome

  • A table of every recent cancellation with its reason, whether it leaves the door open, the offer picked and Jev's confidence.
  • An approved win-back email sent to each customer who got an offer and opted in to marketing email.
  • The customers left out, with why.

Inputs

Ask the user for these before you start.

  • lookback_days: how recent a cancellation counts, e.g. 14
  • offers: the offer for each reason, with any promotion code already created in Stripe, e.g. too_expensive: 30% off for three months with the code COMEBACK30; low_usage: a free setup call; too_complex: a free setup call; missing_feature: a note when it ships; temporary_need: a free month when they return
  • comeback_link: the page where a customer restarts their subscription, e.g. https://app.acme.com/billing
  • consent_source: where you record who opted in to marketing email, e.g. a Stripe customer metadata field, or an export of opted-in addresses from your email tool
  • from_address: the verified Resend sender the emails come from, e.g. Sam at Acme sam@acme.com
  • postal_address: the mailing address every marketing email carries, e.g. Acme Inc., 1 Main St, Springfield, IL 62701
  • min_confidence: how sure Jev must be before its answer is used without you, e.g. 0.8; a yes-or-no answer counts as yes at or above it and as no at or below 1 minus it

Set up

List subscriptions (Stripe, tool:stripe/list-subscriptions)

Use the first option your agent supports.

MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "stripe": { "url": "https://mcp.stripe.com" } } }

Call the MCP tool stripe_api_read with GET /v1/subscriptions.

CLI (official)

Install the command and sign in with it, then confirm it runs.

npm install -g @stripe/cli
stripe --version

Run stripe subscriptions list.

Answer typed questions (TypeSafe AI, tool:typesafe/answer-typed-questions)

Use the API.

Note: Put every question about one record in one request. GET /v1/models lists the models and is the cheapest check of a key; a request over the rate limit gets a 429 with a Retry-After header.

Note: Send state, model (jev-latest) and named questions, each with type, instructions and criteria: a choice maps labels to descriptions, a score lists its levels in order, a noul's is optional. Read a score by its most likely level; send unsure answers to a person.

Send an email (Resend, tool:resend/send-email)

Use the first option your agent supports.

Note: Pass an Idempotency-Key header (--idempotency-key on the CLI) so a retry never sends it twice; keys expire after 24 hours.

MCP (official, remote)

Add this server to your agent's MCP settings, then sign in when asked.

{ "mcpServers": { "resend": { "url": "https://mcp.resend.com/mcp" } } }

Call the MCP tool send-email.

CLI (official)

Install the command, then confirm it runs.

npm install -g resend-cli
resend --version

Run resend emails send.

Set $RESEND_API_KEY in your environment first (get a key: https://resend.com/api-keys).

Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.

Steps

  1. Pull cancellations with List subscriptions (Stripe). List subscriptions with status canceled, each customer expanded, and page through them. Keep those whose ended_at falls in the last lookback_days and whose cancellation_details.reason is cancellation_requested, with each customer's name and email, the plan, how long they subscribed, and the cancellation feedback and comment; list the rest as left out.
  2. Sort the reasons with Answer typed questions (TypeSafe AI). Send each cancellation's feedback, comment, plan and tenure as the state, with a choice reason of too_expensive (price or budget), missing_feature (needs something the product lacks), low_usage (did not use it enough), switched_to_competitor (moved to another product), too_complex (hard to set up or use), support_problem (unhappy with help received), temporary_need (a project or season ended), business_closed (the company closed or was acquired) and other, and a noul door_open (the comment names something that would bring them back). Keep each reason, its confidence and door_open.
  3. Pick the offers yourself. Show the user every cancellation whose reason confidence is below min_confidence or whose door_open is unsure, and keep what the user decides. Give each customer the offer in offers for their reason. Leave out business_closed, switched_to_competitor unless door_open is yes, anyone with no offer for their reason and anyone consent_source doesn't show as opted in, and list each with why. Confirm the consent list with the user.
  4. Write the emails yourself. For each customer, draft a subject line and three or four plain sentences: say what they told you in their own words, make the one offer for their reason, link to comeback_link, and end with a line to opt out of these emails and postal_address. Show the drafts to the user.
  5. Send with Send an email (Resend). After the user approves, send each email from from_address to its customer, with an idempotency key per customer.

Notes

Each offer answers one reason: a discount for price, a setup call for low usage or complexity. A customer who switched to a competitor is usually better left alone. Stripe's own feedback values are broad; the free-text comment is where the detail is, which is why Jev reads both. Customers whose subscriptions ended over a failed payment or a dispute need a billing fix, not an offer, so step 1 leaves them out.

Run it weekly with lookback_days set to 7.

Rules

  • Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
  • Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
  • Never print API keys.