We are going to build a support ticket triage agent that reads unstructured customer messages, extracts intent and entities, and routes each ticket to the correct team. This kind of natural language understanding pipeline replaces brittle regex rules and cuts response time dramatically. Because Oxlo.ai charges a flat rate per request rather than per token, running this on long support threads or in large batches stays predictable and cheap.
What you'll need
Before starting, make sure you have the following:
- Python 3.10 or newer installed locally
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Connect to Oxlo.ai and test the endpoint
I always start with a smoke test. This confirms the API key and base URL are correct before I add any logic. I use llama-3.3-70b because it follows structured instructions reliably.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Say 'Connection to Oxlo.ai is working' and nothing else."},
],
)
print(response.choices[0].message.content)
Step 2: Write the NLU system prompt
The system prompt is the contract. It tells the model exactly what to extract and how to format the output. I want three intents, three urgency levels, and specific entities returned as clean JSON.
SYSTEM_PROMPT = """You are an NLU engine that analyzes customer support tickets.
Read the user message and extract the following fields in JSON format:
- intent: one of [billing, technical, account_access]
- product: the product mentioned, or null
- user_id: any user ID, email, or account number, or null
- urgency: one of [low, medium, high]
- summary: a one-sentence summary of the issue
Rules:
- Output ONLY valid JSON.
- Do not add markdown fences or explanations.
- If a field is missing, use null."""
Step 3: Build the extraction function
Now I wrap the API call in a function that injects the system prompt and parses the JSON. I set response_format to JSON mode so the model stays on track, then parse the result with the standard library.
import json
def analyze_ticket(ticket_text: str) -> dict:
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": ticket_text},
],
response_format={"type": "json_object"},
)
raw = response.choices[0].message.content
return json.loads(raw)
# Quick test
test = "My AcmeWidget 3000 keeps flashing red and won't sync to my account u-88421."
print(analyze_ticket(test))
Step 4: Batch process a queue and route to teams
With the extraction working, I can process a list of tickets and map intents to team inboxes. I keep the routing logic in pure Python so I can change it without touching the prompt.
tickets = [
"I was charged twice for my Pro plan this month. Account bob@example.com.",
"The API returns a 500 error every time I send a request with unicode characters.",
"I forgot my password and the reset email never arrives. User ID u-99123.",
]
TEAM_MAP = {
"billing": "finance@company.com",
"technical": "engineering@company.com",
"account_access": "support@company.com",
}
for text in tickets:
nlu = analyze_ticket(text)
team = TEAM_MAP.get(nlu["intent"], "support@company.com")
print(f"Ticket: {nlu['summary']}")
print(f" Intent: {nlu['intent']} | Urgency: {nlu['urgency']}")
print(f" Route to: {team}\n")
Run it
Save the full script as triage.py, replace YOUR_OXLO_API_KEY, and run python triage.py. You should see output like this:
Ticket: User reports double charge for Pro plan
Intent: billing | Urgency: high
Route to: finance@company.com
Ticket: API returns 500 error on unicode requests
Intent: technical | Urgency: high
Route to: engineering@company.com
Ticket: Password reset email not received for user
Intent: account_access | Urgency: medium
Route to: support@company.com
Next steps
Swap llama-3.3-70b for kimi-k2.6 or deepseek-v3.2 if you need stronger reasoning on ambiguous tickets. You can also persist the extracted JSON to Postgres and wire this into a Slack bot so the routing happens in real time as tickets arrive.
Top comments (0)