Running a Call Center on RustPBX
A contact center is more than a PBX with queues. It needs skill-based routing to send calls to the right agent, real-time monitoring for supervisors, wrap-up time for agents to finish notes, and overflow logic to prevent callers from waiting forever.
RustPBX’s CC (Contact Center) addon provides all of this out of the box. This post walks through setting up a functional call center – from skill groups to supervisor monitoring.
What You Need
- RustPBX >= 0.4.4 with the
contact-centerfeature flag - MySQL 8.0+ or PostgreSQL 14+ recommended (SQLite works for small setups)
- The CC addon auto-includes several dependencies: IVR editor, voicemail, endpoint manager, enterprise auth, and telemetry
Enable it:
[proxy]
addons = ["cc"]
On first boot, RustPBX creates 10 CC-specific tables: cc_agents, cc_agent_endpoints, cc_agent_stats, cc_calls, cc_call_records, cc_skill_groups, cc_queue_snapshots, cc_csat_surveys, cc_monitor_records, and cc_cast_results.
The Setup Flow
Setting up a call center follows six steps:
- Create skill groups
- Create agents
- Register agent endpoints
- Configure a queue
- Create a routing rule
- Test by dialing in
Let’s walk through each.

Step 1: Create Skill Groups
A skill group defines what an agent can handle. It’s not just “Sales” or “Support” – it’s a set of required skills with overflow targets.
Go to CC > Skill Groups and create one:
| Field | Example |
|---|---|
| Skill Group ID | billing-support |
| Display Name | Billing Support |
| Required Skills | billing, english |
| Overflow Groups | general-support |
| SLA Target | 30 seconds (answer within 30s) |
| Max Wait | 90 seconds (overflow after 90s) |

The SLA monitor tracks what percentage of calls are answered within the target. If wait time exceeds max_wait, the call overflows to the next group or goes to voicemail.
Step 2: Create Agents
An agent is a person (or bot) who handles calls. Go to CC > Agents and add agents:
| Field | Example |
|---|---|
| Agent ID | agent-001 |
| Skills | billing, english, escalation |
| Max Concurrency | 1 (handle one call at a time) |
| Priority | 10 (higher = gets calls first) |
| Auto Offline After Wrap-up | true |

Each agent has a state machine:
Offline → Idle → Ringing → Busy → Wrap-up → Idle
↓ ↓
Away Away
- Idle: Ready for calls
- Ringing: Being offered a call
- Busy: On an active call
- Wrap-up: Call ended, finishing notes (timer-based, then auto-returns to Idle)
- Away: On break (lunch, training, personal)
- DND: Do Not Disturb
Step 3: Register Agent Endpoints
Each agent needs at least one SIP endpoint (device). An agent can have multiple endpoints – desk phone AND softphone, for example.
On the agent detail page, add endpoints:
- SIP URI:
sip:2001@your-server - Type: SIP or WebRTC
Agents register their devices using standard SIP registration. The CC addon bridges SIP registration to agent presence – when an endpoint registers, the agent appears as available.
Step 4: Configure the Queue
Queues are defined in TOML files under config/queues/ and managed through the routing system:
# config/queues/billing.toml
[name]
name = "billing-queue"
[strategy]
mode = "sequential"
wait_timeout_secs = 90
[strategy.targets.0]
uri = "sip:acd-agent@localhost"
label = "billing-acd"
[hold]
audio_file = "config/sounds/ring.wav"
[fallback]
skill_group_ref = "general-support"
failure_code = 480
Key settings:
- Strategy mode:
sequential(try agents one by one) orparallel(ring all at once) - Wait timeout: Maximum time a caller waits in queue
- Targets: Agent endpoints to ring
- Hold: Music-on-hold audio file
- Fallback: What happens when no agent picks up – redirect to another skill group, queue, or hangup
Queues can also be managed through the console with hot-reload support.

Step 5: Route Calls to the Queue
Create an inbound route (through the console or config/routes/) that sends callers to the queue:
- Match: incoming calls to your DID
- Action: route to queue
billing-queue
Callers hear hold music while the ACD engine finds an available agent.
Step 6: Agent Experience with CC Phone
RustPBX includes a built-in web phone at /cc/phone. Agents open it in their browser and get:
- SIP Registration: WebRTC-based, no softphone needed
- Status Toggle: Idle, Away (with break type), DND
- Incoming Calls: Pop-up with caller info
- In-Call Actions: Mute, transfer (blind or consult), hang up
- After-Call Work: Wrap-up timer, notes
- Break Types: Lunch, training, meeting, personal

The phone communicates with the CC backend via WebSocket for real-time state updates.
How the ACD Engine Works
When a call enters a queue, the ACD engine evaluates:
- Skill matching: Filter agents who have the required skills for this queue’s skill group
- Availability: Only agents in
Idlestatus with capacity belowmax_concurrency - Selection strategy:
longest-idle: Agent who’s been idle the longestround-robin: Fair distribution across agentsskill-based: Match on skill levels, prioritize higher proficiency
- Priority: Higher-priority agents get calls first within the strategy
These strategies are configured through the ACD policy referenced by the queue’s acd_policy field.
If no agent is available:
- Estimated Wait Time (EWT) is calculated from historical average answer time
- Queue position is communicated to the caller
- Overflow triggers after
max_waitseconds, routing to the next skill group or fallback
The ACD engine processes all of this in real time, handling hundreds of concurrent queue entries without blocking.
Supervisor Features
Supervisors get real-time visibility and intervention tools through the CC console:
| Action | What It Does |
|---|---|
| Listen | Silently monitor an agent’s call (no one hears you) |
| Whisper | Talk to the agent only (customer doesn’t hear) |
| Barge | Join the conversation (both agent and customer hear you) |
| Takeover | Take the call from the agent entirely |

The real-time dashboard shows:
- Number of calls in queue
- Average wait time
- SLA percentage (e.g. 87% answered within 30s)
- Agent status breakdown (idle, busy, wrap-up, away)
- Active call list with caller info and duration
CSAT: Customer Satisfaction
After a call, agents can trigger a satisfaction survey (DTMF-based). Customers rate the experience (1-5), and results are stored per call, per agent, and per skill group. The CC console shows aggregate CSAT scores and trends.
Metrics and Reporting
The CC addon collects metrics compatible with Prometheus:
- Queue depth and wait times
- Agent utilization (talk time, wrap-up time, idle time)
- SLA compliance per skill group
- Call outcomes (answered, abandoned, overflowed)
Use the built-in charts or export to your monitoring stack.
Scaling
The CC addon supports:
- Multi-endpoint agents: An agent can be reached on multiple devices simultaneously
- Skill group overflow: Chain skill groups so calls cascade from specialized to general agents
- Time-of-day scheduling: Different routing rules for business hours vs. after-hours
- Autonomous mode: AI-driven call handling for self-service before queueing
Summary
| Feature | What It Does |
|---|---|
| Skill-based routing | Match callers to agents with the right skills |
| ACD engine | Automatic call distribution with multiple strategies |
| CC Phone | Built-in WebRTC softphone for agents |
| Supervisor tools | Listen, whisper, barge, takeover |
| SLA monitoring | Track answer-time targets per skill group |
| CSAT | Customer satisfaction surveys |
| Real-time metrics | Queue stats, agent utilization, Prometheus export |
With the CC addon, RustPBX goes from a PBX to a full contact center platform – skill routing, agent management, supervisor monitoring, and analytics, all in one runtime.
Series Wrap-Up
Over this series, we covered the full journey of building a telephony platform with RustPBX:
- Extensions for internal VoIP communication
- Routes and Trunks for carrier connectivity and SBC functionality
- JSON-RPC Routing for dynamic, API-driven call control and privacy numbers
- Archive, ACME, and Transcript for day-to-day operations
- SipFlow for call debugging, recording, and cluster-scale capture
- Call Center for ACD, agent management, and supervisor tools
All of this runs in a single Rust binary, managed through a web console, with no external dependencies. That’s RustPBX.