ticket-triage
Published
Public
in @customer-support

Triage a support ticket: priority + category + the signals that drove the call, as strict JSON.

ticket-triage

Triage an inbound support ticket into a priority and a category, with the concrete signals that drove the decision — returned as strict JSON your code can route on.

Drop it at the front of a support queue to auto-prioritize, auto-route, and surface the "why" for every ticket. The optional productContext lets you tune severity to your own product (what's revenue-critical, what counts as an outage) without forking the prompt.

Entrypoints

EntrypointRendersInputs
systemTriage instructions + priority/category rubric + embedded output schemaoptional productContext
userThe delimited ticket block to triagetext

Render system as the system message and user as the user message.

Variables

  • text (string, required) — the ticket body (the customer's message). Subject + body works well.
  • productContext (string, optional) — operational context to inform severity, e.g. "Checkout is revenue-critical; auth outages are urgent; the legacy importer is deprecated." Folded into the severity judgment.

Output

parseOutput() returns:

{
  "reasoning": "Customer reports they cannot access any of their data, which blocks all use with no workaround.",
  "priority": "urgent",
  "category": "outage",
  "urgency_signals": ["cannot access any data", "blocks all work"],
  "confidence": 0.88
}
  • reasoning comes first by design — the model reasons, then commits to a priority. The system prompt pins the key order (reasoningprioritycategoryurgency_signalsconfidence).
  • priority is one of urgent / high / medium / low, judged on impact and scope, not tone. An all-caps rant about a cosmetic glitch is still low; a calm "I lost all my data" is urgent. The prompt explicitly refuses to inflate priority on customer insistence.
  • category is one closed-enum value: bug / billing / account / how_to / feature_request / outage / other.
  • urgency_signals are short, concrete phrases pulled from the ticket — never invented. Empty array when nothing stands out.
  • confidence is self-reported and ⚠️ not calibrated — a routing signal, not a probability.

House conventions

  • Triple-mustache input ({{{text}}}, {{{productContext}}}) so special characters in tickets are never HTML-escaped.
  • Grounded only in the ticket (plus product context if given) — no invented details, no severity inflation from tone.
  • Empty / non-ticket inputpriority: low, category: other, empty signals, confidence ≤ 0.3 (specified, not left to chance).
  • Strict schemaadditionalProperties: false, closed enums, complete required.

Notes

Verified by local render and live battle-test against the API. Suggested default model claude-sonnet-4-6 at temperature: 0 (carried in version metadata — override per call as you like).

@sufleur/