Cancel-save flows are easy to over-engineer into manipulative dark patterns, and easy to under-engineer into "your subscription has been cancelled, goodbye" experiences that lose revenue. A good cancel-save agent does three things: classifies the reason, offers one relevant save option, and respects a direct cancellation request.
The Telnyx code example is:
It is a Python Flask app that combines Telnyx Voice, AI Inference, and Messaging into a small demo you can clone and run in a few minutes.
The Flow
A customer calls in saying they want to cancel. The Flask app receives the webhook, verifies the customer by caller ID, and asks why they want to cancel. AI Inference returns the reason (too_expensive, not_using, missing_feature, support_issue, competitor_switch, temporary_pause, other) and the sentiment. Hardcoded urgent phrases (lawyer, sue, fraud, chargeback) and direct cancel phrases (cancel now, please cancel my subscription) short-circuit before any offer.
Otherwise, the agent offers one save option from the OFFER_POLICY mapping. A "yes" applies the save or pauses the subscription. A "no" or "cancel" ends the call with a graceful cancellation. An ambiguous yes/no gets exactly one clarifying prompt — the agent never loops.
The case is recorded with the outcome (saved, cancelled, paused, transferred, needs_followup), and the customer record is updated. Hangups before resolution are recorded as needs_followup so reps can call back.
Why I Like This Example
It is small enough to demo live, but it covers the parts that often get cut from a "Hello World" voice AI demo:
- Single-prompt AI Inference classification that returns structured JSON
- An offer policy that maps reason to one offer and one default outcome
- Hardcoded overrides for urgent phrases and direct cancel so the agent does not rely on the LLM to get safety right
- One clarifying prompt on ambiguous yes/no so the conversation does not loop
- Idempotent webhook handling so retries do not double-log cases
- Hangup tracking so open cases never disappear
The design choice I care most about is non-manipulation. The agent does not push back on a direct cancellation, and it offers one save option — not five — when the customer is open to one. That maps to how good customer-success teams actually operate.
Run It Locally
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/ai-subscription-cancel-save-retention-agent-python
cp .env.example .env
pip install -r requirements.txt
python app.py
Expose the webhook:
ngrok http 5000
In the Telnyx Portal, set the Voice API app webhook URL to https://<ngrok-id>.ngrok-free.app/webhooks/voice. Seed a customer with POST /customers, then call the Telnyx number from the customer's phone.
What To Demo
I would keep the demo short and show three flows back-to-back:
- Customer says "I want to cancel, it's too expensive" then accepts the 25% off offer. Case ends
saved, customer statusactive. - Customer says "I want to cancel, it's too expensive" then declines. Case ends
cancelled, customer statuscancelled. - Customer says "I want a lawyer this is fraud." Case ends
transferred, call moves to the human escalation number.
That gives viewers the full loop without getting lost in implementation details.
Where To Take It Next
The demo uses in-memory state, which is fine for learning. Production would wire the customer and case stores into your billing system (Stripe, Recurly, Chargebee) so a saved outcome actually applies the discount and a paused outcome defers the next invoice. Add consent recording (record_channels: "dual") for compliance audits, and replace the caller-ID match with a one-time code flow for real verification.
Resources
- Code example: https://github.com/team-telnyx/telnyx-code-examples/tree/main/ai-subscription-cancel-save-retention-agent-python
- Telnyx Voice docs: https://developers.telnyx.com/docs/voice/call-control
- Telnyx AI Inference docs: https://developers.telnyx.com/docs/inference
- Telnyx Messaging docs: https://developers.telnyx.com/docs/messaging
- Telnyx Portal: https://portal.telnyx.com
Top comments (0)