Queues & ACD

ACD (Automatic Call Distribution) is the core engine of the call center, responsible for intelligently assigning queued calls to the appropriate agents.

1. ACD Architecture

Inbound call
    │
    ▼
Queue
    │
    ├── Priority sorting
    ├── Schedule check
    ├── Overflow evaluation
    │
    ▼
Agent Selection (Strategy)
    │
    ├── Skill filtering
    ├── Strategy algorithm
    │
    ▼
Assign to agent ──► Agent ringing ──► Answer / No answer

2. ACD Strategy Configuration

2.1 Strategy Structure

# Define policies in ACD configuration
[acd]
enabled = true
default_policy = "support"

[acd.policies.support]
name = "Support Policy"

[acd.policies.support.priority]
wait_time_weight = 1.0
base_priority = 0
fifo_within_same_priority = true

[acd.policies.support.strategy]
strategy_type = "longest_idle"     # Core algorithm
max_concurrent_calls = 1

[acd.policies.support.overflow]
triggers = [
  { type = "timeout", value = 120, action = "overflow" }
]
chain = ["voicemail"]
retry_per_target = 1

2.2 Agent Assignment Algorithms

AlgorithmDescriptionUse Case
longest_idleLongest idle first (default)Even workload distribution
least_answeredFewest answered firstNew agent protection
round_robinRound robinEven distribution
skill_basedWeighted skill scoringMulti-skill agents
randomRandomSpecial scenarios

2.3 Skill Scoring Algorithm

The skill_based strategy uses weighted scoring:

Score = skill_match × 0.6 + idle_time × 0.3 + priority × 0.1

Weights are customizable in the policy configuration:

[acd.policies.support.strategy]
strategy_type = "skill_based"
max_concurrent_calls = 2
require_exact_skill = false

[acd.policies.support.strategy.skill_weights]
skill_match = 0.6
idle_time = 0.3
priority = 0.1

3. Priority Queuing

3.1 Priority Calculation

Priority score = base_priority + vip_bonus + wait_time × wait_time_weight
ParameterDescriptionDefault
base_priorityBase score0
vip_bonusVIP level bonus (mapped by tier)None
wait_time_weightPer-second wait time bonus1.0

3.2 VIP Configuration

[acd.policies.support.priority]
base_priority = 0
wait_time_weight = 1.5

[acd.policies.support.priority.vip_bonus]
gold = 100
silver = 50
bronze = 20

3.2 Queueing Rules

  • Within the same priority level, FIFO (first in, first out)
  • Higher priority calls are always assigned first
  • Longer wait time increases priority (prevents starvation)

4. Overflow Handling

4.1 Overflow Modes (0.5+)

The skill group’s overflow_mode controls how the overflow chain is walked:

ModeBehavior
replace (default)Overflow transfers the call to the next skill group in the chain
cumulativeAppends more skill groups — original and overflow groups ring simultaneously
sequentialThe call stays in the current queue for threshold_secs, then re-queues into the next overflow group in chain order; the last link waits until the global max_wait expires

Sequential mode avoids blasting every overflow group at once — agents downstream are only interrupted for calls that genuinely ran out of time upstream.

4.2 Overflow Triggers

Trigger TypeDescriptionExample
timeoutWait timeout (seconds)Not assigned within 120s
queue_lengthQueue length exceededQueue ≥ 50 callers
no_agentsNo available agentsAll agents offline

4.3 Overflow Target Chain

Targets are tried in order, with a max of N retries per target:

[[acd.policies.support.overflow.chain]]
skill_group = { id = "senior" }    # First overflow to senior group

[[acd.policies.support.overflow.chain]]
"voicemail" = {}                   # Then to voicemail
Target TypeDescription
skill_groupOverflow to another skill group
voicemailRoute to voicemail
callbackCreate a callback task
back_to_ivrReturn to IVR
hangupHang up

4.4 Overflow Events & Waiting Depth (0.5+)

  • Each hand-off along the chain emits an overflow_joined event, so supervisors can see exactly where a caller is in the escalation path.
  • Waiting depth is tracked per queue — a multi-queue agent sees accurate per-queue counts in the console instead of a single blended number.

4.5 Cross-Node Strict FIFO

In cluster deployments, the dispatch gate enforces strict FIFO across nodes: a call that has been waiting longer on node A is dispatched before a newer call on node B, even when the agent registers on B. This removes the “cutting in line” artifacts that naive per-node queues produce.

4.6 Queue Hold Music (0.5+)

Set a PBX-wide default for queue waiting audio:

[proxy]
queue_hold_music = "sounds/hold-music.wav"

A queue’s own hold audio ([proxy.queues.<name>.hold].audio_file) overrides the default; callers hear looping audio instead of silence while they wait.

5. Schedule Rules

5.1 Business Hours

[acd.policies.support.schedule]
[acd.policies.support.schedule.business_hours]
start = "09:00"
end = "18:00"
timezone = "Asia/Shanghai"

5.2 Holidays

[acd.policies.support.schedule.holidays]
"2026-01-01" = { name = "New Year's Day", overflow_chain = ["voicemail"] }
"2026-02-17" = { name = "Spring Festival", overflow_chain = ["back_to_ivr"] }

5.3 Night Mode

[acd.policies.support.schedule.night_mode]
enabled = true
start = "18:00"
end = "09:00"
action = "voicemail"

6. Queue Management API

OperationEndpointDescription
View queue statusGET /cc/queue-detailQueue count, wait time
Real-time statsGET /cc/realtimeReal-time data for all queues
ACD configurationGET /cc/acd/policiesPolicy list
Export configurationPOST /cc/acd/exportExport as TOML
Reload configurationPOST /cc/acd/reloadReload
ACD diagnosticsGET /cc/acd/diagnosticsCheck configuration issues

7. Call Events

ACD generates events during the assignment process (via the Queue Event system):

  • Enqueued: Call entered queue
  • AgentAssigned: Agent assigned
  • AgentRinging: Agent ringing
  • AgentAnswered: Agent answered
  • AgentNoAnswer: Agent did not answer
  • Dequeued: Dequeued (timeout / cancelled)
  • OverflowJoined (0.5+): Call moved into an overflow skill group

Events are typed as queue signals and carry the resolved agent and queue-entry trace, so each assignment decision is auditable after the fact.

8. Screen-Pop Headers (0.5+)

When dispatching to agents, RustPBX carries Call-Info and User-to-User (RFC 7433) headers on the agent INVITE — and re-resolves them through dynamic dial-list re-dials, so screen-pop data survives re-ring sequences and transfers, not just the first attempt. Desk clients use these headers to pop the customer record at ring time.

9. Configuration Reference

OptionScopeValues / defaultEffect
enabled[acd]boolMaster switch
default_policy[acd]policy namePolicy for queues without own
priority.wait_time_weightpolicyfloat, 1.0Wait-time bonus per second
priority.base_prioritypolicyint, 0Starting score
priority.vip_bonus.<tier>policyint mapTier bonus (gold/silver/…)
priority.fifo_within_same_prioritypolicybool, trueFIFO inside a priority band
strategy.strategy_typepolicylongest_idle | least_answered | round_robin | skill_based | randomAssignment algorithm
strategy.max_concurrent_callspolicyint, 1Simultaneous calls per agent
strategy.require_exact_skillpolicybool, falseAll-skills vs. any-skill match
strategy.skill_weights.*policyfloatsskill_match / idle_time / priority
overflow.modeskill groupreplace | cumulative | sequentialHow the chain is walked
overflow.chainpolicyarrayOrdered targets (skill_group/voicemail/callback/back_to_ivr/hangup)
overflow.retry_per_targetpolicyint, 1Attempts per target
schedule.business_hourspolicystart/end/timezoneOpen hours
schedule.night_modepolicyenabled/start/end/actionOut-of-hours action
schedule.holidays.<date>policyname + overflow_chainPer-holiday behavior
max_wait_secsskill groupint, 0 = ∞Hard wait cap
sla_target_secsskill groupint, 30SLA target for reports
queue_hold_music[proxy]path/URLDefault queue wait audio

Queue management endpoints: GET /cc/queue-detail, GET /cc/realtime, GET /cc/acd/policies, POST /cc/acd/export, POST /cc/acd/reload, GET /cc/acd/diagnostics.