Triage a support ticket
Send each incoming ticket to the right team, flag refund requests, and put urgent ones first, with one call.
Keyword rules miss tickets written in Yorùbá, Pidgin or plain frustration, and a chain of LLM prompts is slow and gives answers you can’t threshold. A decision call asks all three questions in one pass and returns a calibrated probability for each, so you can act automatically when the model is sure and hand the rest to a person.
Run it
Section titled “Run it”pip install requestsexport OLAVERSE_KEY="your-key" # from https://console.olaverselab.compython triage.pyThe script
Section titled “The script”import os
import requests
URL = os.environ.get("OLAVERSE_URL", "https://api.olaverselab.com")HEADERS = {"Authorization": f"Bearer {os.environ['OLAVERSE_KEY']}"}
def call(path, body): r = requests.post(f"{URL}{path}", json=body, headers=HEADERS, timeout=120) r.raise_for_status() return r.json()
# The questions asked about every ticket. Option keys are yours; the descriptions are what the model reads.QUESTIONS = { "team": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "payments, charges and refunds", "delivery": "orders in transit, late or missing parcels", "account": "sign-in, profile and security"}}, "refund": {"type": "noul", "instructions": "The customer is asking for money back."}, "urgency": {"type": "score", "instructions": "How urgent is this?", "criteria": ["can wait", "normal queue", "today", "immediately"]},}SURE = 0.9 # act automatically at or above this probability; below it, a person decides
def triage(ticket): answers = call("/v1/decide", {"state": ticket, "questions": QUESTIONS})["answers"] team = answers["team"]["choice"] return { "queue": team if answers["team"]["probabilities"][team] >= SURE else "triage", "priority": "high" if answers["urgency"]["score"] >= 2 else "normal", "refund_review": answers["refund"]["noul"] >= SURE, }
if __name__ == "__main__": tickets = [ {"id": "T-1001", "channel": "whatsapp", "message": "Ẹ jọ̀ọ́, wọ́n ti yọ owó lẹ́ẹ̀mejì lórí káàdì mi. Mo fẹ́ kí ẹ dá owó mi padà."}, {"id": "T-1002", "channel": "email", "message": "Where is my parcel? It was due on Monday."}, {"id": "T-1003", "channel": "chat", "message": "I can't log in since I changed my phone number."}, ] for ticket in tickets: print(ticket["id"], triage(ticket)) # hand the result to your helpdesk hereTry it with curl
Section titled “Try it with curl”curl -X POST "https://api.olaverselab.com/v1/decide" \ -H "Authorization: Bearer $OLAVERSE_KEY" -H "Content-Type: application/json" \ -d '{"state": {"channel": "email", "message": "I was charged twice for order 1182, please refund me today"}, "questions": { "team": {"type": "choice", "instructions": "Which team should handle this?", "criteria": {"billing": "payments, charges and refunds", "delivery": "orders in transit", "account": "sign-in and security"}}, "refund": {"type": "noul", "instructions": "The customer is asking for money back."}, "urgency": {"type": "score", "instructions": "How urgent is this?", "criteria": ["can wait", "normal queue", "today", "immediately"]}}}'Response
Section titled “Response”What /v1/decide returns for the first ticket. Values are illustrative.
{ "model": "purplemist-mini-2.0", "answers": { "team": {"type": "choice", "choice": "billing", "probabilities": {"billing": 0.97, "delivery": 0.02, "account": 0.01}, "confidence": 0.88}, "refund": {"type": "noul", "noul": 0.96}, "urgency": {"type": "score", "score": 2.1, "probabilities": {"0": 0.03, "1": 0.17, "2": 0.46, "3": 0.34}, "legend": {"0": "can wait", "1": "normal queue", "2": "today", "3": "immediately"}, "confidence": 0.14} }, "usage": {"input_tokens": 312, "output_tokens": 0, "decisions": 3}}So the script prints T-1001 {'queue': 'billing', 'priority': 'high', 'refund_review': True}.
How the answer is used
Section titled “How the answer is used”- Thresholds mean what they say. Probabilities are calibrated, so 0.9 (
SURE) is right about 9 times in 10. Start there and tune it against a week of your own tickets. - Uncertain goes to a person. A team below
SURElands in atriagequeue instead of the wrong team. scoreis the expected level: 2.1 is “around today”, so the ticket is high priority. For the single most likely level, take the highest entry inprobabilities.- Connect your helpdesk where the script prints: create or update the ticket with the queue, priority and refund flag.
Adapt it
Section titled “Adapt it”- More teams: a
choicequestion takes up to 255 options. - More questions: add sentiment, language or “mentions a competitor” to
QUESTIONS; questions share one pass over the state, so they add no time. - A backlog:
POST /v1/decide/batchtakes 32 tickets per call ({"cases": [{"id": ..., "state": ..., "questions": ...}]}) and counts as one request against your rate limit.
DecisionsEvery question type and field.
Route messages by languageDetect the language before you decide.