Compare / JevModel

Email Classification with AI: Rules, LLM Prompts, or a Typed Decision API for Inbound Mail

Route inbound email to support, sales, billing, vendor, or low-value queues: how to trim threads and signatures, compare rules, LLM prompts and typed APIs, and send the mid-band to people.

Last updated:

Quick answer: classify the newest message, not the whole mailbox

  • Email classification assigns each inbound message to one bounded route—such as support, sales, billing, vendor, or low-value outreach—before any automation replies, refunds, or forwards it.
  • Email-specific work happens before the model: strip quoted replies, signatures and legal footers, keep subject, sender domain and recipient alias, and describe attachments as metadata because a text-only model cannot open them.
  • Rules handle known senders and aliases cheaply; LLM prompts handle messy prose but drift; a typed decision API such as JevModel’s Choice plus Noul returns a fixed label set with probabilities, so you can auto-route the high band and send the mid-band to people.

What makes email classification different from ticket or intent classification?

A support ticket usually arrives as one clean description. An email arrives as an envelope: From, To and Reply-To headers, a subject that may say “Re: Fwd: Invoice”, the newest reply on top, several quoted messages underneath, a signature, a confidentiality footer, and sometimes attachments. The route depends mostly on the newest human-written paragraph plus a few headers—which alias it was sent to, whether the sender domain belongs to a customer or a vendor, and whether it is an automatic reply or a bounce. If you send the raw message, the model reads the quoted history and the footer as evidence and often picks the topic of a message from three weeks ago. Intent classification asks what the writer wants; email classification first has to decide which part of the email is the writer speaking now. For queue design itself, see support-triage; for intent labels across channels, see intent-classification.

Route customer support with JevIntent Classification for Product & Support Text: Rules, LLMs, and Typed APIs

Rules vs LLM prompts vs a typed decision API for inbound email

Most production inboxes end up with all three layers: rules for facts you already know, a model for the prose, and code that applies thresholds. The table compares maintenance and failure modes; it is not a benchmark, and none of the options replaces a labeled test set from your own mail.

How to classify text with the JevModel APIJev or rules?Jev vs GPT and Claude: choosing a decision layer
Rules vs LLM prompts vs a typed decision API for inbound email
DimensionMail rules / filtersLLM prompt + parseTyped API (JevModel Choice/Noul)
Best signalHeaders: recipient alias, known sender domains, auto-reply and bounce markersThe body: paraphrases, mixed requests, polite indirect wordingThe trimmed body plus headers, scored against written criteria for each route
Typical failureMisses new wording; rule lists grow until nobody knows which one firedReads quoted history as current; invents labels; JSON shape drifts after prompt editsWeak criteria produce spread-out probabilities; long threads must be trimmed to fit the state limit
UncertaintyNone—a rule fires or it does notSelf-reported confidence text, hard to calibratePer-option probabilities you can threshold and check against labels

How should you prepare an email before sending it to a classifier?

Do the email parsing in your own code, then send a small JSON state. Keep: the subject with “Re:” and “Fwd:” prefixes removed, the recipient alias (billing@, sales@), the sender domain and whether it is on your customer or vendor list, and the newest message body. Remove: quoted replies (lines starting with “>” and blocks after “On … wrote:”), signatures, confidentiality footers, tracking pixels, and HTML. For a forwarded chain, keep the forwarder’s note plus a short excerpt of the original sender’s first paragraph, labeled as forwarded. For attachments, pass only filenames and types—JevModel accepts text or JSON, not files or images, so “invoice.pdf attached” is a hint, not evidence of what the PDF says. In JevModel the serialized state and the full request must each fit within 8,000 characters, which a trimmed email almost always does. The example asks one Choice question for the route and one Noul question for whether a person should look now.

JevModel API: request and responseChoice, Score, and NoulIs Jev a Multimodal / Downloadable Model? What JevModel Actually Is
{
  "state": {
    "subject": "Invoice 2291 charged twice",
    "to_alias": "billing@",
    "sender_domain": "customer-example.com",
    "sender_known_as": "customer",
    "latest_message": "Hi, our card was charged twice for invoice 2291 this morning. Can you refund the duplicate?",
    "attachments": [
      "receipt.png (not read)"
    ]
  },
  "questions": {
    "route": {
      "type": "choice",
      "instructions": "Which team should own the newest message in this email? Ignore attachment names as evidence.",
      "criteria": {
        "support": "Product questions, bugs, how-to or account access problems.",
        "sales": "Pricing, plans, demos, procurement or purchase questions from prospects.",
        "billing": "Charges, refunds, invoices, receipts or payment method changes.",
        "vendor": "Messages from suppliers or partners about their own services or invoices to us.",
        "low_value": "Cold outreach, newsletters, automatic notifications needing no action."
      }
    },
    "needs_person_now": {
      "type": "noul",
      "instructions": "Should a person read this email today instead of waiting in a queue?",
      "criteria": {
        "true": "Money, access, legal or a clear deadline is at stake today.",
        "false": "It can wait in the normal queue."
      }
    }
  }
}

How should confidence thresholds route email to people?

Use three bands per route, set on your own held-out mail. High band: move the email to the team’s folder or queue and add a label—low-risk, reversible actions. Mid-band: put it in a shared review view with the top two suggested routes attached; this is where mixed emails (“thanks for the demo, also our invoice is wrong”) land. Low band or a near-tie between two routes: leave it in the general inbox. Never let a route label alone trigger an irreversible step such as a refund, a contract reply, or deleting the message; require a separate check in code, and use a Noul question like needs_person_now to pull urgent mail forward regardless of route. Re-tune the bands per alias, because billing@ and info@ carry very different mixes. The general pattern is described in confidence-and-abstention.

Jev probability, confidence and human-review thresholdsAI Decision Flows with Jev and human review

How do you regression-test an email classifier?

Build fixtures from real, anonymized mail and freeze them. Cover the shapes that break email routing specifically: a reply whose quoted history is about a different topic, a forwarded chain where the forwarder adds only “see below”, an out-of-office reply, a delivery bounce, a vendor invoice sent to billing@ (vendor, not billing), a customer writing from a personal address, a message in a second language, and a mixed request that should land in the mid-band. Run the parser and the classifier together, because most regressions come from trimming changes, not from the model. In JevModel’s Console → Batch you can upload CSV, TXT or JSONL rows with one fixed question and export row-level answers, then join them to your labels in a script; Batch does not compute accuracy for you. Fail the change if golden routes flip or if mid-band fixtures stop abstaining. See evaluation and batch-text-classification-api for the mechanics.

Evaluate a Jev workflowBatch text classification with the JevModel API

When does JevModel fit email routing, and when does it not?

JevModel is a hosted decision API: you POST a trimmed email as state plus 1–8 named questions to /api/v1/systemone, and it calls the fixed model typesafe/jev-1.13 through OpenRouter. It fits when several services—a mail worker, a help desk, a CRM sync—must share one route definition with probabilities, and when you want the mid-band to reach people instead of guessing. Choice supports 2–12 routes, Score rates ordered levels such as urgency, and Noul answers yes/no questions with a probability. It does not fit as a spam or phishing filter—keep your mail provider’s spam and sender-authentication checks in front of it. It cannot read attachments, images, or scanned PDFs, it is not open source and has no downloadable weights, and free verified accounts get 5 successful runs per UTC day, so a busy shared inbox needs a paid plan or batch planning. For help-desk-specific setups, see zendesk-ai-ticket-classification.

JevModel pricing and free Jev runsZendesk AI Ticket Classification & Routing: Built-in Intelligent Triage vs a Custom ClassifierLLM-as-a-Judge: Free-Form Prompts, Rubric Scoring, or a Typed Judge with AbstentionRoute customer support with JevIntent Classification for Product & Support Text: Rules, LLMs, and Typed APIsJev probability, confidence and human-review thresholdsBatch text classification with the JevModel APICustomer Feedback Classification: One Theme, a Priority Score, and Why Sentiment Is Not Enough

Frequently asked questions

Can an AI email classifier read attachments?

JevModel cannot: it accepts text or JSON only. If an attachment matters, extract its text with your own OCR or parser first and pass a short excerpt in state; otherwise pass only the filename and type as a hint.

Should I use an LLM or a decision API as my spam filter?

No. Leave spam, phishing and sender authentication to your mail provider. Use a classifier after that for business categories such as cold outreach, newsletters or automatic notifications that are legitimate mail but need no reply.

How is this different from the support-triage and Zendesk guides?

Those guides start from a ticket that already exists. This page covers the step before: turning a raw email with headers, quoted history, signatures and attachments into a clean state, and routing it across teams beyond support.

How do I choose the mid-band threshold for email?

Label a held-out set per alias, run it, and pick the lowest probability at which auto-routed mail is still correct often enough for your team’s tolerance. Everything between that point and your low band goes to review; re-check after parser or criteria changes.

JevModel is independent and not affiliated with TypeSafe AI.