Support Ticket Triage with CSV, Noul and Score
Produce exportable suggestions and a review queue without auto replying to customers.
Use caseRoute multilingual support messages by language, intent, urgency, and human review
Read one fictional ticket from a CSV and ask System One for language, intent, urgency, and a human-review signal. The result is a routing suggestion, never an automatic reply.
Source · JevLog original · Original guide
2026-09-23 update: read the sample CSV directly and combine triage into one request.
Problem
Section titled “Problem”Support messages often combine two requests, such as a late delivery and a refund. This fictional example classifies one ticket while keeping its original text and ID.
Before you begin
Section titled “Before you begin”- Use Python 3.10+, install
typesafe-sdk, and prepare a fictional CSV. Put TYPESAFE_API_KEY in an environment variable before a live request; do not use real customer data.
Sources
Section titled “Sources”
Ticket triage: labels stay suggestions until checked by a person. No automatic reply. AI concept art.
1. Load one sample ticket
Section titled “1. Load one sample ticket”Keep the sample CSV beside the script. The code finds ticket 7 by ID and retains its original text so you can check the suggestion.
2. Get a triage suggestion in one request
Section titled “2. Get a triage suggestion in one request”One request returns language, main intent, urgency, and a review signal. Noul gives a 0–1 review probability; Score gives a 0–2 weighted value from your defined scale. Both are suggestions, not proof that a label is correct.
import csvimport osfrom typesafe_sdk import Choice, Noul, Score, TypeSafeClient
assert os.environ.get("TYPESAFE_API_KEY"), "Set TYPESAFE_API_KEY before a live request"
with open("customer_feedback.csv", newline="", encoding="utf-8-sig") as f: ticket = next(row for row in csv.DictReader(f) if row["id"] == "7")
with TypeSafeClient() as client: result = client.system_one( state={"ticket_id": ticket["id"], "ticket_text": ticket["feedback"]}, questions={ "language": Choice( instructions="Detect the language used in this support ticket.", criteria={"zh": "Chinese", "en": "English", "mixed": "Chinese and English", "other": "Other or unclear"}, ), "intent": Choice( instructions="Choose the main support intent.", criteria={"billing": "Refund, charge, or invoice", "technical": "Login, bug, or outage", "shipping": "Delivery, tracking, or address", "other": "Other or unclear"}, ), "needs_human": Noul(instructions="Should a person review this ticket before any customer-visible action?"), "urgency": Score( instructions="Choose the urgency that best fits the ticket.", criteria=["Routine", "Soon", "Urgent"], ), }, )
suggestion = { "id": ticket["id"], "original": ticket["feedback"], "language": result.choices["language"].choice, "intent": result.choices["intent"].choice, "human_review_probability": result.nouls["needs_human"].noul, "urgency_score": result.scores["urgency"].score,}print(suggestion)3. Check the original, then route to a person
Section titled “3. Check the original, then route to a person”Set routing thresholds using tickets labeled by your team. Send urgent, conflicting, or flagged records to a person; replies, refunds, and order changes stay in your existing workflow.
Practice sample: download customer_feedback.csv (CSV Studio / local practice; not a live run here).
Check the result
Section titled “Check the result”Each suggestion keeps its ticket ID and original text; a person handles the review.
- The result keeps the ticket ID and original text.
- Urgent, conflicting, or flagged tickets go to a human queue.
Continue reading
Section titled “Continue reading”Why not auto-reply?
Section titled “Why not auto-reply?”A label can be wrong. Have a person check the original before the existing support workflow sends a reply.