Skip to content
RSFlowHub

How to Triage Support Tickets Automatically in Python

How to Triage Support Tickets Automatically in Python

Quick Answer

Send each new ticket to POST /api/v1/ai/ticket-analyze and read data.result. It returns the category, priority, sentiment, a one-line issue_summary, a suggested_department and a requires_human flag. Map those fields to your queues in a small Python function, and send anything with low confidence to a person.

A busy support inbox treats every ticket the same: first in, first out. An angry customer locked out of a paid account waits behind a question about invoice formats. In this tutorial you will build a small Python triage step that reads each new ticket, decides where it belongs and how urgent it is, and hands your helpdesk a clean summary. You need Python 3.9 or newer, the requests package and an RSFlowHub API key.

1. Why triage automatically

Manual triage is slow and inconsistent. Two agents label the same ticket differently, urgent tickets sit unread over a weekend and the people who are best at solving problems spend their time sorting. A triage step does three jobs before a human opens the ticket:

  • Classifies it: billing, account access, bug report, feature request and so on.
  • Ranks it: priority and urgency, so the worst problems are seen first.
  • Summarises it: one sentence an agent can read in two seconds.

The goal is not to replace your agents. It is to put the right ticket in front of the right person sooner. Anything the model is unsure about should go to a human, and the code below does exactly that.

2. Write the analysis helper

Keep your key in an environment variable and call the API from your backend only. The helper below retries once when the API answers with HTTP 429 and returns None on any other failure, so a problem with triage never blocks ticket creation.

triage.py Python
import os
import time

import requests

API_URL = "https://rsflowhub.com/api/v1/ai/ticket-analyze"


def analyze_ticket(ticket, subject=None, customer_context=None):
    """Return the analysis dict, or None if the ticket could not be analysed."""
    payload = {"ticket": ticket}
    if subject:
        payload["subject"] = subject
    if customer_context:
        payload["customer_context"] = customer_context

    headers = {
        "Content-Type": "application/json",
        "X-API-Key": os.environ["RSFLOWHUB_KEY"],
    }

    for attempt in range(2):
        try:
            res = requests.post(API_URL, json=payload, headers=headers, timeout=30)
        except requests.RequestException as exc:
            print(f"triage unavailable: {exc}")
            return None

        if res.status_code == 429 and attempt == 0:
            time.sleep(int(res.headers.get("Retry-After", "2")))
            continue

        if not res.ok:
            code = res.json().get("error", {}).get("code", res.status_code)
            print(f"triage failed: {code}")
            return None

        return res.json()["data"]["result"]

    return None

customer_context is optional but useful. A line such as Active Premium subscription, customer for 3 years helps the model weigh the ticket the way your own agents would. Do not put full personal records in it; send only what is needed to judge urgency. See how to redact personal data from tickets if tickets may contain card numbers or addresses.

3. Read the result

A successful call returns the standard RSFlowHub envelope. The analysis is inside data.result:

Example response JSON
{
  "success": true,
  "request_id": "req_7f3a9c2d1e4b8a6f",
  "data": {
    "result": {
      "category": "account",
      "intent": "restore_access",
      "sentiment": "negative",
      "priority": "high",
      "urgency": "high",
      "issue_summary": "Customer is unable to access their account due to password reset failures.",
      "key_problem": "Password reset mechanism not restoring account access.",
      "requires_human": true,
      "suggested_department": "account_support",
      "recommended_action": "assign_agent",
      "language": "en",
      "confidence": 0.96
    }
  }
}
Field Use it for
category, intentWhich queue or label the ticket gets, and what the customer wants.
priority, urgencySort order and SLA clock in your helpdesk.
sentimentFlag unhappy customers for a more careful reply.
issue_summary, key_problemThe text an agent reads first.
suggested_department, recommended_actionAutomatic assignment hints.
requires_human, confidenceWhether a person must handle it, and how sure the model is.

4. Turn the result into routing

Keep the decision logic in your own code, not inside a prompt. That way you can read it, test it and change it without touching the API. Start small: one function that returns a queue name and a flag for human review.

routing.py Python
from triage import analyze_ticket

MIN_CONFIDENCE = 0.7

# Your own queue names. Unknown values fall back to "general".
QUEUES = {
    "billing_support": "billing",
    "account_support": "accounts",
    "technical_support": "engineering",
}


def route_ticket(ticket, subject=None):
    analysis = analyze_ticket(ticket, subject)

    # The API failed: never block the ticket, put it in the general queue.
    if analysis is None:
        return {"queue": "general", "priority": "normal", "needs_review": True, "summary": None}

    unsure = analysis.get("confidence", 0) < MIN_CONFIDENCE
    return {
        "queue": QUEUES.get(analysis.get("suggested_department"), "general"),
        "priority": analysis.get("priority", "normal"),
        "needs_review": bool(analysis.get("requires_human")) or unsure,
        "summary": analysis.get("issue_summary"),
    }

Notice the two safety nets. If the API is unreachable, the ticket still lands in a queue. If the model is unsure or says a person is required, needs_review is true and an agent looks before anything automatic happens. Automation should make good tickets faster, not hide bad ones.

5. Process a backlog without hitting limits

When you first switch triage on you will want to label the tickets already in your helpdesk. Each plan has a per-minute request limit, so use a small worker pool instead of firing hundreds of calls at once.

backfill.py Python
from concurrent.futures import ThreadPoolExecutor

from routing import route_ticket


def backfill(tickets, workers=3):
    """tickets: list of dicts with 'id', 'subject' and 'body'."""
    with ThreadPoolExecutor(max_workers=workers) as pool:
        results = pool.map(lambda t: (t["id"], route_ticket(t["body"], t["subject"])), tickets)
        return dict(results)

Three workers is a safe start. If you see HTTP 429 responses, lower it; the helper already waits for the Retry-After value once. The limits and credits guide lists the limit for each plan and explains how calls are billed.

6. Test with realistic tickets

Before connecting triage to your live helpdesk, run a handful of real (anonymised) tickets and read the output yourself. Include the awkward ones: a short angry message, a long rambling one, a ticket in another language and one that is not really a support request.

try_triage.py Python
from routing import route_ticket

samples = [
    ("I cannot log in. It keeps saying invalid password even after resetting it.", "Login issue"),
    ("Can you send me last month's invoice as a PDF?", "Invoice"),
    ("Your app crashed twice today and I lost my work. This is the third time!", "Crash"),
    ("Thanks, that fixed it.", None),
]

for body, subject in samples:
    print(route_ticket(body, subject))

Check that urgent tickets rank higher than routine ones, that the summaries are accurate, and that the closing "thanks" message does not create work. Adjust MIN_CONFIDENCE and your queue map until the results match how your team would have sorted the same tickets.

7. Common mistakes to avoid

  • Trusting the output blindly. Treat the result as a recommendation. Keep a human in the loop for low confidence and for requires_human.
  • Blocking ticket creation on the API. Triage should be a bonus step. If it fails, create the ticket anyway.
  • Hard-coding department names from examples. Map values to your own queues and give unknown values a default.
  • Sending secrets in the ticket body. Remove card numbers and passwords before analysis.
  • Calling the API from the browser. The key must stay on your server.
  • Never measuring. Compare automatic labels with what agents change. If they correct the same label often, adjust your routing rules.

Triage Every Ticket with One API Call

Ticket analysis returns category, priority, sentiment, a short summary and a routing hint in one JSON response. It works from Python, Node.js, PHP or any backend.

View Ticket Analysis API →

Key Takeaways

  • Call POST /api/v1/ai/ticket-analyze from your backend for every new ticket.
  • Read category, priority, sentiment, issue_summary and suggested_department from data.result.
  • Keep routing rules in your own code and map results to your own queues.
  • Send low-confidence tickets and those with requires_human set to a person.
  • Never block ticket creation if the API fails; fall back to a general queue.
  • Use a small worker pool for backlogs and respect the Retry-After header on HTTP 429.

Frequently Asked Questions

It returns category, intent, sentiment, priority, urgency, issue_summary, key_problem, requires_human, suggested_department, recommended_action, language and confidence inside data.result.

It returns a suggested department and recommended action, but your own code decides what to do with them. This keeps routing rules under your control and easy to test.

Send the ticket to a person. A threshold such as 0.7 is a sensible starting point; tune it by comparing automatic labels with what your agents change.

Yes. The response includes the detected language, and the same call handles tickets written in many languages.

Each plan has a per-minute request limit. Over the limit the API returns HTTP 429 with a Retry-After header. See the limits and credits guide for your plan.

Ticket analysis only classifies and summarises. A separate ticket reply endpoint can draft a response, and a person should review drafts before they are sent.

Reviews & Discussion (0)

0

Based on 0 ratings

5 ★
0%
4 ★
0%
3 ★
0%
2 ★
0%
1 ★
0%
Write a Review or Comment
No rating selected
No comments yet

Be the first to share your thoughts on this article!

Unified AI Access ⚡

One API Key. Infinite Possibilities.

Get access to OpenAI, Anthropic, Gemini, and more through a single, secure gateway. Start building in minutes with zero setup friction.

RSFlowHub

Sign in to continue

You'll come straight back to this page.

Forgot password?

New to RSFlowHub? Create a free account