By Sagar Shankaran, Founder of CallSphere
Implement an AI-powered ticket classification system that automatically assigns priority, department, and SLA to incoming support requests using multi-label classification and intelligent routing rules.
Key takeaways
When a billing question lands in the engineering queue, two things happen: the engineer wastes time reading something they cannot act on, and the customer waits an extra cycle for re-routing. Studies show that misrouted tickets add an average of 4.2 hours to resolution time. At scale, this translates to millions in wasted labor and measurably lower customer satisfaction.
AI-powered ticket classification eliminates this bottleneck by analyzing the ticket content, assigning labels, priority, and department in under a second, and routing it to the right team before any human touches it.
Support tickets rarely fit a single category. A message like "My payment failed and now I can't access my account" spans both billing and technical access. The classifier must support multi-label output.
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
flowchart LR
USER(["Customer"])
CHANNEL{"Channel"}
CHAT["Chat agent"]
VOICE["Voice agent"]
EMAIL["Email agent"]
TRIAGE["Triage and<br/>intent detection"]
KB[("Knowledge base<br/>RAG")]
CRM[("CRM context")]
AUTORES{"Auto resolvable?"}
RESOLVE(["Resolved with<br/>cited answer"])
HUMAN(["Tier 2 agent"])
USER --> CHANNEL --> CHAT --> TRIAGE
CHANNEL --> VOICE --> TRIAGE
CHANNEL --> EMAIL --> TRIAGE
TRIAGE --> KB
TRIAGE --> CRM
TRIAGE --> AUTORES
AUTORES -->|Yes| RESOLVE
AUTORES -->|No| HUMAN
style TRIAGE fill:#4f46e5,stroke:#4338ca,color:#fff
style AUTORES fill:#f59e0b,stroke:#d97706,color:#1f2937
style RESOLVE fill:#059669,stroke:#047857,color:#fff
style HUMAN fill:#0ea5e9,stroke:#0369a1,color:#fff
from dataclasses import dataclass
from openai import AsyncOpenAI
import json
DEPARTMENTS = [
"billing", "technical", "shipping",
"account", "product", "legal"
]
PRIORITIES = ["low", "medium", "high", "urgent"]
@dataclass
class TicketClassification:
departments: list[str]
primary_department: str
priority: str
sla_hours: int
confidence: float
reasoning: str
CLASSIFICATION_PROMPT = """Analyze this support ticket and return a JSON object:
{
"departments": ["list of relevant departments"],
"primary_department": "the single most relevant department",
"priority": "low|medium|high|urgent",
"confidence": 0.0-1.0,
"reasoning": "brief explanation"
}
Departments: billing, technical, shipping, account, product, legal
Priority rules:
- urgent: service outage, security breach, legal threat
- high: payment failure, account locked, data loss
- medium: feature questions, general complaints
- low: feedback, feature requests, general inquiries
Ticket: {ticket_text}"""
async def classify_ticket(
client: AsyncOpenAI, ticket_text: str
) -> TicketClassification:
response = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": "You are a support ticket classifier. Return valid JSON only.",
},
{
"role": "user",
"content": CLASSIFICATION_PROMPT.format(
ticket_text=ticket_text
),
},
],
response_format={"type": "json_object"},
max_tokens=200,
)
data = json.loads(response.choices[0].message.content)
sla = compute_sla(data["priority"])
return TicketClassification(
departments=data["departments"],
primary_department=data["primary_department"],
priority=data["priority"],
sla_hours=sla,
confidence=data["confidence"],
reasoning=data["reasoning"],
)
SLA deadlines are computed from the priority level and department. Urgent billing tickets get a 1-hour SLA, while low-priority feedback might have a 72-hour window.
SLA_MATRIX = {
("urgent", "billing"): 1,
("urgent", "technical"): 2,
("urgent", "account"): 1,
("urgent", "shipping"): 4,
("urgent", "legal"): 2,
("high", "billing"): 4,
("high", "technical"): 4,
("high", "account"): 4,
("high", "shipping"): 8,
("medium", "billing"): 12,
("medium", "technical"): 12,
("medium", "shipping"): 24,
("low", "billing"): 48,
("low", "technical"): 48,
("low", "shipping"): 72,
}
def compute_sla(priority: str, department: str = "technical") -> int:
return SLA_MATRIX.get(
(priority, department),
{"urgent": 2, "high": 8, "medium": 24, "low": 72}[priority],
)
The routing engine maps classifications to specific teams and agents. It considers agent availability, current workload, and skill matching.
from typing import Optional
@dataclass
class Agent:
id: str
name: str
department: str
skills: list[str]
current_load: int
max_load: int
@dataclass
class RoutingDecision:
assigned_agent: Optional[Agent]
queue: str
sla_hours: int
priority: str
tags: list[str]
class TicketRouter:
def __init__(self, agents: list[Agent]):
self.agents = agents
def find_best_agent(
self, department: str, required_skills: list[str]
) -> Optional[Agent]:
candidates = [
a for a in self.agents
if a.department == department
and a.current_load < a.max_load
]
if required_skills:
skilled = [
a for a in candidates
if any(s in a.skills for s in required_skills)
]
if skilled:
candidates = skilled
if not candidates:
return None
# Assign to agent with lowest current load
return min(candidates, key=lambda a: a.current_load)
def route(self, classification: TicketClassification) -> RoutingDecision:
agent = self.find_best_agent(
classification.primary_department,
classification.departments,
)
queue = (
f"{classification.primary_department}-"
f"{classification.priority}"
)
return RoutingDecision(
assigned_agent=agent,
queue=queue,
sla_hours=classification.sla_hours,
priority=classification.priority,
tags=classification.departments,
)
The complete pipeline classifies, assigns SLA, and routes in a single async call.
async def process_new_ticket(
client: AsyncOpenAI,
router: TicketRouter,
ticket_text: str,
ticket_id: str,
) -> dict:
classification = await classify_ticket(client, ticket_text)
routing = router.route(classification)
return {
"ticket_id": ticket_id,
"classification": classification,
"routing": routing,
"auto_routed": routing.assigned_agent is not None,
}
Aim for 90%+ accuracy on your top five ticket categories before going live. Below that, misrouting causes more frustration than manual triage. Start by running the classifier in shadow mode — it classifies every ticket but a human still routes. Compare results for two weeks before switching to auto-routing.
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
Assign the ticket to the primary department but tag all relevant departments. The primary department agent resolves their portion and can transfer to secondary departments. This avoids the ticket sitting in limbo between teams.
Route low-confidence tickets (below 0.7) to a triage queue where a human reviews and classifies them. Log these cases as training data — they represent the boundary cases your classifier needs to improve on.
#TicketClassification #AutoRouting #SLAManagement #SupportAutomation #AIAgents #AgenticAI #LearnAI #AIEngineering

Written by
Sagar Shankaran· Founder, CallSphere
LinkedInSagar Shankaran is the founder of CallSphere, where he builds production AI voice and chat agents deployed across healthcare, hospitality, real estate, and home services. He writes about agentic AI, LLM engineering, and shipping voice agents that handle real calls in production.
See how AI voice agents work for your industry. Live demo available -- no signup required.
A founder's guide to the personal AI assistant market: best AI assistant apps, business-grade options, and how CallSphere's voice agent fits in.
A founder's guide to free AI agents, low-code AI agent builders, and how to know when you should pay for a real platform like CallSphere.
Graphiti is the open-source temporal knowledge graph for AI agents in 2026. Learn how bi-temporal memory beats vector RAG for voice agents and long-running LLMs.
Chatbot app vs ChatGPT in 2026: a founder's clear take on the difference, when to use which, and how a real AI chatbot app development works.
How we built a fault-tolerant HVAC emergency triage and tech-dispatch platform on Kubernetes — three-tier CQRS, 11 micro-agents on the OpenAI Agents SDK + LangGraph, NATS JetStream, DTMF/SMS/WebSocket acceptance, circuit breakers, and an evaluation pipeline that catches regressions before they wake a tech at 3 AM.
Head-to-head: OpenAI Frontier and Anthropic's managed agent stack — strengths, fit, and what each means for enterprise AI voice and chat deployment.
© 2026 CallSphere Inc. All rights reserved.
Made within San Francisco