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

FieldValueConfidence
CategoryBilling → Duplicate charge0.94
Order reference481200.99
SentimentNegative0.81
Prior contact claimedYes0.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:

  1. The extracted facts contradict the customer's stated premise
  2. 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

StepCost driver
ClassificationOne short model call
Extraction + lookupOne model call, two API reads
Escalation reasoningRule evaluation, no model call
Draft generationOne long model call
Human reviewFour 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.