Smart Routing
Replace hundreds of if/else rules with one AI classifier. Build real intent detection that routes data to the right team — with confidence scoring, fallback handling, and production error patterns.
Why AI Routing Beats Rules Engines
A rules engine works until it does not. You write if subject.contains("invoice") and it routes billing emails — until a customer writes "my invoice is broken and I need help resetting my password." That is two intents in one message. A rules engine picks one (usually wrong). An AI classifier reads the full context and decides.
• Fails on ambiguous or novel inputs
• 50+ rules become unmaintainable
• Cannot handle multi-intent messages
• Breaks silently when language changes
• Reads full context, not just keywords
• Returns confidence scores for safety
• One model replaces hundreds of rules
• Adapts as language evolves
Architecture: How Smart Routing Works
The routing pipeline has four stages. An incoming message enters the AI classifier, which determines intent and confidence, then routes to the appropriate team.
The Implementation: Building an AI Classifier
Here is the complete, production-ready classifier using Claude. This is real code you can deploy today:
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic();
const SYSTEM_PROMPT = `You are an intent classifier.
Classify the message into exactly ONE intent.
Valid intents:
- billing_issue: invoices, payments, charges, refunds
- technical_support: bugs, errors, broken features
- sales_inquiry: pricing, demos, enterprise plans
- account_management: password reset, profile changes
- feature_request: suggestions, improvements
Respond ONLY with valid JSON:
{"intent": "...", "confidence": 0.0-1.0, "reasoning": "..."}`;
async function classifyIntent(message) {
const response = await client.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 150,
system: SYSTEM_PROMPT,
messages: [{ role: 'user', content: message }]
});
return JSON.parse(response.content[0].text);
}
The system prompt constrains Claude to return valid JSON with exactly three fields. This makes downstream processing reliable — you can always access result.intent and result.confidence without guessing the format.
The Router: Confidence Gating
Classification alone is not enough. You need a confidence threshold — a gate that catches uncertain classifications before they misroute data. This is the human-in-the-loop pattern:
const ROUTES = {
billing_issue: { team: 'billing', channel: '#billing-queue' },
technical_support: { team: 'support', channel: '#support-queue' },
sales_inquiry: { team: 'sales', channel: '#sales-queue' },
account_management: { team: 'support', channel: '#account-queue' },
feature_request: { team: 'product', channel: '#feature-requests' },
};
const CONFIDENCE_THRESHOLD = 0.8;
async function routeMessage(message) {
const classification = await classifyIntent(message);
// LOW CONFIDENCE → human review queue
if (classification.confidence < CONFIDENCE_THRESHOLD) {
return sendToHumanReview({
message,
suggested_intent: classification.intent,
confidence: classification.confidence,
reasoning: classification.reasoning
});
}
// HIGH CONFIDENCE → auto-route
const route = ROUTES[classification.intent];
if (!route) {
return sendToHumanReview({ message, reason: 'unknown_intent' });
}
await sendToSlack(route.channel, {
text: `New ${classification.intent} (${Math.round(classification.confidence * 100)}% conf)`,
message,
classification
});
// Log for monitoring and model improvement
await logClassification(message, classification, route);
}
This lesson is for Pro members
Unlock all 520+ lessons across 52 courses with Academy Pro.
Already a member? Sign in to access your lessons.