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
| Algorithm | Description | Use Case |
|---|---|---|
longest_idle | Longest idle first (default) | Even workload distribution |
least_answered | Fewest answered first | New agent protection |
round_robin | Round robin | Even distribution |
skill_based | Weighted skill scoring | Multi-skill agents |
random | Random | Special 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
| Parameter | Description | Default |
|---|---|---|
| base_priority | Base score | 0 |
| vip_bonus | VIP level bonus (mapped by tier) | None |
| wait_time_weight | Per-second wait time bonus | 1.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:
| Mode | Behavior |
|---|---|
replace (default) | Overflow transfers the call to the next skill group in the chain |
cumulative | Appends more skill groups — original and overflow groups ring simultaneously |
sequential | The 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 Type | Description | Example |
|---|---|---|
timeout | Wait timeout (seconds) | Not assigned within 120s |
queue_length | Queue length exceeded | Queue ≥ 50 callers |
no_agents | No available agents | All 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 Type | Description |
|---|---|
skill_group | Overflow to another skill group |
voicemail | Route to voicemail |
callback | Create a callback task |
back_to_ivr | Return to IVR |
hangup | Hang up |
4.4 Overflow Events & Waiting Depth (0.5+)
- Each hand-off along the chain emits an
overflow_joinedevent, 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
| Operation | Endpoint | Description |
|---|---|---|
| View queue status | GET /cc/queue-detail | Queue count, wait time |
| Real-time stats | GET /cc/realtime | Real-time data for all queues |
| ACD configuration | GET /cc/acd/policies | Policy list |
| Export configuration | POST /cc/acd/export | Export as TOML |
| Reload configuration | POST /cc/acd/reload | Reload |
| ACD diagnostics | GET /cc/acd/diagnostics | Check configuration issues |
7. Call Events
ACD generates events during the assignment process (via the Queue Event system):
Enqueued: Call entered queueAgentAssigned: Agent assignedAgentRinging: Agent ringingAgentAnswered: Agent answeredAgentNoAnswer: Agent did not answerDequeued: 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
| Option | Scope | Values / default | Effect |
|---|---|---|---|
enabled | [acd] | bool | Master switch |
default_policy | [acd] | policy name | Policy for queues without own |
priority.wait_time_weight | policy | float, 1.0 | Wait-time bonus per second |
priority.base_priority | policy | int, 0 | Starting score |
priority.vip_bonus.<tier> | policy | int map | Tier bonus (gold/silver/…) |
priority.fifo_within_same_priority | policy | bool, true | FIFO inside a priority band |
strategy.strategy_type | policy | longest_idle | least_answered | round_robin | skill_based | random | Assignment algorithm |
strategy.max_concurrent_calls | policy | int, 1 | Simultaneous calls per agent |
strategy.require_exact_skill | policy | bool, false | All-skills vs. any-skill match |
strategy.skill_weights.* | policy | floats | skill_match / idle_time / priority |
overflow.mode | skill group | replace | cumulative | sequential | How the chain is walked |
overflow.chain | policy | array | Ordered targets (skill_group/voicemail/callback/back_to_ivr/hangup) |
overflow.retry_per_target | policy | int, 1 | Attempts per target |
schedule.business_hours | policy | start/end/timezone | Open hours |
schedule.night_mode | policy | enabled/start/end/action | Out-of-hours action |
schedule.holidays.<date> | policy | name + overflow_chain | Per-holiday behavior |
max_wait_secs | skill group | int, 0 = ∞ | Hard wait cap |
sla_target_secs | skill group | int, 30 | SLA target for reports |
queue_hold_music | [proxy] | path/URL | Default 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.