← Back to Blog
ticket routingsupport automationclassificationproductionops

How to Route Support Tickets with Jev (Instead of Brittle Keyword Rules)

·2 min read

How to Route Support Tickets with Jev (Instead of Brittle Keyword Rules)

Most support ticket routing systems fail the same way. “Charged twice” goes to billing. “Not working” goes to tech. A ticket that says both flips a coin. Agents pay for every misroute in handle time and customer patience.

Jev ticket routing reads the whole ticket and returns a probability per queue. Mixed tickets show up as mixed distributions — visible, tunable, and safe to hand to humans when unsure.

TL;DR: One choice question with your real queue names (billing, tech_support, sales). If confidence < 0.7, enqueue for human triage. Log full distributions to catch drift early.


Why keyword routing breaks down

Failure mode What happens Cost
Overlapping keywords Ticket matches 2+ queues Wrong queue SLA
New product vocabulary Unknown words ignored Permanent misroutes
Multi-issue tickets One dominant keyword wins Partial resolution
Non-English slang Patterns miss Silent failures

Probabilistic ticket classification handles overlap by design: the distribution is the uncertainty.


Queue design that maps to code

Use labels that are exactly your downstream queue keys:

["billing", "tech_support", "sales"]

Avoid UI labels that need a mapping table (“Billing & Payments” → billing). If you must, keep a single mapping layer — not in every worker.

How many queues?

  • 3–5 is the sweet spot for choice questions.
  • More than ~7 smears probabilities.
  • Add one human_only bucket rather than stuffing “other” into existing queues.

What to put in the state

Subject: Charged twice for order #4821

I was charged twice for the same order #4821. Please fix this ASAP.
I already called support once and nobody helped.

Include: subject, body, product name, plan tier, error codes, order IDs.
Exclude: full payment instruments, unnecessary PII, internal notes you do not want the model to see.


The routing request

curl https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "typesafe/jev-1.13",
    "messages": [{
      "role": "user",
      "content": {
        "state": "<ticket text>",
        "questions": [{
          "type": "choice",
          "text": "Which team should handle this?",
          "options": ["billing", "tech_support", "sales"]
        }]
      }
    }]
  }'

Example answer:

{
  "selected": "billing",
  "confidence": 0.94,
  "distribution": {
    "billing": 0.94,
    "tech_support": 0.04,
    "sales": 0.02
  }
}

Confidence thresholds and human fallback

Confidence Action
≥ 0.9 Auto-assign
0.7 – 0.9 Auto-assign + notify lead if SLA-sensitive
< 0.7 Human triage queue

In benchmarks on support-like corpora, a 0.7 floor cuts auto-routes by only 8–12% while nearly eliminating wrong-queue incidents. Low-confidence fall-through is a feature, not a gap in the model.

if (answer.confidence < 0.7) return enqueue('human_triage');
return enqueue(answer.selected);

Production monitoring for ticket routing

  1. Log selected, confidence, full distribution, latency, ticket id.
  2. Entropy alerts — rising average entropy often appears weeks before accuracy drops.
  3. Queue mix dashboards — a sudden spike in other/human_triage after a product launch is expected; a slow bleed is not.
  4. Regression set — 50 historical tickets that were hard for agents, re-scored on deploys.

Multi-label and multi-issue tickets

One ticket with billing and tech issues: prefer two questions (primary queue, secondary queue) or a separate “multi-issue” flag question (Noul). Do not force one choice question to average two judgments.


Cost and latency vs LLM routers

Approach Latency Output Typical cost pattern
Chat LLM router 1–5s Prose / JSON to parse Prompt + completion tokens
Jev router 70–500ms Typed + distribution Input only (~$0.042 / 1M tokens)

For 100k tickets/day, the difference is not rounding error — and agents feel the latency in the tool UI.


FAQ

What about attachments and screenshots?
Jev takes text state. Extract text upstream (OCR, ticket form fields) and pass it in the state.

Can I use this for email and chat too?
Yes — same pattern. See message intent detection.

What if queues are highly specialized (20+)?
Cluster into 4–6 macro-queues first, then a second Jev call (or rules) for sub-queues.


Related reading