Daily
Spot customers at risk of leaving from their tickets
Each morning, Slack lists the customers whose recent tickets suggest they might cancel, grouped by company.
- Runs
- Daily
- Apps
- Slack, Zendesk
- AI
- Yes, uses the built-in AI allowance
- Access
- Zendesk read; chat:write
Send this to your assistant
Create a ClickRuntime automation: every morning, read yesterday's updated Zendesk tickets. Use AI to flag ones that mention cancelling, switching or serious frustration, group them by organisation and post the list to #customer-success.
First time? Adding ClickRuntime to your assistant takes about two minutes.
Why use it
Why teams use this automation
A subscription business with a small customer success team only finds out a customer is unhappy when the cancellation arrives. The warning signs were there in support tickets: a third complaint about the same bug, a question about how to export all their data, a line saying they are looking at other options. Nobody reads every ticket with that in mind.
A daily list of customers who sound like they might leave gives account managers a chance to call before the decision is made.
What you get out of it
Warning signs reach the right people
Customer success sees the risk signals that support hears every day, without reading every ticket themselves.
Time to act before renewal
A call the day after a frustrated ticket does more than a win-back email after the customer has gone.
Grouped by account
Several worried tickets from the same company show up together, which is a far stronger signal than any one of them.
Language rules miss most of it
Customers rarely write the word cancel. AI picks up phrases like looking at alternatives or exporting everything that a keyword filter would miss.
How it works
What happens, step by step
Every morning, ClickRuntime finds the Zendesk tickets updated in the last day.
AI reads each one and flags those that mention cancelling, switching to another provider or ongoing frustration.
Flagged tickets are grouped by customer organisation.
The list, with a short reason and a link for each ticket, is posted to your #customer-success Slack channel.
Before it runs live
- Connect Slack, then invite the app to the channel (type /invite @ClickRuntime there)
- Connect Zendesk
What you get
Build your own
Need it to work differently?
Your own rules
Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.
Any number of apps
One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.
AI where it helps
Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.
On a schedule or on each event
Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.
Changes you can ask for
- Run it at a different time, more or less often, or only on weekdays
- Change what the AI looks for, or how it writes the result
- Add another app, for example also send it to Google Sheets
- Combine it with other Slack and Zendesk steps into one automation
Under the hood
The code that runs this automation
from datetime import date, timedelta
from clickruntime import on_trigger, http, credentials, ai, notify
ZD, AGENT = "https://yourcompany.zendesk.com/api/v2", "you@yourcompany.com"
def zd(method, path, **kw):
r = http.request(method, ZD + path, auth=(f"{AGENT}/token", credentials.secret("ZENDESK_API_TOKEN")), **kw)
return r.raise_for_status() or (r.json() if r.content else None)
@on_trigger
def run(event):
since = (date.today() - timedelta(days=1)).isoformat()
tickets = zd("GET", "/search.json", params={"query": f"type:ticket updated>={since}"})["results"][:100]
if not tickets:
return {"flagged": 0}
numbered = "\n".join(f"{i}. {t['subject']} | {t['description'][:300]}" for i, t in enumerate(tickets))
res = ai.generate(numbered, system="Return the numbers of tickets that suggest the customer may cancel or switch provider, with a 6-word reason each.",
json_schema={"type": "object", "properties": {"risks": {"type": "array", "items": {"type": "object",
"properties": {"n": {"type": "integer"}, "reason": {"type": "string"}}}}}}, max_output_tokens=600).json
by_org = {}
for r in res["risks"]:
t = tickets[r["n"]]
by_org.setdefault(t.get("organization_id") or "No organisation", []).append(f" #{t['id']} {r['reason']}")
if by_org:
notify.slack("Possible churn risk:\n" + "\n".join(f"• Org {o}\n" + "\n".join(v) for o, v in by_org.items()), channel="#customer-success")
return {"flagged": len(res["risks"])}FAQ
Common questions
Which tickets does it read?
Does it change anything in Zendesk?
What if nothing looks risky?
What permissions does it need?
Does it need AI?
How many runs does it use?
Can I change how it works?
Related
You might also like
Post weekly support numbers to Slack
Every Monday, Slack shows last week's new and solved tickets and the median first reply time, compared with the week before.
See how it worksSummarise and prioritise new Zendesk tickets with AI
Each new ticket gets a short summary, a sentiment and a priority, and the urgent ones are flagged in Slack.
See how it worksFollow each Zendesk ticket in its own Slack thread
Every new ticket appears in Slack, and each reply or status change lands in that ticket's thread.
See how it worksKeep exploring
Set up “Spot customers at risk of leaving from their tickets” from your assistant
Copy the prompt above, or connect your assistant first. Free plan, no credit card.