Classification

It’s opt-in. Turn it on per agent. You’ll get intent, entities, and urgency on mail from new senders. You don’t write the classifier. You don’t maintain it. We do.

On the event

Intent, entities and urgency on every first contact

Extract intent + entities + urgency from first-contact inbound via our 2-call classifier. Opt-in per agent on paid plans, no extra charge. Skip if your agent runs its own LLM — doing the work twice isn’t a feature.

Events / sarah

message.received18reply.received
  • tomas@harborlane.example41m agorequest_info0.28
  • ines@copperglen.example1h agoschedule_demo0.44
  • ravi@northpier.example2h agoquestion0.30
  • june@willowmere.example3h agodecline0.12
  • nadia@lanternfield.example4h agofollow_up0.40
  • omar@saltmarsh.example5h agomeeting_request0.36
  • keiko@foxgrove.example7h agoquestion0.22
  • bruno@ashbyquay.example9h agorequest_info0.31
  • sofia@millbrook.example12h agoschedule_demo0.47
  • theo@ravenstone.example1d agoquestion0.18
  • ama@kestrelbay.example1d agofollow_up0.26
  • yusuf@larkspur.example2d agodecline0.09
  • elise@tidewater.example2d agoquestion0.20
  • hugo@brambleworth.example3d agorequest_info0.15
message.receivedfrom priya@fernhollow.example
Event payload
{  "type": "message.received",  "intent": "schedule_demo",  "urgency": 0.62,  "injection_score": 0.02,  "sender_reputation": 0.81,  "entities": {    "date": "2026-10-14",    "time": "15:00"  }}
Webhook deliveryattempt 1
Statussucceeded
HTTP status200
reply.receivedtheir reply, later in the thread
Intentgeneral_reply
Urgency0.50

When to enable, when to skip

Classification is a speed layer for routing. If your own model already reads every message, it repeats work you have done.

  • Three signs you should turn it on

    • Your hot path is fast routing
    • You want entity extraction reused multiple places
    • You don’t want to maintain a classifier
  • Three signs you should leave it off

    • Your agent runs an LLM on every reply anyway
    • You only need the body + sender
    • You need exact-match intents we don’t ship

Our support agent switches on the intent label before our own model runs. Demo requests go straight to the calendar.

Leah OkaforHead of Platform at Tallowfin

Turn it on

One flag, per agent

Set classify_inbound when you create the agent. First-contact mail to it then arrives with intent, entities and urgency on the event.

// Needs Pro (5 agents): a second agent, classified at no extra charge
const client = createClient();
await client.agents.create("sarah", { classify_inbound: true });

client.agent("sarah").onMessage((msg) => {
  if (msg.intent === "schedule_demo") {
    return calendar.schedule(msg.entities);
  }
  if ((msg.urgency ?? 0) > 0.8) {
    return escalate.toHuman(msg);
  }
  // Fall back to your own LLM for cases the classifier didn't catch
  return llm.handle(msg.data.extracted_text);
});

The questions we get.

What does the classifier actually do?
Two LLM calls per first-contact message. Call 1 (~$0.0010) scores the message for prompt injection. Call 2 (~$0.0015) extracts intent, entities and urgency, plus a sender-reputation estimate: intents are free-form labels such as schedule_demo, with entities to match (a date and time for schedule_demo, for example). Total cost to us ~$0.0025 per classified message; it is included at no extra charge on paid plans.
Why is injection scanning included but classification is opt-in?
Injection scanning is security infrastructure — you can’t easily replicate it and you shouldn’t have to. It runs on inbound regardless of this flag. Classification is convenience infrastructure — your agent probably has its own LLM that does similar work. We don’t want to charge you twice for the same extraction.
What are the signs I should turn it on?

Your hot path is fast routing. You want switch (msg.intent) to handle the 80% common cases without an extra LLM call. Latency-sensitive support workflows benefit most.

You want entity extraction reused multiple places. msg.entities.date parsed once, used in calendar + CRM + notification handlers. Cheaper than running your own extractor each place.

You don’t want to maintain a classifier. We tune the prompt and pin the model version. You consume the output as a stable API.

What are the signs I should leave it off?

Your agent runs an LLM on every reply anyway. If your code is agent.onMessage((msg) => claude.complete(msg.data.extracted_text)), our pre-extraction is duplicated work.

You only need the body + sender. Simple acknowledgment agents that reply to ANY inbound the same way don’t need intent. The base inbound event already carries the reply text, sender and injection score.

You need exact-match intents we don’t ship. Intents are free-form labels such as schedule_demo. If you need domain-specific intents (e.g., legal-document review categories), build it yourself with a custom classifier.

Can I turn it on for some agents but not others?
Yes. classify_inbound: true is a per-agent flag. Enable it on the customer-service agent that benefits from fast routing; leave it off on the high-volume notification agent that just forwards body.
What if your classifier returns the wrong intent?
Your agent code should fall back to a default branch (the default case in your switch). The classifier won’t be perfect — it’s a speed optimization for the common cases, not a replacement for your agent’s reasoning.

Give your first agent an inbox

Free covers 3,000 emails and 3,000 inbound replies a month, with no card. Upgrade when your agents get busy.

Get your API key