Skip to content

Routing, Roles, and Assignment ​

This page is the clearest reference for how tickets move through the system, who can do what, how departments are chosen, and when an agent is auto-assigned.

Routing logic ​

The API computes routing in apps/api/src/lib/router.ts using shared thresholds from @arabic-itsm/shared.

Confidence thresholds ​

ModeRuleTicket status
autoevery available classification level is >= 0.85open
reviewnot auto, but l1.confidence >= 0.60pending_review
manualbelow review threshold, classifier failed, or classifier unavailablenew

Important detail ​

The stored routing_confidence is the minimum confidence across:

  • l1
  • l2
  • optional l3

That means one weak level can prevent auto-routing even if the others are high.

What each routing mode actually means ​

auto ​

  • classifier confidence is high enough across the available levels
  • system opens the ticket immediately
  • department is chosen from the L1 label
  • ticket is auto-assigned to the least-loaded agent in that department
  • assigned agent receives an automatic assignment notification

review ​

  • classifier has enough confidence to suggest direction, but not enough for full automatic handling
  • status is set to pending_review
  • ticket is routed to Service Desk if that department exists
  • otherwise it stays with the matched department
  • no direct agent auto-assignment is made
  • review/triage agents are notified to inspect and confirm

manual ​

  • classifier confidence is too low, or classifier output is unavailable
  • status is set to new
  • ticket is not auto-assigned
  • admins are notified for manual triage
  • the helpdesk still works even when classification fails

Department routing ​

Department selection is based on the ticket's classification.l1.label.

The API matches that label against departments.l1_labels.

Expected department families ​

L1 labelExpected department
AccessAccess Management
HardwareHardware Support
NetworkNetwork Operations
SecuritySecurity Team
ServiceService Desk
SoftwareSoftware Support

Assignment logic ​

Assignment is handled in apps/api/src/lib/assignment.ts.

For auto tickets ​

  1. Find the department by L1 label.
  2. Query all agents in that department.
  3. Count each agent's open tickets with statuses:
    • new
    • pending_review
    • open
    • in_progress
  4. Choose the least-loaded agent.
  5. Save assigned_agent_id.
  6. Record an audit entry.
  7. Notify the assigned agent.

For review tickets ​

  1. Find the department suggested by L1.
  2. Prefer the Service Desk department for triage if it exists.
  3. Set department_id to that triage department.
  4. Do not auto-assign an individual agent.
  5. Notify the triage agents.

For manual tickets ​

  • no automatic assignment
  • no confidence-based department workflow
  • admins are expected to step in

Roles and access model ​

Role information comes from Supabase user app_metadata and is enforced by the API.

end_user ​

  • can create tickets
  • can read only their own tickets
  • can see their own ticket comments and notifications
  • cannot update workflow fields or routing

agent ​

  • can read tickets in their department
  • can also read tickets directly assigned to them
  • can update ticket status, priority, department, and assignee when allowed
  • can override routing
  • can work comments, queues, and review flows

admin ​

  • can read and manage all tickets
  • can manage users and invitations
  • can access stats utilities and developer tools
  • can reseed demo data and quick actions

Human override behavior ​

Routing override ​

When an agent or admin changes routing through PATCH /api/v1/tickets/:id/routing:

  • routing_overridden is forced to true
  • an audit entry is written
  • notifications are sent
  • the override becomes measurable in stats

Reclassify ​

When an agent re-runs AI classification:

  • classification and routing_confidence are refreshed
  • if the ticket was already manually overridden, the system does not silently replace the human decision

Failure behavior ​

If the classifier is unavailable:

  • ticket creation still succeeds
  • classification = null
  • routing_mode = manual
  • status = new
  • routing_reason = "Classifier unavailable."

This fallback is intentional. The helpdesk is not dependent on the classifier being online.

Built from the current monorepo implementation.