Vicidial Predictive Dialer Tuning: Maximizing Agent Productivity
Vicidial is the most widely deployed open-source predictive dialer. A default installation works. A tuned installation delivers 45–55 minutes of talk time per agent hour instead of the 30–35 minutes most teams see out of the box. The difference comes down to dial ratio math, database query performance, and understanding how Vicidial's adaptive algorithm responds to your specific lead list and agent pool characteristics.
How the Predictive Algorithm Works
Vicidial's predictive dialer uses an adaptive algorithm that continuously adjusts the dial ratio (calls dialed per available agent) based on recent outcome statistics. The core formula:
dial_ratio = available_agents × (1 / (1 - target_abandon_rate)) × safety_margin
Where:
target_abandon_rateis typically 3% (FTC limit in the US) or 5% (Ofcom limit in the UK)safety_marginis 0.85–0.95 (accounts for prediction error)
At 3% target abandon rate: dial_ratio = agents × 1.031 × 0.9 ≈ agents × 0.928
This means with 10 available agents, Vicidial should be dialing roughly 9–10 simultaneous calls. Many installations are tuned too conservatively (ratio 1.2:1) or too aggressively (ratio 3:1), both of which hurt productivity.
Key Vicidial Campaign Settings
Navigate to Admin > Campaigns > Edit Campaign for each campaign you want to tune:
| Setting | Default | Recommended | Effect |
|---|---|---|---|
dial_ratio | 1.0 | Adaptive | Calls per available agent |
auto_dial_level | MANUAL | ADAPT_TANH | Use adaptive algorithm |
adaptive_dropped_percentage | 3 | 3 | FTC compliance target |
dial_timeout | 30 | 20–25 | Seconds before AMD / abandon |
drop_call_seconds | 3 | 2 | Seconds before drop if no agent |
dead_seconds | 1 | 0 | Delay before drop (set 0) |
available_only_ratio | N | Y | Only count truly available agents |
calls_waiting_size_limit | 0 | 2 | Calls waiting buffer |
Setting auto_dial_level=ADAPT_TANH activates Vicidial's built-in adaptive mode. The TANH variant uses a hyperbolic tangent function to smooth ratio adjustments, preventing the oscillation you see with ADAPT_AVERAGE when agent availability spikes or drops suddenly.
Answering Machine Detection (AMD) Tuning
AMD is the biggest lever for talk-time productivity. Vicidial uses Asterisk's AMD application, which analyzes audio energy and silence patterns to classify calls as human or machine. Poor AMD configuration causes two problems:
- False positives (humans classified as machines) — agents never hear the call
- False negatives (machines passed to agents) — agents hear voicemail, waste time
Tune these parameters in /etc/asterisk/amd.conf:
[general]
initial_silence = 2500 ; Max silence before first word (ms)
greeting = 1500 ; Max length of greeting (ms)
after_greeting_silence = 800 ; Silence after greeting = machine
total_analysis_time = 5000 ; Max time to analyze
min_word_length = 100 ; Min word length (ms) — below this is noise
between_words_silence = 50 ; Silence between words = word boundary
maximum_number_of_words = 3 ; If > 3 words, probably machine
silence_threshold = 256 ; Energy threshold for silence detection
maximum_word_length = 5000 ; Single word longer than this = machine
Measure your AMD accuracy weekly. In a well-tuned system:
- Human detection rate: >90%
- Machine detection rate: >70%
- False positive rate (human called machine): <5%
Log AMD results via Vicidial's call_log table and query accuracy:
SELECT
call_date::date AS day,
SUM(CASE WHEN status = 'AMD' THEN 1 ELSE 0 END) AS machine_detected,
SUM(CASE WHEN status IN ('SALE', 'NI', 'NA', 'DNC') THEN 1 ELSE 0 END) AS human_connected,
SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS dropped,
COUNT(*) AS total_calls,
ROUND(
100.0 * SUM(CASE WHEN status IN ('SALE','NI','NA','DNC') THEN 1 ELSE 0 END) / COUNT(*),
1
) AS connect_rate_pct
FROM vicidial_log
WHERE call_date > NOW() - INTERVAL '7 days'
GROUP BY call_date::date
ORDER BY day DESC;
MySQL Performance Optimization
Vicidial is heavily database-driven. The predictive algorithm queries the vicidial_list table every second to select leads. On large campaigns (1M+ records), this query becomes the bottleneck.
Critical indexes:
-- vicidial_list: compound index for lead selection query
ALTER TABLE vicidial_list
ADD INDEX status_order_idx (status, list_id, gmt_offset_now, called_count, lead_id);
-- vicidial_log: index for recent performance queries
ALTER TABLE vicidial_log
ADD INDEX campaign_date_idx (campaign_id, call_date, status);
-- vicidial_agent_log: index for real-time agent stats
ALTER TABLE vicidial_agent_log
ADD INDEX agent_campaign_idx (campaign_id, event_time, user);
MySQL configuration for a dedicated Vicidial database server (32 GB RAM):
[mysqld]
innodb_buffer_pool_size = 24G # 75% of RAM
innodb_buffer_pool_instances = 8
innodb_log_file_size = 2G
innodb_flush_log_at_trx_commit = 2 # Faster writes, minimal data loss risk
innodb_flush_method = O_DIRECT
query_cache_type = 0 # Disable — Vicidial invalidates it constantly
max_connections = 500
thread_cache_size = 64
table_open_cache = 4000
innodb_flush_log_at_trx_commit=2 flushes the log buffer to OS every second rather than every transaction. On Vicidial's write-heavy workload, this typically doubles write throughput with negligible durability risk (you lose at most 1 second of data on crash, and CDRs are also in Asterisk).
Real-Time Agent Monitoring via ESL
Vicidial's built-in monitoring dashboard polls the database, which adds 1–3 second lag. For real-time dashboards, connect directly to Asterisk's Event Socket Layer:
import socket
def monitor_active_calls():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('127.0.0.1', 8021))
# Authenticate
sock.sendall(b'auth ClueCon\r\n\r\n')
response = sock.recv(1024)
# Subscribe to channel events
sock.sendall(b'event plain CHANNEL_CREATE CHANNEL_HANGUP CHANNEL_BRIDGE\r\n\r\n')
while True:
data = sock.recv(4096).decode()
if 'CHANNEL_CREATE' in data:
process_new_call(data)
elif 'CHANNEL_HANGUP' in data:
process_hangup(data)
elif 'CHANNEL_BRIDGE' in data:
process_agent_connected(data)
ESL events arrive within 50ms of the actual channel event — fast enough to update a real-time dashboard without database polling.
Compliance: Abandon Rate Enforcement
US FTC regulations require abandon rates below 3% per campaign per 30-day period. Vicidial's adaptive mode tracks this internally, but you should also verify from the database:
-- Monthly abandon rate by campaign (FTC calculation)
SELECT
campaign_id,
COUNT(*) AS total_connected,
SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS abandoned,
ROUND(
100.0 * SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) / COUNT(*),
2
) AS abandon_rate_pct
FROM vicidial_log
WHERE call_date >= DATE_TRUNC('month', NOW())
AND status NOT IN ('AMD', 'CBHOLD', 'CFAIL') -- Exclude non-connected
GROUP BY campaign_id
HAVING abandon_rate_pct > 2.5 -- Alert before hitting 3% limit
ORDER BY abandon_rate_pct DESC;
Run this query from a cron job every hour and alert when any campaign approaches 2.5%. At 2.5% you have margin to reduce the dial ratio before crossing the compliance threshold.
Lead List Hygiene
A clean lead list has a larger impact on agent productivity than any algorithm tuning. Before loading a list:
- Scrub against the National Do Not Call Registry (required by law)
- Remove duplicates by phone number within the last 30 days
- Filter disconnected numbers using carrier lookup APIs (Twilio Lookup, Numverify)
- Set time zone based on area code — never dial outside 8 AM–9 PM local time
A list with 20% bad numbers means 20% of your dial capacity is wasted on disconnects. Carrier lookup APIs cost $0.005–$0.01 per number. On a 100,000-number list, $500–$1,000 of cleanup saves significant agent idle time over the campaign lifetime.
Expected Results After Tuning
| Metric | Before tuning | After tuning |
|---|---|---|
| Agent talk time per hour | 32 min | 48 min |
| Connect rate | 18% | 28% |
| AMD accuracy | 65% | 88% |
| Abandon rate | 8% | 2.5% |
| DB query time (lead select) | 800ms | 45ms |
These numbers come from a 50-agent campaign on a list of 500,000 records after applying the indexes, AMD tuning, and adaptive dial level changes described above.




