Routing
Task assignment, skills matching, and queue management
Routing and Assignment
Route tasks to the right humans based on skills, availability, workload, and other factors.
Basic Routing
import { human } from 'human-in-the-loop'
const task = human.task({
name: 'support-ticket',
routing: {
strategy: 'round-robin',
assignTo: { team: 'support' },
},
})Routing Strategies
Round Robin
const roundRobin = human.routing({
strategy: 'round-robin',
assignTo: { team: 'support' },
skipUnavailable: true,
})Skills-Based
const skillsRouting = human.routing({
strategy: 'skills-match',
skills: {
required: ['customer-service'],
preferred: ['technical-support', 'product-knowledge'],
},
// How to score matches
scoring: {
requiredSkillWeight: 1.0,
preferredSkillWeight: 0.5,
experienceWeight: 0.3,
},
})Load-Balanced
const loadBalanced = human.routing({
strategy: 'load-balanced',
factors: {
currentWorkload: 0.4, // Current task count
availability: 0.3, // Schedule availability
capacity: 0.2, // Max task capacity
recentAssignments: 0.1, // Fair distribution
},
limits: {
maxTasksPerPerson: 10,
maxHighPriorityPerPerson: 3,
},
})Priority-Based
const priorityRouting = human.routing({
strategy: 'priority',
rules: [
{
condition: 'priority = critical',
assignTo: { role: 'senior-specialist' },
},
{
condition: 'customer.tier = enterprise',
assignTo: { team: 'enterprise-support' },
},
{
condition: 'topic = billing',
assignTo: { team: 'billing' },
},
{
default: true,
assignTo: { team: 'general-support' },
},
],
})Dynamic Assignment
const dynamicRouting = human.routing({
strategy: 'dynamic',
assignTo: async ({ task, context }) => {
// Custom assignment logic
if (task.language !== 'en') {
return findByLanguage(task.language)
}
if (task.complexity === 'high') {
return findByExpertise(task.category)
}
return findAvailable({ team: 'support' })
},
})Queue Management
Basic Queue
const taskQueue = human.queue({
name: 'review-queue',
// Queue settings
settings: {
maxSize: 1000,
defaultPriority: 'normal',
fifo: true, // First in, first out
},
})
// Add to queue
await taskQueue.add(task)
// Get next task for worker
const next = await taskQueue.getNext({ worker: workerId })Priority Queue
const priorityQueue = human.queue({
name: 'priority-queue',
prioritization: [
// Priority boosting rules
{ condition: 'priority = critical', boost: 10 },
{ condition: 'deadline < 1h', boost: 5 },
{ condition: 'customer.tier = enterprise', boost: 3 },
{ condition: 'waitTime > 30m', boost: 2 },
{ condition: 'type = escalation', boost: 1.5 },
],
// Decay waiting tasks' priority over time
aging: {
enabled: true,
boostPerHour: 0.5,
},
})SLA-Based Queue
const slaQueue = human.queue({
name: 'sla-queue',
sla: {
critical: { responseTime: '15m', resolution: '1h' },
high: { responseTime: '1h', resolution: '4h' },
normal: { responseTime: '4h', resolution: '24h' },
low: { responseTime: '24h', resolution: '72h' },
},
// Escalate when SLA at risk
escalation: {
warnAt: 0.75, // 75% of SLA time
escalateAt: 0.9,
escalateTo: 'supervisor',
},
})Fairness and Limits
const fairQueue = human.queue({
name: 'fair-queue',
fairness: {
// Distribution limits
maxTasksPerPerson: 10,
maxHighPriorityPerPerson: 3,
// Rotation
rotateAfter: '2h',
breakReminders: {
after: '90m',
message: 'Consider taking a short break',
},
// Variety
maxSameTypeConsecutive: 3,
balanceCategories: true,
},
})Availability
Schedule-Based
const scheduledRouting = human.routing({
strategy: 'skills-match',
availability: {
// Consider working hours
respectSchedule: true,
// Working hours
workingHours: {
default: '9:00-17:00',
timezone: 'local',
},
// Handle out of hours
outOfHours: {
queue: true,
fallback: 'on-call-team',
},
},
})Real-Time Availability
const realtimeRouting = human.routing({
strategy: 'load-balanced',
availability: {
realtime: true,
statusCheck: true, // Check user status
statuses: {
available: { eligible: true, weight: 1.0 },
busy: { eligible: true, weight: 0.5 },
away: { eligible: false },
offline: { eligible: false },
},
},
})Escalation Paths
const escalatingRouting = human.routing({
strategy: 'tiered',
tiers: [
{
name: 'tier-1',
assignTo: { role: 'support-agent' },
timeout: '30m',
},
{
name: 'tier-2',
assignTo: { role: 'senior-agent' },
timeout: '1h',
},
{
name: 'tier-3',
assignTo: { role: 'specialist' },
timeout: '2h',
},
{
name: 'management',
assignTo: { role: 'support-manager' },
final: true,
},
],
escalateOn: ['timeout', 'request', 'complexity-increase'],
})Queue Analytics
const stats = await taskQueue.getStats()
console.log(stats)
// {
// total: 150,
// waiting: 45,
// inProgress: 30,
// completed: 75,
// avgWaitTime: '12m',
// avgProcessTime: '25m',
// slaCompliance: 0.92,
// byPriority: { critical: 5, high: 20, ... },
// byAssignee: { 'user_1': 10, 'user_2': 12, ... },
// }
// Real-time monitoring
taskQueue.on('sla-warning', (task) => {
console.log(`SLA at risk for task ${task.id}`)
})
taskQueue.on('queue-full', () => {
console.log('Queue is at capacity')
})Claiming and Reassignment
// Worker claims task
await taskQueue.claim(taskId, { worker: workerId })
// Release task back to queue
await taskQueue.release(taskId, {
reason: 'Need specialist assistance',
preserveProgress: true,
})
// Reassign to specific person
await taskQueue.reassign(taskId, {
to: 'specialist@company.com',
reason: 'Requires technical expertise',
})
// Bulk reassignment
await taskQueue.bulkReassign({
from: 'agent_leaving',
to: 'team',
preserveProgress: true,
})Notifications
const notifiedQueue = human.queue({
name: 'notified-queue',
notifications: {
onAssignment: {
channels: ['email', 'slack', 'push'],
template: 'task-assigned',
},
onEscalation: {
channels: ['email', 'slack'],
includeContext: true,
},
reminders: [
{ after: '30m', channels: ['slack'] },
{ after: '1h', channels: ['email'] },
],
},
})Best Practices
- Match skills to tasks - Route based on expertise
- Balance workload - Prevent burnout
- Set clear SLAs - Define expectations
- Enable escalation - Provide escape valves
- Monitor queues - React to backlogs early
- Support reassignment - Handle unavailability gracefully
Was this page helpful?