0Pricing
AI Agents · Lezione

Instradamento dei ticket e logica di escalation

Classificazione dell’intento, instradamento verso agenti specializzati e criteri di escalation.

Instradamento dei ticket e logica di escalation è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.

Il problema dell'instradamento

Ogni giorno un agente del servizio clienti riceve migliaia di messaggi diversi: contestazioni di fatture, reimpostazioni di password, difetti dei prodotti, ritardi nelle spedizioni e richieste di nuove funzionalità. Inviare ogni messaggio allo stesso gestore produce risposte lente e di bassa qualità.

L'instradamento dei ticket classifica ogni messaggio e lo invia al team più adatto a risolverlo.

Classificazione dell'intento con un LLM

Il livello di instradamento chiama un LLM con un prompt di classificazione. Il modello restituisce una risposta strutturata con un'etichetta intent e un punteggio di confidence.

import openai, json

client = openai.OpenAI(api_key='YOUR_OPENAI_KEY')

INTENTS = ['billing', 'technical_support', 'returns_refunds',
           'account_access', 'shipping', 'general_inquiry']

def classify_intent(message: str) -> dict:
    prompt = (
        f'Classify this customer message into exactly one intent.\n'
        f'Intents: {INTENTS}\n'
        f'Message: "{message}"\n'
        f'Respond with JSON: {{"intent": "...", "confidence": 0.0-1.0}}'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)

Instradamento verso le code degli specialisti

Una volta identificato l'intento, instradi il ticket verso la coda dello specialista appropriato. Ogni coda dispone di propri template di risposta, SLA e regole di escalation.

ROUTING_MAP = {
    'billing':           'queue_billing',
    'technical_support': 'queue_tech',
    'returns_refunds':   'queue_returns',
    'account_access':    'queue_tech',
    'shipping':          'queue_fulfillment',
    'general_inquiry':   'queue_general'
}

def route_ticket(ticket: dict) -> str:
    result = classify_intent(ticket['message'])
    intent = result['intent']
    confidence = result['confidence']
    queue = ROUTING_MAP.get(intent, 'queue_general')
    ticket['intent'] = intent
    ticket['confidence'] = confidence
    ticket['queue'] = queue
    return queue

Soglia di confidenza per l'escalation

Se il classificatore non è sicuro, con una confidenza inferiore a 0,7, l'instradamento automatico potrebbe essere errato. I ticket con bassa confidenza devono essere inoltrati a una persona per il triage manuale, invece di essere instradati automaticamente a uno specialista.

CONFIDENCE_THRESHOLD = 0.70

def route_with_escalation(ticket: dict) -> dict:
    result = classify_intent(ticket['message'])
    intent = result['intent']
    confidence = result['confidence']

    if confidence < CONFIDENCE_THRESHOLD:
        return {
            'ticket_id': ticket['id'],
            'action': 'escalate_to_human',
            'reason': f'Low confidence: {confidence:.2f}',
            'suggested_intent': intent
        }

    queue = ROUTING_MAP.get(intent, 'queue_general')
    return {
        'ticket_id': ticket['id'],
        'action': 'route_to_queue',
        'queue': queue,
        'intent': intent,
        'confidence': confidence
    }

Escalation della priorità basata sull'SLA

Anche i ticket instradati automaticamente possono violare il proprio SLA se non vengono risolti in tempo. Un job in background confronta l'età del ticket con gli obiettivi dell'SLA e inoltra i ticket in ritardo a una coda per i supervisori.

from datetime import datetime, timezone

SLA_HOURS = {
    'queue_billing':      4,
    'queue_tech':         8,
    'queue_returns':      24,
    'queue_fulfillment':  12,
    'queue_general':      48
}

def check_sla_breach(ticket: dict) -> bool:
    created = datetime.fromisoformat(ticket['created_at'])
    age_hours = (datetime.now(timezone.utc) - created).total_seconds() / 3600
    sla = SLA_HOURS.get(ticket['queue'], 24)
    if age_hours > sla and ticket['status'] == 'open':
        ticket['queue'] = 'queue_supervisor_escalation'
        ticket['escalation_reason'] = f'SLA breach: {age_hours:.1f}h > {sla}h'
        return True
    return False

if __name__ == '__main__':
    from datetime import datetime, timedelta, timezone
    old_ticket = {
        'created_at': (datetime.now(timezone.utc) - timedelta(hours=10)).isoformat(),
        'queue': 'queue_billing',
        'status': 'open',
    }
    breached = check_sla_breach(old_ticket)
    print(f'SLA breached: {breached}')
    if breached:
        print('Escalation reason:', old_ticket['escalation_reason'])

Instradamento multi-etichetta per ticket complessi

Alcuni messaggi riguardano più ambiti: «Il mio ordine è arrivato danneggiato e mi è stato addebitato due volte». Un classificatore multi-etichetta restituisce più intenti; il ticket viene duplicato in entrambe le code e gli agenti coordinano la risoluzione.

def classify_multi_intent(message: str) -> list[dict]:
    prompt = (
        f'A customer message may have multiple intents.\n'
        f'Intents: {INTENTS}\n'
        f'Message: "{message}"\n'
        f'Return JSON array: [{{"intent": "...", "confidence": 0.0}}]\n'
        f'Include only intents with confidence > 0.5'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    data = json.loads(resp.choices[0].message.content)
    return data.get('intents', [])

# Route to multiple queues
def route_multi(ticket: dict) -> list[str]:
    intents = classify_multi_intent(ticket['message'])
    return [ROUTING_MAP.get(i['intent'], 'queue_general') for i in intents]

Estrazione dei metadati del ticket

Prima dell'instradamento, estragga dal messaggio i metadati utili agli specialisti: numeri d'ordine, nomi dei prodotti e ID degli account. Questo accelera la risoluzione eliminando il primo giro di domande di chiarimento.

def extract_metadata(message: str) -> dict:
    prompt = (
        f'Extract structured metadata from this customer message.\n'
        f'Return JSON: {{"order_id": null, "product": null, "account_email": null}}\n'
        f'Use null for fields not mentioned.\n'
        f'Message: "{message}"'
    )
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)

meta = extract_metadata('My order #A12345 for the blue headphones never arrived.')
print(meta)  # {'order_id': 'A12345', 'product': 'blue headphones', 'account_email': None}

Aumento della priorità basato sul sentiment

I clienti arrabbiati hanno maggiori probabilità di abbandonare il servizio. Rilevi il sentiment negativo e aumenti la priorità del ticket, così i clienti insoddisfatti ricevono risposte più rapide anche se il loro SLA non è ancora scaduto.

def detect_sentiment(message: str) -> str:
    prompt = f'Classify sentiment as positive/neutral/negative.\nMessage: "{message}"\nReturn JSON: {{"sentiment": "..."}}'
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}],
        response_format={'type': 'json_object'}
    )
    return json.loads(resp.choices[0].message.content)['sentiment']

def set_priority(ticket: dict) -> str:
    sentiment = detect_sentiment(ticket['message'])
    if sentiment == 'negative':
        ticket['priority'] = 'high'
    elif sentiment == 'positive':
        ticket['priority'] = 'low'
    else:
        ticket['priority'] = 'normal'
    return ticket['priority']

Definizione della catena di escalation

Definisca una catena di escalation chiara, in modo che ogni coda abbia un livello alternativo. Quando la coda di prima linea non riesce a risolvere il problema entro lo SLA, il ticket passa al livello 2, poi al livello 3, affidato a uno specialista senior, e infine al supervisore.

ESCALATION_CHAIN = {
    'queue_tech':              'queue_tech_tier2',
    'queue_tech_tier2':        'queue_tech_senior',
    'queue_tech_senior':       'queue_supervisor_escalation',
    'queue_billing':           'queue_billing_senior',
    'queue_billing_senior':    'queue_supervisor_escalation',
    'queue_returns':           'queue_supervisor_escalation',
    'queue_fulfillment':       'queue_supervisor_escalation',
    'queue_general':           'queue_supervisor_escalation',
    'queue_supervisor_escalation': None  # terminal — human manager
}

def escalate(ticket: dict) -> str | None:
    next_queue = ESCALATION_CHAIN.get(ticket['queue'])
    if next_queue:
        ticket['queue'] = next_queue
    return next_queue

if __name__ == '__main__':
    ticket = {'queue': 'queue_tech'}
    for _ in range(3):
        nxt = escalate(ticket)
        print(f"Escalated to: {ticket['queue']}")
        if nxt is None:
            break

Pipeline completa di instradamento

Combini classificazione, estrazione dei metadati, analisi del sentiment e verifica dello SLA in un'unica pipeline eseguita per ogni ticket in arrivo.

def process_ticket(raw_ticket: dict) -> dict:
    ticket = dict(raw_ticket)

    # Step 1: Classify and route
    routing = route_with_escalation(ticket)
    ticket.update(routing)

    # Step 2: Extract metadata
    ticket['metadata'] = extract_metadata(ticket['message'])

    # Step 3: Set priority from sentiment
    ticket['priority'] = set_priority(ticket)

    # Step 4: Check if already breaching SLA
    if ticket.get('created_at'):
        check_sla_breach(ticket)

    return ticket

result = process_ticket({
    'id': 'T001',
    'message': 'I was charged twice for my subscription last month!',
    'created_at': '2026-05-28T10:00:00+00:00',
    'status': 'open'
})
print(result)

Monitoraggio dell'accuratezza dell'instradamento

Misuri l'accuratezza dell'instradamento sottoponendo a revisione umana un campione di percentuale prestabilita dei ticket instradati automaticamente. Quando uno specialista riassegna un ticket a una coda diversa, si tratta di un errore di instradamento. Utilizzi questi errori per migliorare il prompt o perfezionare un classificatore.

import random

def log_routing_decision(ticket: dict, final_queue: str):
    was_correct = ticket.get('queue') == final_queue
    if not was_correct:
        print(f'[ROUTING_ERROR] ticket={ticket["id"]} '
              f'predicted={ticket["queue"]} actual={final_queue} '
              f'confidence={ticket.get("confidence", 0):.2f}')

# Specialist reassigns ticket: log the discrepancy
def specialist_reassign(ticket: dict, new_queue: str):
    log_routing_decision(ticket, new_queue)
    ticket['queue'] = new_queue
    return ticket

if __name__ == '__main__':
    ticket = {'id': 'T-1001', 'queue': 'queue_billing', 'confidence': 0.62}
    specialist_reassign(ticket, 'queue_tech')

Quale soglia di confidenza deve attivare l'escalation a una persona invece dell'instradamento automatico?

La scelta della soglia di confidenza corretta bilancia il tasso di automazione e l'accuratezza dell'instradamento. Una soglia troppo alta provoca un numero eccessivo di escalation; una troppo bassa causa instradamenti errati.

Riepilogo dell'instradamento dei ticket

Un instradamento efficace dei ticket combina la classificazione dell'intento tramite LLM con una soglia di confidenza per l'escalation a una persona, l'estrazione dei metadati per velocizzare la risoluzione, la priorità basata sul sentiment per i clienti a rischio e una catena di escalation basata sull'SLA per garantire che nessun ticket venga trascurato.

Domande Frequenti

La lezione «Instradamento dei ticket e logica di escalation» è gratuita?

Sì — il testo completo di «Instradamento dei ticket e logica di escalation» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.

Cosa imparerò in «Instradamento dei ticket e logica di escalation»?

Classificazione dell’intento, instradamento verso agenti specializzati e criteri di escalation. Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Agents?

Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Instradamento dei ticket e logica di escalation»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Agents?

Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Instradamento dei ticket e logica di escalation
  2. Integrazione CRM: Salesforce e HubSpot
  3. Protocolli di trasferimento a operatori umani
  4. Gestione del contesto e della cronologia dei clienti
← Torna a AI Agents