AI Triage

The AI triage pipeline is the core intelligence layer of the ITSM platform. It processes incoming tickets through a multi-stage classification system: intent classification across 15+ intent types, priority assignment via an Impact x Urgency matrix, entity extraction for 22+ entity types (including Polish-specific identifiers like PESEL, NIP, and IBAN), semantic similarity search against previously resolved tickets, and a final routing decision. All stages are backed by real LLM API calls with tracked token usage.

The triage result model

When a ticket is triaged, the AI pipeline returns a structured result containing the routing decision, classification details, extracted entities, and similar resolved tickets. Every triage result includes token usage metrics for cost tracking and observability.

Properties

  • Name
    decision
    Type
    string
    Description

    The routing decision: auto_resolve (confidence >= 0.7), agent_assist (confidence >= 0.5), or escalate (confidence < 0.5).

  • Name
    confidence
    Type
    number
    Description

    Overall confidence score between 0 and 1, aggregated across all classification stages.

  • Name
    intent
    Type
    object
    Description

    Intent classification result containing type (e.g., incident_report, service_request, password_reset), confidence score, and alternatives array of other likely intents.

  • Name
    priority
    Type
    object
    Description

    Priority classification containing level (P1-P5), impact (critical, high, medium, low), urgency (critical, high, medium, low), and sla_target in minutes. VIP and security adjustments are applied automatically.

  • Name
    entities
    Type
    array
    Description

    Extracted entities, each with type (e.g., email, hostname, pesel, nip, iban), value, confidence score, and position offset in the source text.

  • Name
    similar_tickets
    Type
    array
    Description

    Previously resolved tickets found via semantic search in Qdrant, each with id, title, similarity score (cosine), and resolution text.

  • Name
    suggested_category
    Type
    string
    Description

    AI-suggested ITSM category for the ticket (e.g., hardware, software, network, access_management).

  • Name
    suggested_team
    Type
    string
    Description

    Recommended team for routing (e.g., l1_support, network_ops, security, desktop_engineering).

  • Name
    token_usage
    Type
    object
    Description

    LLM token consumption for this triage, containing input tokens, output tokens, total tokens, and cost in USD.


POST/v1/ai/triage

Triage a ticket

Submit a ticket for AI triage. You can provide either a ticketId referencing an existing ticket in the database, or a raw title and description for ad-hoc classification. The pipeline runs intent classification, priority assignment, entity extraction, similarity search, and routing in sequence, returning the full triage result.

Required attributes

  • Name
    ticketId
    Type
    string
    Description

    The ID of an existing ticket to triage. Mutually exclusive with title/description.

Alternative attributes

  • Name
    title
    Type
    string
    Description

    Ticket title for ad-hoc triage (used when no ticketId is provided).

  • Name
    description
    Type
    string
    Description

    Ticket description for ad-hoc triage (used when no ticketId is provided).

Request

POST
/v1/ai/triage
curl -X POST http://localhost:3000/v1/ai/triage \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "ticketId": "tkt_01J5K9QRMX3BVGY7HNDCWZ48TP"
  }'

Response

{
  "decision": "agent_assist",
  "confidence": 0.62,
  "intent": {
    "type": "incident_report",
    "confidence": 0.87,
    "alternatives": [
      { "type": "service_request", "confidence": 0.09 },
      { "type": "change_request", "confidence": 0.04 }
    ]
  },
  "priority": {
    "level": "P2",
    "impact": "high",
    "urgency": "high",
    "sla_target": 240
  },
  "entities": [
    {
      "type": "hostname",
      "value": "srv-prod-db-03",
      "confidence": 0.95,
      "position": 42
    },
    {
      "type": "email",
      "value": "jan.kowalski@acme.pl",
      "confidence": 0.99,
      "position": 118
    },
    {
      "type": "error_code",
      "value": "ORA-12541",
      "confidence": 0.91,
      "position": 203
    }
  ],
  "similar_tickets": [
    {
      "id": "tkt_01J4WMRVN8HAXJFGQ2C6YB39KE",
      "title": "Database connection timeout on srv-prod-db-03",
      "similarity": 0.89,
      "resolution": "Restarted Oracle listener service and increased connection pool max_size from 50 to 100 in /etc/oracle/listener.ora."
    },
    {
      "id": "tkt_01J3NP8KFX6DTYRW2B7QHSV5MA",
      "title": "Intermittent ORA-12541 errors on production DB cluster",
      "similarity": 0.74,
      "resolution": "Root cause was network switch failover. Applied static route and restarted TNS listener."
    }
  ],
  "suggested_category": "database",
  "suggested_team": "dba_operations",
  "token_usage": {
    "input": 847,
    "output": 312,
    "total": 1159,
    "cost": 0.0023
  }
}

POST/v1/ai/triage

Triage a ticket (ad-hoc)

You can also triage a ticket without saving it to the database first by providing raw title and description fields. This is useful for previewing AI classification in real-time, such as while a user is filling out a ticket form.

Request

POST
/v1/ai/triage
curl -X POST http://localhost:3000/v1/ai/triage \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Cannot reset password for Active Directory account",
    "description": "User anna.nowak@acme.pl reports she is locked out of her AD account after 5 failed login attempts. PESEL 85010212345. Needs immediate access for month-end financial reporting deadline."
  }'

Response

{
  "decision": "auto_resolve",
  "confidence": 0.84,
  "intent": {
    "type": "password_reset",
    "confidence": 0.93,
    "alternatives": [
      { "type": "access_request", "confidence": 0.05 },
      { "type": "account_unlock", "confidence": 0.02 }
    ]
  },
  "priority": {
    "level": "P3",
    "impact": "medium",
    "urgency": "high",
    "sla_target": 480
  },
  "entities": [
    {
      "type": "email",
      "value": "anna.nowak@acme.pl",
      "confidence": 0.99,
      "position": 5
    },
    {
      "type": "pesel",
      "value": "85010212345",
      "confidence": 0.97,
      "position": 112
    },
    {
      "type": "system",
      "value": "Active Directory",
      "confidence": 0.94,
      "position": 32
    }
  ],
  "similar_tickets": [
    {
      "id": "tkt_01J2FHG5NR9PAWQXV4T8CK7YMB",
      "title": "AD account lockout after failed password attempts",
      "similarity": 0.92,
      "resolution": "Unlocked account via ADUC, reset password, and cleared lockout counter. Reminded user of password policy."
    }
  ],
  "suggested_category": "access_management",
  "suggested_team": "l1_support",
  "token_usage": {
    "input": 623,
    "output": 289,
    "total": 912,
    "cost": 0.0018
  }
}

POST/v1/ai/triage/batch

Batch triage

Submit multiple tickets for triage in a single request. The pipeline processes each ticket independently through all classification stages. Results are returned in the same order as the input ticketIds array. Batch triage is processed via BullMQ for reliability and retry handling.

Required attributes

  • Name
    ticketIds
    Type
    array
    Description

    Array of ticket IDs to triage. Maximum 50 tickets per batch request.

Request

POST
/v1/ai/triage/batch
curl -X POST http://localhost:3000/v1/ai/triage/batch \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "ticketIds": [
      "tkt_01J5K9QRMX3BVGY7HNDCWZ48TP",
      "tkt_01J5KA2FNX7CQWRM4D9HYTV6PB",
      "tkt_01J5KA8GTY4DPZSN6E2JKVW7RC"
    ]
  }'

Response

{
  "batch_id": "batch_01J5KBCNRX8FQWTYV3D2HMZS9P",
  "total": 3,
  "completed": 3,
  "failed": 0,
  "results": [
    {
      "ticketId": "tkt_01J5K9QRMX3BVGY7HNDCWZ48TP",
      "decision": "agent_assist",
      "confidence": 0.62,
      "intent": { "type": "incident_report", "confidence": 0.87 },
      "priority": { "level": "P2", "impact": "high", "urgency": "high", "sla_target": 240 },
      "suggested_category": "database",
      "suggested_team": "dba_operations"
    },
    {
      "ticketId": "tkt_01J5KA2FNX7CQWRM4D9HYTV6PB",
      "decision": "auto_resolve",
      "confidence": 0.91,
      "intent": { "type": "password_reset", "confidence": 0.96 },
      "priority": { "level": "P4", "impact": "low", "urgency": "medium", "sla_target": 1440 },
      "suggested_category": "access_management",
      "suggested_team": "l1_support"
    },
    {
      "ticketId": "tkt_01J5KA8GTY4DPZSN6E2JKVW7RC",
      "decision": "escalate",
      "confidence": 0.34,
      "intent": { "type": "security_incident", "confidence": 0.41 },
      "priority": { "level": "P1", "impact": "critical", "urgency": "critical", "sla_target": 60 },
      "suggested_category": "security",
      "suggested_team": "security_ops"
    }
  ],
  "token_usage": {
    "input": 2541,
    "output": 936,
    "total": 3477,
    "cost": 0.0069
  }
}

GET/v1/ai/triage/metrics

Get triage metrics

Retrieve aggregated triage metrics including decision distribution, average confidence scores, classification accuracy, and token usage over time. Useful for monitoring AI performance and cost tracking in dashboards.

Optional attributes

  • Name
    period
    Type
    string
    Description

    Time period for aggregation: 1h, 24h, 7d, 30d. Defaults to 24h.

  • Name
    team
    Type
    string
    Description

    Filter metrics by suggested team.

Request

GET
/v1/ai/triage/metrics
curl -G http://localhost:3000/v1/ai/triage/metrics \
  -H "Authorization: Bearer {token}" \
  -d period=24h

Response

{
  "period": "24h",
  "total_triaged": 847,
  "decisions": {
    "auto_resolve": 412,
    "agent_assist": 298,
    "escalate": 137
  },
  "avg_confidence": 0.71,
  "accuracy": {
    "intent_classification": 0.89,
    "priority_assignment": 0.82,
    "routing_accuracy": 0.76
  },
  "intent_distribution": {
    "incident_report": 287,
    "service_request": 194,
    "password_reset": 132,
    "change_request": 78,
    "information_request": 61,
    "access_request": 45,
    "hardware_request": 28,
    "security_incident": 12,
    "other": 10
  },
  "priority_distribution": {
    "P1": 18,
    "P2": 124,
    "P3": 389,
    "P4": 247,
    "P5": 69
  },
  "avg_processing_time_ms": 1847,
  "token_usage": {
    "total_input": 714293,
    "total_output": 263841,
    "total_tokens": 978134,
    "total_cost": 1.96
  }
}

POST/v1/ai/chat

AI Chat

Send a message to the ITSM AI assistant. The assistant can answer questions about IT policies, troubleshoot common issues, and guide users through service request workflows. Conversations are tracked by conversationId for multi-turn context.

Required attributes

  • Name
    message
    Type
    string
    Description

    The user message to the AI assistant.

Optional attributes

  • Name
    conversationId
    Type
    string
    Description

    ID of an existing conversation for multi-turn context. Omit to start a new conversation.

Request

POST
/v1/ai/chat
curl -X POST http://localhost:3000/v1/ai/chat \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "My laptop screen is flickering after the latest Windows update. What should I try before submitting a ticket?",
    "conversationId": "conv_01J5KC7NRX2FQWTYV3D8HMZS4A"
  }'

Response

{
  "conversationId": "conv_01J5KC7NRX2FQWTYV3D8HMZS4A",
  "response": "Screen flickering after a Windows update is commonly caused by an incompatible display driver. Here are the steps to try before submitting a ticket:\n\n1. Restart in Safe Mode - Press Shift while clicking Restart, then navigate to Troubleshoot > Advanced > Startup Settings > Safe Mode.\n2. Roll back the display driver - Open Device Manager > Display adapters > right-click your GPU > Properties > Driver > Roll Back Driver.\n3. Uninstall the recent update - Go to Settings > Update and Security > View update history > Uninstall updates, and remove the latest one.\n4. Restart Desktop Window Manager - Open Task Manager, find Desktop Window Manager, and restart it.\n\nIf none of these resolve the issue, I can create a P3 hardware ticket and route it to Desktop Engineering.",
  "suggested_actions": [
    {
      "label": "Create a ticket",
      "action": "create_ticket",
      "params": { "category": "hardware", "subcategory": "display" }
    },
    {
      "label": "Escalate to Desktop Engineering",
      "action": "escalate",
      "params": { "team": "desktop_engineering" }
    }
  ],
  "token_usage": {
    "input": 312,
    "output": 487,
    "total": 799,
    "cost": 0.0016
  }
}

POST/v1/ai/search/semantic

Perform a semantic (vector) search against a specified Qdrant collection. The query text is embedded and compared against stored vectors using cosine similarity. This powers the knowledge base search, ticket deduplication, and similar-issue detection features.

Required attributes

  • Name
    query
    Type
    string
    Description

    The natural-language search query to embed and match against.

  • Name
    collection
    Type
    string
    Description

    The Qdrant collection to search: tickets, knowledge_base, or runbooks.

Optional attributes

  • Name
    limit
    Type
    integer
    Description

    Maximum number of results to return. Defaults to 10, maximum 100.

  • Name
    threshold
    Type
    number
    Description

    Minimum cosine similarity score (0-1). Defaults to 0.5.

  • Name
    filters
    Type
    object
    Description

    Qdrant payload filters to narrow results (e.g., { "status": "resolved" }).

Request

POST
/v1/ai/search/semantic
curl -X POST http://localhost:3000/v1/ai/search/semantic \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "Oracle database connection timeout on production server",
    "collection": "tickets",
    "limit": 5,
    "threshold": 0.6
  }'

Response

{
  "query": "Oracle database connection timeout on production server",
  "collection": "tickets",
  "results": [
    {
      "id": "tkt_01J4WMRVN8HAXJFGQ2C6YB39KE",
      "score": 0.91,
      "payload": {
        "title": "Database connection timeout on srv-prod-db-03",
        "status": "resolved",
        "category": "database",
        "resolution": "Restarted Oracle listener service and increased connection pool max_size from 50 to 100.",
        "resolved_at": "2025-11-14T09:23:00Z"
      }
    },
    {
      "id": "tkt_01J3NP8KFX6DTYRW2B7QHSV5MA",
      "score": 0.84,
      "payload": {
        "title": "Intermittent ORA-12541 errors on production DB cluster",
        "status": "resolved",
        "category": "database",
        "resolution": "Root cause was network switch failover. Applied static route and restarted TNS listener.",
        "resolved_at": "2025-10-28T14:47:00Z"
      }
    },
    {
      "id": "tkt_01J2R6YMDW3BQNXHK7T5PCVF8A",
      "score": 0.77,
      "payload": {
        "title": "Connection pool exhaustion on Oracle RAC node 2",
        "status": "resolved",
        "category": "database",
        "resolution": "Identified long-running queries holding connections. Killed sessions and added connection timeout of 30s.",
        "resolved_at": "2025-09-19T11:05:00Z"
      }
    }
  ],
  "total_found": 3,
  "search_time_ms": 47
}

POST/v1/ai/similar-tickets

Similar tickets

Find tickets that are semantically similar to a given ticket. This endpoint embeds the source ticket title and description, then performs a cosine similarity search against all indexed tickets in Qdrant. Results include the resolution text from previously resolved tickets, enabling auto-resolve suggestions and knowledge reuse.

Required attributes

  • Name
    ticketId
    Type
    string
    Description

    The ID of the ticket to find similar matches for.

Optional attributes

  • Name
    limit
    Type
    integer
    Description

    Maximum number of similar tickets to return. Defaults to 5, maximum 20.

  • Name
    status
    Type
    string
    Description

    Filter by ticket status: resolved, open, in_progress, or all. Defaults to resolved.

Request

POST
/v1/ai/similar-tickets
curl -X POST http://localhost:3000/v1/ai/similar-tickets \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "ticketId": "tkt_01J5K9QRMX3BVGY7HNDCWZ48TP",
    "limit": 3
  }'

Response

{
  "ticketId": "tkt_01J5K9QRMX3BVGY7HNDCWZ48TP",
  "similar": [
    {
      "id": "tkt_01J4WMRVN8HAXJFGQ2C6YB39KE",
      "title": "Database connection timeout on srv-prod-db-03",
      "similarity": 0.89,
      "status": "resolved",
      "category": "database",
      "resolution": "Restarted Oracle listener service and increased connection pool max_size from 50 to 100 in /etc/oracle/listener.ora.",
      "resolved_at": "2025-11-14T09:23:00Z",
      "resolved_by": "marek.wisniewski@acme.pl"
    },
    {
      "id": "tkt_01J3NP8KFX6DTYRW2B7QHSV5MA",
      "title": "Intermittent ORA-12541 errors on production DB cluster",
      "similarity": 0.74,
      "status": "resolved",
      "category": "database",
      "resolution": "Root cause was network switch failover. Applied static route and restarted TNS listener.",
      "resolved_at": "2025-10-28T14:47:00Z",
      "resolved_by": "piotr.zielinski@acme.pl"
    },
    {
      "id": "tkt_01J2R6YMDW3BQNXHK7T5PCVF8A",
      "title": "Connection pool exhaustion on Oracle RAC node 2",
      "similarity": 0.68,
      "status": "resolved",
      "category": "database",
      "resolution": "Identified long-running queries holding connections. Killed sessions and added connection timeout of 30s.",
      "resolved_at": "2025-09-19T11:05:00Z",
      "resolved_by": "marek.wisniewski@acme.pl"
    }
  ],
  "search_time_ms": 52
}

Was this page helpful?