← How I Built It
Claude Haiku 4.5

How I built the Email Triage demo

Read an inbound email once, and come out the other side with a category, an urgency level, who should own it, and a draft reply — the four decisions a human triaging a shared inbox actually makes.

Last reviewed

Evidence typeModel demonstration — Claude Haiku 4.5 processes the real email text a visitor submits, live, via the production endpoint; this page's benchmark (8 hand-authored synthetic emails, run 2026-08-02) is reported below, not pre-scripted.

The problem

A shared inbox mixes sales inquiries, support tickets, complaints, spam, and the occasional legal notice. Triage isn't one decision — it's classify, prioritize, route, and often draft a first response, all before anyone with the right context has read the message.

One call, seven fields

Rather than chain separate classify → route → draft calls, the route asks for one JSON object with all seven fields at once: category, urgency, sentiment, routing destination, a one-line summary, a suggested reply, and extracted key entities. Fewer round trips, and the fields stay consistent with each other since one call reasons about all of them together.

The four classification fields are closed enums, not free text; summary, suggested reply, and key entities are free text

category: Sales | Support | Complaint | Partnership | Spam | Internal | Invoice | Legal

urgency: low | medium | high | critical

sentiment: positive | neutral | negative | frustrated | urgent

routeTo: Sales | Support | Finance | Legal | Management | Spam | HR

Why enums, not open categories

An open-ended "category": string field looks more flexible, but it pushes the hard part downstream: whatever consumes this output — a routing rule, a dashboard filter, a ticketing integration — now has to handle arbitrary strings a model might invent. Naming the exact set of allowed values in the prompt turns validation into a one-line membership check instead of fuzzy string matching against however the model phrased something this time. It's a small constraint that removes an entire category of downstream bugs.

Labeled benchmark

Run 2026-08-02

Model

Claude Haiku 4.5 (claude-haiku-4-5-20251001)

Sample size

8 synthetic emails

Data source

8 hand-authored synthetic emails (complaint, sales inquiry, invoice, security incident, partnership pitch, spam, internal HR note, legal notice) run live against the production endpoint at tioga.ai.

Category exact-match

8/8 (100%)

Urgency exact-match

5/8 (63%)

Successful classifications

8/8 (HTTP 200)

Average latency

~1.8s

Limitations

  • —Urgency is inherently more subjective than category — all 3 mismatches were one severity level off (e.g. "high" vs "critical"), and every miss erred toward flagging higher urgency, not lower.
  • —Sample size is small (8 cases) and hand-authored; a production engagement would calibrate urgency thresholds against your team's actual triage decisions.
  • —Sentiment and routing fields weren't scored in this run — only category and urgency.