REM Queue Monitor - Automated Queue Management REM Runs on schedule to monitor queue health, reassign stale conversations, REM notify supervisors of issues, and generate queue metrics. REM REM Schedule: SET SCHEDULE "queue-monitor", "*/5 * * * *" (every 5 minutes) DESCRIPTION "Monitor queue health, reassign stale conversations, alert on issues" ' Get current queue status queue = GET QUEUE PRINT "Queue Monitor Running - " + FORMAT(NOW(), "yyyy-MM-dd HH:mm:ss") PRINT "Total: " + queue.total + " | Waiting: " + queue.waiting + " | Active: " + queue.active ' === Check for stale waiting conversations === ' Conversations waiting more than 10 minutes without assignment stale_threshold_minutes = 10 FOR EACH item IN queue.items IF item.status = "waiting" THEN ' Calculate wait time created_at = GET SESSION item.session_id, "created_at" wait_minutes = DATEDIFF("minute", created_at, NOW()) IF wait_minutes > stale_threshold_minutes THEN PRINT "ALERT: Stale conversation " + item.session_id + " waiting " + wait_minutes + " minutes" ' Try to find available attendant attendants = GET ATTENDANTS "online" IF attendants.count > 0 THEN ' Find attendant with least active conversations best_attendant = NULL min_active = 999 FOR EACH att IN attendants.items stats = GET ATTENDANT STATS att.id IF stats.active_conversations < min_active THEN min_active = stats.active_conversations best_attendant = att END IF NEXT IF best_attendant IS NOT NULL AND min_active < 5 THEN ' Auto-assign result = ASSIGN CONVERSATION item.session_id, best_attendant.id IF result.success THEN PRINT "Auto-assigned " + item.session_id + " to " + best_attendant.name ADD NOTE item.session_id, "Auto-assigned after " + wait_minutes + " min wait" ' Notify customer SEND TO SESSION item.session_id, "Obrigado por aguardar! " + best_attendant.name + " irá atendê-lo agora." END IF END IF ELSE ' No attendants available - escalate IF wait_minutes > 20 THEN ' Critical - notify supervisor SEND MAIL "supervisor@company.com", "URGENTE: Fila sem atendentes", "Conversa " + item.session_id + " aguardando há " + wait_minutes + " minutos sem atendentes disponíveis." ' Set high priority SET PRIORITY item.session_id, "urgent" TAG CONVERSATION item.session_id, "no-attendants" ' Send apology to customer SEND TO SESSION item.session_id, "Pedimos desculpas pela espera. Nossa equipe está com alta demanda. Você será atendido em breve." END IF END IF END IF END IF NEXT ' === Check for inactive assigned conversations === ' Conversations assigned but no activity for 15 minutes inactive_threshold_minutes = 15 FOR EACH item IN queue.items IF item.status = "assigned" OR item.status = "active" THEN last_activity = GET SESSION item.session_id, "last_activity_at" IF last_activity IS NOT NULL THEN inactive_minutes = DATEDIFF("minute", last_activity, NOW()) IF inactive_minutes > inactive_threshold_minutes THEN PRINT "WARNING: Inactive conversation " + item.session_id + " - " + inactive_minutes + " min since last activity" ' Get assigned attendant assigned_to = GET SESSION item.session_id, "assigned_to" IF assigned_to IS NOT NULL THEN ' Check attendant status att_status = GET ATTENDANT STATUS assigned_to IF att_status = "offline" OR att_status = "away" THEN ' Attendant went away - reassign PRINT "Attendant " + assigned_to + " is " + att_status + " - reassigning" ' Find new attendant new_attendants = GET ATTENDANTS "online" IF new_attendants.count > 0 THEN new_att = new_attendants.items[0] ' Transfer conversation old_ctx = GET SESSION item.session_id, "context" result = ASSIGN CONVERSATION item.session_id, new_att.id IF result.success THEN ADD NOTE item.session_id, "Reatribuído de " + assigned_to + " (status: " + att_status + ") para " + new_att.name SEND TO SESSION item.session_id, "Desculpe a espera. " + new_att.name + " continuará seu atendimento." END IF END IF ELSE ' Attendant is online but inactive - send reminder ' Only remind once every 10 minutes last_reminder = GET SESSION item.session_id, "last_attendant_reminder" IF last_reminder IS NULL OR DATEDIFF("minute", last_reminder, NOW()) > 10 THEN ' Get customer sentiment sentiment = GET SESSION item.session_id, "last_sentiment" reminder = "⚠️ Conversa inativa há " + inactive_minutes + " min" IF sentiment = "negative" THEN reminder = reminder + " - Cliente frustrado!" END IF ' Send reminder via WebSocket to attendant UI NOTIFY ATTENDANT assigned_to, reminder SET SESSION item.session_id, "last_attendant_reminder", NOW() END IF END IF END IF END IF END IF END IF NEXT ' === Check for abandoned conversations === ' Customer hasn't responded in 30 minutes abandon_threshold_minutes = 30 FOR EACH item IN queue.items IF item.status = "active" OR item.status = "assigned" THEN last_customer_msg = GET SESSION item.session_id, "last_customer_message_at" IF last_customer_msg IS NOT NULL THEN silent_minutes = DATEDIFF("minute", last_customer_msg, NOW()) IF silent_minutes > abandon_threshold_minutes THEN ' Check if already marked already_marked = GET SESSION item.session_id, "abandon_warning_sent" IF already_marked IS NULL THEN ' Send follow-up SEND TO SESSION item.session_id, "Ainda está aí? Se precisar de mais ajuda, é só responder." SET SESSION item.session_id, "abandon_warning_sent", NOW() PRINT "Sent follow-up to potentially abandoned session " + item.session_id ELSE ' Check if warning was sent more than 15 min ago warning_minutes = DATEDIFF("minute", already_marked, NOW()) IF warning_minutes > 15 THEN ' Mark as abandoned RESOLVE CONVERSATION item.session_id, "Abandoned - no customer response" TAG CONVERSATION item.session_id, "abandoned" PRINT "Marked session " + item.session_id + " as abandoned" END IF END IF END IF END IF END IF NEXT ' === Generate queue metrics === ' Calculate averages and store for analytics metrics = {} metrics.timestamp = NOW() metrics.total_waiting = queue.waiting metrics.total_active = queue.active metrics.total_resolved = queue.resolved ' Calculate average wait time for waiting conversations total_wait = 0 wait_count = 0 FOR EACH item IN queue.items IF item.status = "waiting" THEN created_at = GET SESSION item.session_id, "created_at" wait_minutes = DATEDIFF("minute", created_at, NOW()) total_wait = total_wait + wait_minutes wait_count = wait_count + 1 END IF NEXT IF wait_count > 0 THEN metrics.avg_wait_minutes = total_wait / wait_count ELSE metrics.avg_wait_minutes = 0 END IF ' Get attendant utilization attendants = GET ATTENDANTS online_count = 0 busy_count = 0 FOR EACH att IN attendants.items IF att.status = "online" THEN online_count = online_count + 1 ELSE IF att.status = "busy" THEN busy_count = busy_count + 1 END IF NEXT metrics.attendants_online = online_count metrics.attendants_busy = busy_count metrics.utilization_pct = 0 IF online_count + busy_count > 0 THEN metrics.utilization_pct = (busy_count / (online_count + busy_count)) * 100 END IF ' Store metrics for dashboard SAVE "queue_metrics", metrics ' Alert if queue is getting long IF queue.waiting > 10 THEN SEND MAIL "supervisor@company.com", "Alerta: Fila com " + queue.waiting + " aguardando", "A fila de atendimento está com " + queue.waiting + " conversas aguardando. Tempo médio de espera: " + metrics.avg_wait_minutes + " minutos." END IF ' Alert if no attendants online during business hours hour_now = HOUR(NOW()) day_now = WEEKDAY(NOW()) IF hour_now >= 9 AND hour_now < 18 AND day_now >= 1 AND day_now <= 5 THEN IF online_count = 0 AND busy_count = 0 THEN SEND MAIL "supervisor@company.com", "CRÍTICO: Sem atendentes online", "Não há atendentes online durante o horário comercial. Fila: " + queue.waiting + " aguardando." END IF END IF PRINT "Queue monitor completed. Metrics saved." RETURN metrics