[{"data":1,"prerenderedAt":920},["ShallowReactive",2],{"post-\u002Fblog\u002Fvicidial-predictive-dialer-tuning":3},{"id":4,"title":5,"author":6,"body":7,"category":903,"coverImage":904,"date":905,"description":906,"extension":907,"meta":908,"navigation":472,"path":909,"readingTime":322,"seo":910,"stem":911,"tags":912,"__hash__":919},"posts\u002Fblog\u002Fvicidial-predictive-dialer-tuning.md","Vicidial Predictive Dialer Tuning: Maximizing Agent Productivity","Tumarm Engineering",{"type":8,"value":9,"toc":893},"minimark",[10,14,18,23,26,37,40,56,62,65,69,72,222,237,241,248,256,263,332,335,346,353,434,438,445,448,508,511,566,572,576,579,695,698,702,705,782,785,789,792,807,810,814,886,889],[11,12,5],"h1",{"id":13},"vicidial-predictive-dialer-tuning-maximizing-agent-productivity",[15,16,17],"p",{},"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.",[19,20,22],"h2",{"id":21},"how-the-predictive-algorithm-works","How the Predictive Algorithm Works",[15,24,25],{},"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:",[27,28,33],"pre",{"className":29,"code":31,"language":32},[30],"language-text","dial_ratio = available_agents × (1 \u002F (1 - target_abandon_rate)) × safety_margin\n","text",[34,35,31],"code",{"__ignoreMap":36},"",[15,38,39],{},"Where:",[41,42,43,50],"ul",{},[44,45,46,49],"li",{},[34,47,48],{},"target_abandon_rate"," is typically 3% (FTC limit in the US) or 5% (Ofcom limit in the UK)",[44,51,52,55],{},[34,53,54],{},"safety_margin"," is 0.85–0.95 (accounts for prediction error)",[15,57,58,59],{},"At 3% target abandon rate: ",[34,60,61],{},"dial_ratio = agents × 1.031 × 0.9 ≈ agents × 0.928",[15,63,64],{},"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.",[19,66,68],{"id":67},"key-vicidial-campaign-settings","Key Vicidial Campaign Settings",[15,70,71],{},"Navigate to Admin > Campaigns > Edit Campaign for each campaign you want to tune:",[73,74,75,94],"table",{},[76,77,78],"thead",{},[79,80,81,85,88,91],"tr",{},[82,83,84],"th",{},"Setting",[82,86,87],{},"Default",[82,89,90],{},"Recommended",[82,92,93],{},"Effect",[95,96,97,114,130,145,161,176,192,208],"tbody",{},[79,98,99,105,108,111],{},[100,101,102],"td",{},[34,103,104],{},"dial_ratio",[100,106,107],{},"1.0",[100,109,110],{},"Adaptive",[100,112,113],{},"Calls per available agent",[79,115,116,121,124,127],{},[100,117,118],{},[34,119,120],{},"auto_dial_level",[100,122,123],{},"MANUAL",[100,125,126],{},"ADAPT_TANH",[100,128,129],{},"Use adaptive algorithm",[79,131,132,137,140,142],{},[100,133,134],{},[34,135,136],{},"adaptive_dropped_percentage",[100,138,139],{},"3",[100,141,139],{},[100,143,144],{},"FTC compliance target",[79,146,147,152,155,158],{},[100,148,149],{},[34,150,151],{},"dial_timeout",[100,153,154],{},"30",[100,156,157],{},"20–25",[100,159,160],{},"Seconds before AMD \u002F abandon",[79,162,163,168,170,173],{},[100,164,165],{},[34,166,167],{},"drop_call_seconds",[100,169,139],{},[100,171,172],{},"2",[100,174,175],{},"Seconds before drop if no agent",[79,177,178,183,186,189],{},[100,179,180],{},[34,181,182],{},"dead_seconds",[100,184,185],{},"1",[100,187,188],{},"0",[100,190,191],{},"Delay before drop (set 0)",[79,193,194,199,202,205],{},[100,195,196],{},[34,197,198],{},"available_only_ratio",[100,200,201],{},"N",[100,203,204],{},"Y",[100,206,207],{},"Only count truly available agents",[79,209,210,215,217,219],{},[100,211,212],{},[34,213,214],{},"calls_waiting_size_limit",[100,216,188],{},[100,218,172],{},[100,220,221],{},"Calls waiting buffer",[15,223,224,225,228,229,232,233,236],{},"Setting ",[34,226,227],{},"auto_dial_level=ADAPT_TANH"," activates Vicidial's built-in adaptive mode. The ",[34,230,231],{},"TANH"," variant uses a hyperbolic tangent function to smooth ratio adjustments, preventing the oscillation you see with ",[34,234,235],{},"ADAPT_AVERAGE"," when agent availability spikes or drops suddenly.",[19,238,240],{"id":239},"answering-machine-detection-amd-tuning","Answering Machine Detection (AMD) Tuning",[15,242,243,244,247],{},"AMD is the biggest lever for talk-time productivity. Vicidial uses Asterisk's ",[34,245,246],{},"AMD"," application, which analyzes audio energy and silence patterns to classify calls as human or machine. Poor AMD configuration causes two problems:",[41,249,250,253],{},[44,251,252],{},"False positives (humans classified as machines) — agents never hear the call",[44,254,255],{},"False negatives (machines passed to agents) — agents hear voicemail, waste time",[15,257,258,259,262],{},"Tune these parameters in ",[34,260,261],{},"\u002Fetc\u002Fasterisk\u002Famd.conf",":",[27,264,268],{"className":265,"code":266,"language":267,"meta":36,"style":36},"language-ini shiki shiki-themes github-light github-dark","[general]\ninitial_silence = 2500      ; Max silence before first word (ms)\ngreeting = 1500             ; Max length of greeting (ms)\nafter_greeting_silence = 800 ; Silence after greeting = machine\ntotal_analysis_time = 5000  ; Max time to analyze\nmin_word_length = 100       ; Min word length (ms) — below this is noise\nbetween_words_silence = 50  ; Silence between words = word boundary\nmaximum_number_of_words = 3 ; If > 3 words, probably machine\nsilence_threshold = 256     ; Energy threshold for silence detection\nmaximum_word_length = 5000  ; Single word longer than this = machine\n","ini",[34,269,270,278,284,290,296,302,308,314,320,326],{"__ignoreMap":36},[271,272,275],"span",{"class":273,"line":274},"line",1,[271,276,277],{},"[general]\n",[271,279,281],{"class":273,"line":280},2,[271,282,283],{},"initial_silence = 2500      ; Max silence before first word (ms)\n",[271,285,287],{"class":273,"line":286},3,[271,288,289],{},"greeting = 1500             ; Max length of greeting (ms)\n",[271,291,293],{"class":273,"line":292},4,[271,294,295],{},"after_greeting_silence = 800 ; Silence after greeting = machine\n",[271,297,299],{"class":273,"line":298},5,[271,300,301],{},"total_analysis_time = 5000  ; Max time to analyze\n",[271,303,305],{"class":273,"line":304},6,[271,306,307],{},"min_word_length = 100       ; Min word length (ms) — below this is noise\n",[271,309,311],{"class":273,"line":310},7,[271,312,313],{},"between_words_silence = 50  ; Silence between words = word boundary\n",[271,315,317],{"class":273,"line":316},8,[271,318,319],{},"maximum_number_of_words = 3 ; If > 3 words, probably machine\n",[271,321,323],{"class":273,"line":322},9,[271,324,325],{},"silence_threshold = 256     ; Energy threshold for silence detection\n",[271,327,329],{"class":273,"line":328},10,[271,330,331],{},"maximum_word_length = 5000  ; Single word longer than this = machine\n",[15,333,334],{},"Measure your AMD accuracy weekly. In a well-tuned system:",[41,336,337,340,343],{},[44,338,339],{},"Human detection rate: >90%",[44,341,342],{},"Machine detection rate: >70%",[44,344,345],{},"False positive rate (human called machine): \u003C5%",[15,347,348,349,352],{},"Log AMD results via Vicidial's ",[34,350,351],{},"call_log"," table and query accuracy:",[27,354,358],{"className":355,"code":356,"language":357,"meta":36,"style":36},"language-sql shiki shiki-themes github-light github-dark","SELECT\n    call_date::date AS day,\n    SUM(CASE WHEN status = 'AMD' THEN 1 ELSE 0 END) AS machine_detected,\n    SUM(CASE WHEN status IN ('SALE', 'NI', 'NA', 'DNC') THEN 1 ELSE 0 END) AS human_connected,\n    SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS dropped,\n    COUNT(*) AS total_calls,\n    ROUND(\n        100.0 * SUM(CASE WHEN status IN ('SALE','NI','NA','DNC') THEN 1 ELSE 0 END) \u002F COUNT(*),\n        1\n    ) AS connect_rate_pct\nFROM vicidial_log\nWHERE call_date > NOW() - INTERVAL '7 days'\nGROUP BY call_date::date\nORDER BY day DESC;\n","sql",[34,359,360,365,370,375,380,385,390,395,400,405,410,416,422,428],{"__ignoreMap":36},[271,361,362],{"class":273,"line":274},[271,363,364],{},"SELECT\n",[271,366,367],{"class":273,"line":280},[271,368,369],{},"    call_date::date AS day,\n",[271,371,372],{"class":273,"line":286},[271,373,374],{},"    SUM(CASE WHEN status = 'AMD' THEN 1 ELSE 0 END) AS machine_detected,\n",[271,376,377],{"class":273,"line":292},[271,378,379],{},"    SUM(CASE WHEN status IN ('SALE', 'NI', 'NA', 'DNC') THEN 1 ELSE 0 END) AS human_connected,\n",[271,381,382],{"class":273,"line":298},[271,383,384],{},"    SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS dropped,\n",[271,386,387],{"class":273,"line":304},[271,388,389],{},"    COUNT(*) AS total_calls,\n",[271,391,392],{"class":273,"line":310},[271,393,394],{},"    ROUND(\n",[271,396,397],{"class":273,"line":316},[271,398,399],{},"        100.0 * SUM(CASE WHEN status IN ('SALE','NI','NA','DNC') THEN 1 ELSE 0 END) \u002F COUNT(*),\n",[271,401,402],{"class":273,"line":322},[271,403,404],{},"        1\n",[271,406,407],{"class":273,"line":328},[271,408,409],{},"    ) AS connect_rate_pct\n",[271,411,413],{"class":273,"line":412},11,[271,414,415],{},"FROM vicidial_log\n",[271,417,419],{"class":273,"line":418},12,[271,420,421],{},"WHERE call_date > NOW() - INTERVAL '7 days'\n",[271,423,425],{"class":273,"line":424},13,[271,426,427],{},"GROUP BY call_date::date\n",[271,429,431],{"class":273,"line":430},14,[271,432,433],{},"ORDER BY day DESC;\n",[19,435,437],{"id":436},"mysql-performance-optimization","MySQL Performance Optimization",[15,439,440,441,444],{},"Vicidial is heavily database-driven. The predictive algorithm queries the ",[34,442,443],{},"vicidial_list"," table every second to select leads. On large campaigns (1M+ records), this query becomes the bottleneck.",[15,446,447],{},"Critical indexes:",[27,449,451],{"className":355,"code":450,"language":357,"meta":36,"style":36},"-- vicidial_list: compound index for lead selection query\nALTER TABLE vicidial_list\nADD INDEX status_order_idx (status, list_id, gmt_offset_now, called_count, lead_id);\n\n-- vicidial_log: index for recent performance queries\nALTER TABLE vicidial_log\nADD INDEX campaign_date_idx (campaign_id, call_date, status);\n\n-- vicidial_agent_log: index for real-time agent stats\nALTER TABLE vicidial_agent_log\nADD INDEX agent_campaign_idx (campaign_id, event_time, user);\n",[34,452,453,458,463,468,474,479,484,489,493,498,503],{"__ignoreMap":36},[271,454,455],{"class":273,"line":274},[271,456,457],{},"-- vicidial_list: compound index for lead selection query\n",[271,459,460],{"class":273,"line":280},[271,461,462],{},"ALTER TABLE vicidial_list\n",[271,464,465],{"class":273,"line":286},[271,466,467],{},"ADD INDEX status_order_idx (status, list_id, gmt_offset_now, called_count, lead_id);\n",[271,469,470],{"class":273,"line":292},[271,471,473],{"emptyLinePlaceholder":472},true,"\n",[271,475,476],{"class":273,"line":298},[271,477,478],{},"-- vicidial_log: index for recent performance queries\n",[271,480,481],{"class":273,"line":304},[271,482,483],{},"ALTER TABLE vicidial_log\n",[271,485,486],{"class":273,"line":310},[271,487,488],{},"ADD INDEX campaign_date_idx (campaign_id, call_date, status);\n",[271,490,491],{"class":273,"line":316},[271,492,473],{"emptyLinePlaceholder":472},[271,494,495],{"class":273,"line":322},[271,496,497],{},"-- vicidial_agent_log: index for real-time agent stats\n",[271,499,500],{"class":273,"line":328},[271,501,502],{},"ALTER TABLE vicidial_agent_log\n",[271,504,505],{"class":273,"line":412},[271,506,507],{},"ADD INDEX agent_campaign_idx (campaign_id, event_time, user);\n",[15,509,510],{},"MySQL configuration for a dedicated Vicidial database server (32 GB RAM):",[27,512,514],{"className":265,"code":513,"language":267,"meta":36,"style":36},"[mysqld]\ninnodb_buffer_pool_size = 24G        # 75% of RAM\ninnodb_buffer_pool_instances = 8\ninnodb_log_file_size = 2G\ninnodb_flush_log_at_trx_commit = 2   # Faster writes, minimal data loss risk\ninnodb_flush_method = O_DIRECT\nquery_cache_type = 0                  # Disable — Vicidial invalidates it constantly\nmax_connections = 500\nthread_cache_size = 64\ntable_open_cache = 4000\n",[34,515,516,521,526,531,536,541,546,551,556,561],{"__ignoreMap":36},[271,517,518],{"class":273,"line":274},[271,519,520],{},"[mysqld]\n",[271,522,523],{"class":273,"line":280},[271,524,525],{},"innodb_buffer_pool_size = 24G        # 75% of RAM\n",[271,527,528],{"class":273,"line":286},[271,529,530],{},"innodb_buffer_pool_instances = 8\n",[271,532,533],{"class":273,"line":292},[271,534,535],{},"innodb_log_file_size = 2G\n",[271,537,538],{"class":273,"line":298},[271,539,540],{},"innodb_flush_log_at_trx_commit = 2   # Faster writes, minimal data loss risk\n",[271,542,543],{"class":273,"line":304},[271,544,545],{},"innodb_flush_method = O_DIRECT\n",[271,547,548],{"class":273,"line":310},[271,549,550],{},"query_cache_type = 0                  # Disable — Vicidial invalidates it constantly\n",[271,552,553],{"class":273,"line":316},[271,554,555],{},"max_connections = 500\n",[271,557,558],{"class":273,"line":322},[271,559,560],{},"thread_cache_size = 64\n",[271,562,563],{"class":273,"line":328},[271,564,565],{},"table_open_cache = 4000\n",[15,567,568,571],{},[34,569,570],{},"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).",[19,573,575],{"id":574},"real-time-agent-monitoring-via-esl","Real-Time Agent Monitoring via ESL",[15,577,578],{},"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:",[27,580,584],{"className":581,"code":582,"language":583,"meta":36,"style":36},"language-python shiki shiki-themes github-light github-dark","import socket\n\ndef monitor_active_calls():\n    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n    sock.connect(('127.0.0.1', 8021))\n    \n    # Authenticate\n    sock.sendall(b'auth ClueCon\\r\\n\\r\\n')\n    response = sock.recv(1024)\n    \n    # Subscribe to channel events\n    sock.sendall(b'event plain CHANNEL_CREATE CHANNEL_HANGUP CHANNEL_BRIDGE\\r\\n\\r\\n')\n    \n    while True:\n        data = sock.recv(4096).decode()\n        if 'CHANNEL_CREATE' in data:\n            process_new_call(data)\n        elif 'CHANNEL_HANGUP' in data:\n            process_hangup(data)\n        elif 'CHANNEL_BRIDGE' in data:\n            process_agent_connected(data)\n","python",[34,585,586,591,595,600,605,610,615,620,625,630,634,639,644,648,653,659,665,671,677,683,689],{"__ignoreMap":36},[271,587,588],{"class":273,"line":274},[271,589,590],{},"import socket\n",[271,592,593],{"class":273,"line":280},[271,594,473],{"emptyLinePlaceholder":472},[271,596,597],{"class":273,"line":286},[271,598,599],{},"def monitor_active_calls():\n",[271,601,602],{"class":273,"line":292},[271,603,604],{},"    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n",[271,606,607],{"class":273,"line":298},[271,608,609],{},"    sock.connect(('127.0.0.1', 8021))\n",[271,611,612],{"class":273,"line":304},[271,613,614],{},"    \n",[271,616,617],{"class":273,"line":310},[271,618,619],{},"    # Authenticate\n",[271,621,622],{"class":273,"line":316},[271,623,624],{},"    sock.sendall(b'auth ClueCon\\r\\n\\r\\n')\n",[271,626,627],{"class":273,"line":322},[271,628,629],{},"    response = sock.recv(1024)\n",[271,631,632],{"class":273,"line":328},[271,633,614],{},[271,635,636],{"class":273,"line":412},[271,637,638],{},"    # Subscribe to channel events\n",[271,640,641],{"class":273,"line":418},[271,642,643],{},"    sock.sendall(b'event plain CHANNEL_CREATE CHANNEL_HANGUP CHANNEL_BRIDGE\\r\\n\\r\\n')\n",[271,645,646],{"class":273,"line":424},[271,647,614],{},[271,649,650],{"class":273,"line":430},[271,651,652],{},"    while True:\n",[271,654,656],{"class":273,"line":655},15,[271,657,658],{},"        data = sock.recv(4096).decode()\n",[271,660,662],{"class":273,"line":661},16,[271,663,664],{},"        if 'CHANNEL_CREATE' in data:\n",[271,666,668],{"class":273,"line":667},17,[271,669,670],{},"            process_new_call(data)\n",[271,672,674],{"class":273,"line":673},18,[271,675,676],{},"        elif 'CHANNEL_HANGUP' in data:\n",[271,678,680],{"class":273,"line":679},19,[271,681,682],{},"            process_hangup(data)\n",[271,684,686],{"class":273,"line":685},20,[271,687,688],{},"        elif 'CHANNEL_BRIDGE' in data:\n",[271,690,692],{"class":273,"line":691},21,[271,693,694],{},"            process_agent_connected(data)\n",[15,696,697],{},"ESL events arrive within 50ms of the actual channel event — fast enough to update a real-time dashboard without database polling.",[19,699,701],{"id":700},"compliance-abandon-rate-enforcement","Compliance: Abandon Rate Enforcement",[15,703,704],{},"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:",[27,706,708],{"className":355,"code":707,"language":357,"meta":36,"style":36},"-- Monthly abandon rate by campaign (FTC calculation)\nSELECT\n    campaign_id,\n    COUNT(*) AS total_connected,\n    SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS abandoned,\n    ROUND(\n        100.0 * SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) \u002F COUNT(*),\n        2\n    ) AS abandon_rate_pct\nFROM vicidial_log\nWHERE call_date >= DATE_TRUNC('month', NOW())\n  AND status NOT IN ('AMD', 'CBHOLD', 'CFAIL')  -- Exclude non-connected\nGROUP BY campaign_id\nHAVING abandon_rate_pct > 2.5  -- Alert before hitting 3% limit\nORDER BY abandon_rate_pct DESC;\n",[34,709,710,715,719,724,729,734,738,743,748,753,757,762,767,772,777],{"__ignoreMap":36},[271,711,712],{"class":273,"line":274},[271,713,714],{},"-- Monthly abandon rate by campaign (FTC calculation)\n",[271,716,717],{"class":273,"line":280},[271,718,364],{},[271,720,721],{"class":273,"line":286},[271,722,723],{},"    campaign_id,\n",[271,725,726],{"class":273,"line":292},[271,727,728],{},"    COUNT(*) AS total_connected,\n",[271,730,731],{"class":273,"line":298},[271,732,733],{},"    SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) AS abandoned,\n",[271,735,736],{"class":273,"line":304},[271,737,394],{},[271,739,740],{"class":273,"line":310},[271,741,742],{},"        100.0 * SUM(CASE WHEN status = 'DROP' THEN 1 ELSE 0 END) \u002F COUNT(*),\n",[271,744,745],{"class":273,"line":316},[271,746,747],{},"        2\n",[271,749,750],{"class":273,"line":322},[271,751,752],{},"    ) AS abandon_rate_pct\n",[271,754,755],{"class":273,"line":328},[271,756,415],{},[271,758,759],{"class":273,"line":412},[271,760,761],{},"WHERE call_date >= DATE_TRUNC('month', NOW())\n",[271,763,764],{"class":273,"line":418},[271,765,766],{},"  AND status NOT IN ('AMD', 'CBHOLD', 'CFAIL')  -- Exclude non-connected\n",[271,768,769],{"class":273,"line":424},[271,770,771],{},"GROUP BY campaign_id\n",[271,773,774],{"class":273,"line":430},[271,775,776],{},"HAVING abandon_rate_pct > 2.5  -- Alert before hitting 3% limit\n",[271,778,779],{"class":273,"line":655},[271,780,781],{},"ORDER BY abandon_rate_pct DESC;\n",[15,783,784],{},"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.",[19,786,788],{"id":787},"lead-list-hygiene","Lead List Hygiene",[15,790,791],{},"A clean lead list has a larger impact on agent productivity than any algorithm tuning. Before loading a list:",[793,794,795,798,801,804],"ol",{},[44,796,797],{},"Scrub against the National Do Not Call Registry (required by law)",[44,799,800],{},"Remove duplicates by phone number within the last 30 days",[44,802,803],{},"Filter disconnected numbers using carrier lookup APIs (Twilio Lookup, Numverify)",[44,805,806],{},"Set time zone based on area code — never dial outside 8 AM–9 PM local time",[15,808,809],{},"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.",[19,811,813],{"id":812},"expected-results-after-tuning","Expected Results After Tuning",[73,815,816,829],{},[76,817,818],{},[79,819,820,823,826],{},[82,821,822],{},"Metric",[82,824,825],{},"Before tuning",[82,827,828],{},"After tuning",[95,830,831,842,853,864,875],{},[79,832,833,836,839],{},[100,834,835],{},"Agent talk time per hour",[100,837,838],{},"32 min",[100,840,841],{},"48 min",[79,843,844,847,850],{},[100,845,846],{},"Connect rate",[100,848,849],{},"18%",[100,851,852],{},"28%",[79,854,855,858,861],{},[100,856,857],{},"AMD accuracy",[100,859,860],{},"65%",[100,862,863],{},"88%",[79,865,866,869,872],{},[100,867,868],{},"Abandon rate",[100,870,871],{},"8%",[100,873,874],{},"2.5%",[79,876,877,880,883],{},[100,878,879],{},"DB query time (lead select)",[100,881,882],{},"800ms",[100,884,885],{},"45ms",[15,887,888],{},"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.",[890,891,892],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":36,"searchDepth":280,"depth":280,"links":894},[895,896,897,898,899,900,901,902],{"id":21,"depth":280,"text":22},{"id":67,"depth":280,"text":68},{"id":239,"depth":280,"text":240},{"id":436,"depth":280,"text":437},{"id":574,"depth":280,"text":575},{"id":700,"depth":280,"text":701},{"id":787,"depth":280,"text":788},{"id":812,"depth":280,"text":813},"Dialer","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1516321318423-f06f85e504b3?w=1200&q=80","2025-11-01","Tune Vicidial's predictive dialer for maximum agent productivity: dial ratio math, abandon rate compliance, MySQL query optimization, and Asterisk AGI integration patterns.","md",{},"\u002Fblog\u002Fvicidial-predictive-dialer-tuning",{"title":5,"description":906},"blog\u002Fvicidial-predictive-dialer-tuning",[913,914,915,916,917,918],"vicidial","predictive-dialer","asterisk","call-center","dialer-tuning","agi","LruH-okX53wG4D-RlBCIffnkI_w70nwfzHsqFNLYwV0",1776974166862]