Support ticket triage
Routes a support ticket or email to a team and assesses urgency, sentiment and the need for human review.
Example
Context
- company
- An online shop selling outdoor clothing and camping gear across Europe.
- channel
Input
Subject: Wrong item in my parcel Hi, my order 88213 arrived today but the parcel had a large Alpine shell jacket instead of the medium I ordered. Please exchange it and send the medium before Saturday. Thanks, Marta
Labels (the options)
- orders
- Orders, deliveries, returns and exchanges
- payments
- Payments, refunds and invoices
- product
- Product questions, sizing advice and stock
- account
- Customer accounts, passwords and newsletters
- Answer (JSON)
- value orders, confidence 1
- Top options
- orders 1
- product 0
- payments 0
A wrong item to exchange is a matter for the orders team.
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.support.triage.route", context={ "company": "An online shop selling outdoor clothing and camping gear across Europe.", "channel": "email", }, labels={ "orders": "Orders, deliveries, returns and exchanges", "payments": "Payments, refunds and invoices", "product": "Product questions, sizing advice and stock", "account": "Customer accounts, passwords and newsletters", }) decision = decide("Subject: Wrong item in my parcel\nHi, my order 88213 arrived today but the parcel had a large Alpine shell jacket instead of the medium I ordered. Please exchange it and send the medium before Saturday. Thanks, Marta") print(decision.value, decision.confidence)
More examples
Charged twice for one orderanswer payments · confidence 1
Context
- company
- An online shop selling outdoor clothing and camping gear across Europe.
- channel
Input
Subject: Double charge Hello, my card was charged twice for order 88340, 129.00 each time, but I only placed one order. Please refund the extra payment. Regards, Henrik
Labels (the options)
- orders
- Orders, deliveries, returns and exchanges
- payments
- Payments, refunds and invoices
- product
- Product questions, sizing advice and stock
- account
- Customer accounts, passwords and newsletters
- Answer (JSON)
- value payments, confidence 1
- Top options
- payments 1
- orders 0
- product 0
A card charged twice for one order goes to the
paymentsteam.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.support.triage.route", context={ "company": "An online shop selling outdoor clothing and camping gear across Europe.", "channel": "email", }, labels={ "orders": "Orders, deliveries, returns and exchanges", "payments": "Payments, refunds and invoices", "product": "Product questions, sizing advice and stock", "account": "Customer accounts, passwords and newsletters", }) decision = decide("Subject: Double charge\nHello, my card was charged twice for order 88340, 129.00 each time, but I only placed one order. Please refund the extra payment. Regards, Henrik") print(decision.value, decision.confidence)
Which sleeping bag for winter?answer product · confidence 1
Context
- company
- An online shop selling outdoor clothing and camping gear across Europe.
- channel
- web form
Input
Is the Fjellbu 600 sleeping bag warm enough for camping in the mountains in February, around minus 10? Or should I take the 900?
Labels (the options)
- orders
- Orders, deliveries, returns and exchanges
- payments
- Payments, refunds and invoices
- product
- Product questions, sizing advice and stock
- account
- Customer accounts, passwords and newsletters
- Answer (JSON)
- value product, confidence 1
- Top options
- product 1
- orders 0
- account 0
A question about which sleeping bag is warm enough is for the
productteam.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.support.triage.route", context={ "company": "An online shop selling outdoor clothing and camping gear across Europe.", "channel": "web form", }, labels={ "orders": "Orders, deliveries, returns and exchanges", "payments": "Payments, refunds and invoices", "product": "Product questions, sizing advice and stock", "account": "Customer accounts, passwords and newsletters", }) decision = decide("Is the Fjellbu 600 sleeping bag warm enough for camping in the mountains in February, around minus 10? Or should I take the 900?") print(decision.value, decision.confidence)
Stove that caught fireanswer true · confidence 1
Context
- company
- An online shop selling outdoor clothing and camping gear across Europe.
- channel
Input
Subject: Your stove set my tent on fire The gas stove I bought from you (order 87112) flared up on its first use and burned a hole in my tent. My hand was burned too. I want to know what you are going to do about this.
- Answer (JSON)
- value true, confidence 1
- Top options
- true 1
- false 0
A stove that set a tent on fire and burned the customer is a safety complaint, so it needs a person and the answer is
true.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.support.triage.needs_human", context={ "company": "An online shop selling outdoor clothing and camping gear across Europe.", "channel": "email", }) decision = decide("Subject: Your stove set my tent on fire\nThe gas stove I bought from you (order 87112) flared up on its first use and burned a hole in my tent. My hand was burned too. I want to know what you are going to do about this.") print(decision.value, decision.confidence)
Password reset questionanswer false · confidence 1
Context
- company
- An online shop selling outdoor clothing and camping gear across Europe.
- channel
- chat
Input
hi how do I reset my password? the link on the login page is where?
- Answer (JSON)
- value false, confidence 1
- Top options
- false 1
- true 0
Where to find the password reset link can be answered automatically, so the answer is
false.import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.support.triage.needs_human", context={ "company": "An online shop selling outdoor clothing and camping gear across Europe.", "channel": "chat", }) decision = decide("hi how do I reset my password? the link on the login page is where?") print(decision.value, decision.confidence)
Use when
- Each ticket, email or chat message needs a team assignment, urgency rating and human-review decision.
- You want to use your own team list, with a short description of each team.
Avoid when
- You need to write a reply; this adapter returns decisions without generating text.
- The decision depends on facts outside the message, such as order history; include them in the request or handle them in code.
Context and input
| Field | Kind | Description |
|---|---|---|
message | input | The ticket or email as received, including subject line, quoted thread and signature. |
company | context | One sentence about the organisation the message is sent to. |
channel | context | Where the message came from, for example email, web form, chat, app review, social media reply or phone transcript. |
Functions
| Key | Interface | Instructions | Labels |
|---|---|---|---|
| route | route | Which team should handle this message? If it covers several issues, choose the team for the most important one. | from the caller |
| urgency | rate | How urgently does this need a response? | No action needed, Can wait a few days, Handle within a day, Handle within hours, Handle immediately |
| sentiment | rate | How does the customer feel? | Very negative, angry or distressed, Negative, Neutral, Positive, Very positive |
| needs_human | requires_escalation | Does this need a person to act on it now, rather than an automatic reply? Answer yes for complaints that could escalate, legal or safety issues, or requests an automatic system cannot resolve. | false, true |
How it was measured
Test accuracy: the share of test rows whose top answer was right.
- 91.2% on the in-house test (7,256 rows). in-house: same generator as the training data
When confident
From the calibration set: at or above the threshold confidence, how often the answer is right, and how often the adapter is that confident. Below it, escalate.
| Function | Right when confident | Confident on | Threshold | Calibration rows |
|---|---|---|---|---|
| route | 95.1% | 100.0% | 0.43 | 367 |
| urgency | 95.0% | 59.9% | 0.79 | 367 |
| sentiment | 95.0% | 88.0% | 0.69 | 367 |
| needs_human | 98.9% | 100.0% | 0.54 | 367 |
Base: Jeff v1.4. Adapter trained: 25 October 2026.
Base
jeff-base v1.4
Call it
jeff.support.triage.route, with placeholders for its input and context.
import os import jeff with jeff.Jeff.remote("https://api.jeffhub.ai", token=os.environ["JEFF_API_KEY"], timeout_s=30) as client: decide = client.function("jeff.support.triage.route", context={ "company": "<company>", "channel": "<channel>", }) decision = decide("<message>") print(decision.value, decision.confidence)
Download
Weights: mstrasser/jeff-adapter-triage (v1.4)
Licence: Apache-2.0