Most writing about support automation describes systems. This one follows a single ticket — an ordinary refund request — through every step, and notes what the automation did, what it declined to do, and where it was wrong.
The ticket is real in shape and anonymised in detail.
09:14 — Arrival
The email lands in a shared inbox:
Hi, I was charged twice for my March subscription. Order #48120. Can you sort this out? I already emailed last week and nobody replied.
Three things are true about this message and only one of them is the stated request. There is a billing issue, a claim of a prior contact, and an implicit complaint about response time. A classifier that only sees the first one will produce a technically correct, emotionally wrong reply.
09:14 — Classification
| Field | Value | Confidence |
|---|---|---|
| Category | Billing → Duplicate charge | 0.94 |
| Order reference | 48120 | 0.99 |
| Sentiment | Negative | 0.81 |
| Prior contact claimed | Yes | 0.88 |
The order number is extracted with near certainty because it matches a known format. Sentiment is the softest number here, and deliberately so — it routes tone, not action.
09:14 — The lookup that changes everything
The agent queries the billing system and finds something the customer did not mention:
- One charge on 3 March for the monthly plan
- One charge on 5 March for the annual plan
- A plan change recorded on 4 March
This is not a duplicate charge. It is an upgrade that was billed correctly, with a prorated overlap the customer did not expect.
The automation now knows the customer's premise is wrong. This is the exact case most support bots handle worst: they answer the question that was asked rather than the situation that exists.
09:15 — The escalation decision
Two rules fire at once:
- The extracted facts contradict the customer's stated premise
- The customer claims a prior contact with no reply on record
Either alone would allow an automated response with a human spot-check. Together they force a hard escalation. The agent writes a draft and hands it over rather than sending it.
Route: Billing queue, priority raised
Reason: premise_contradiction + unanswered_prior_contact
Draft: prepared, not sent
SLA: 4h → 1h
09:41 — The human
An agent reads the draft, keeps the explanation of the proration, deletes the sentence that opened with "Actually," and adds a line acknowledging the ignored first email. Total handling time: four minutes, against a manual baseline of roughly eighteen.
That gap is the entire return on the project. Not the deflection, the drafting.
What this ticket cost
| Step | Cost driver |
|---|---|
| Classification | One short model call |
| Extraction + lookup | One model call, two API reads |
| Escalation reasoning | Rule evaluation, no model call |
| Draft generation | One long model call |
| Human review | Four minutes |
The human review dominates, and it should. The design goal was never to remove the person from this ticket — it was to hand them a ticket that had already been read, matched against the billing record, and drafted against the real facts.
The lesson generalises past support. The most valuable thing an automation does is often not answering. It is noticing that the question contains a false premise, and saying so to the right person.