Use cases · Saina Helm 2

Route and prioritize support tickets with a decision model

Pick the team, set the priority and flag what needs a person, from the ticket text, in one call. How to triage support tickets with Saina Helm 2 instead of keyword rules or a chat-model prompt, with thresholds that send unsure cases to review.

Saina · Updated October 16, 2026

In short: Send the ticket as the state and ask three typed questions: which team, how urgent, does it need a person. Helm scores every option and you set a threshold; everything below it goes to a review queue instead of the wrong team. One request, no prompt to maintain, and it runs on a CPU next to your helpdesk.

Model

Saina Helm 2

Reads

Text

Fits

Tickets, chats, forms and emails arriving in a helpdesk or an n8n workflow

The step

“We get 700 internal tickets a week and L1 spends most of the morning re-categorizing what the form put in the wrong queue. I don’t want a chatbot answering them. I want the right team to see the right ticket first.”

What a helpdesk lead asks for, paraphrased from the threads we read every day

Triage is the step before any answer gets written: who owns this, how soon, and does it need judgement. It is almost always one of three things today.

The job is not writing; it is picking between options you already know. That is what a decision model does, and nothing else.

What the request looks like

{
  "model": "saina-helm-2-0.8b",
  "state": "Nobody on our team can sign in since this morning. SSO says
'identity provider error'. Customer demo at 2pm.",
  "mode": "decision",
  "threshold": 0.7,
  "min_margin": 0.2,
  "questions": {
    "team": {
      "type": "single_choice",
      "question": "Which team should own this ticket?",
      "options": {
        "it_access":  "Accounts, sign-in, SSO, permissions",
        "billing":    "Charges, invoices, plan changes",
        "product":    "Bugs and errors inside the product",
        "facilities": "Office, hardware, equipment"
      }
    },
    "priority": {
      "type": "rating",
      "question": "How urgent is this?",
      "levels": ["Low", "Normal", "Urgent"]
    },
    "needs_person": {
      "type": "yes_no",
      "question": "Does this need a person rather than a self-service article?"
    }
  }
}

And what comes back:

{
  "answers": {
    "team": {
      "type": "single_choice",
      "selection": "it_access",
      "reason": "accepted",
      "probabilities": {
        "it_access": 0.91,
        "product": 0.06,
        "billing": 0.02,
        "facilities": 0.01
      },
      "confidence": 0.88
    },
    "priority": {
      "type": "rating",
      "expected_level": 1.86,
      "reason": "accepted",
      "probabilities": {
        "0": 0.02,
        "1": 0.1,
        "2": 0.88
      },
      "levels": [
        "Low",
        "Normal",
        "Urgent"
      ],
      "level": 2,
      "confidence": 0.86
    },
    "needs_person": {
      "type": "yes_no",
      "yes": 0.83,
      "no": 0.17,
      "confidence": 0.66,
      "selected": true,
      "reason": "accepted"
    }
  }
}
team · threshold 0.70
it_access0.91
product0.06
billing0.02
facilities0.01

Illustrative answer: the shape and fields are exact, the numbers show what a clear ticket looks like. Run your own tickets in the playground to see real scores.

Three answers from one read of the ticket, each keyed by the ID you chose. reason: "accepted" means the pick cleared your threshold and margin. When it doesn’t, you get below_threshold, below_margin or tie instead of a guess, with the scores attached, and the ticket goes to a person. Nothing is dropped and nothing is invented: the model can only score the teams you listed.

Putting it in place

Start from last month’s tickets

You don’t need labels to start, but you need a bar. Take a few hundred closed tickets and use the team that finally resolved each one as the label. Run them through Helm in distribution mode, look at where the top score lands for the ones it got right and the ones it got wrong, and set threshold and min_margin from that. Measure wrong-team transfers and the share sent to review, not just accuracy; a router that sends 20% to review and never mis-routes is often the one the team wants.

Run it in shadow mode first

Let the form or the rules keep routing for a week while Helm scores in parallel and logs its pick. Compare, tune the thresholds, then flip.

Wire it in

In n8n, the Saina Helm node has two outputs, Selected and Fallback: connect Selected to your Switch on team, and Fallback to the review queue. The node is for self-hosted n8n and ships with a “Route support tickets to the right team” template; on n8n Cloud, its “over HTTP” template does the same with the built-in HTTP Request node. From anything else, it is one HTTP request:

curl https://api.saina.run/v1/ask \
  -H "Authorization: Bearer $SAINA_API_KEY" \
  -H 'Content-Type: application/json' \
  -d @ticket.json

Or self-host: pip install 'saina[local,server]' and point the same request at your own server. Helm 2 is 0.8B and runs on a CPU, so the tickets never leave your infrastructure.

What it won’t do

Frequently asked questions

Can it classify tickets into my own categories?

Yes. The categories are part of each request, as IDs with a plain-language description. Change them in the next request and Helm follows; there is no training step.

How is this different from asking GPT to classify the ticket?

A chat model writes text that you then parse into a category, and it can answer with a label you never defined. Helm only scores the options you gave it, returns a probability for each, and gives you an explicit fallback when the call is too close. There is no prompt to drift.

Does it need the ticket history or the customer record?

No. It reads the state you send. If the history helps the decision, include it in the state; everything in one request is read once and shared by every question.

Can it run inside n8n?

Yes. The Saina Helm community node (self-hosted n8n) takes the ticket and your questions and has Selected and Fallback outputs; on n8n Cloud the same flow runs through the HTTP Request node. Either targets the hosted API or a server you run.

Read next