VICIdial is the most widely deployed open-source contact center platform in the world. It runs on thousands of servers across hundreds of contact centers, handling millions of calls per day. Its built-in answering machine detection, however, was designed in a different era — and it shows.
Default VICIdial AMD relies on audio energy analysis and silence detection. It works well enough for simple cases but struggles with modern voicemail greetings, carrier-side audio processing, and the latency patterns introduced by VoIP infrastructure. The result is a false positive rate that most operations accept as unavoidable.
It is not unavoidable. Here is how to replace it.
How VICIdial AMD Works by Default
VICIdial's AMD is implemented through Asterisk's AMD application, which is the underlying telephony engine. When a call connects, Asterisk listens to the first few seconds of audio and applies a set of heuristics:
- Initial silence duration (long silence suggests machine greeting)
- Word count in the initial audio burst (machines tend to speak in longer uninterrupted segments)
- Total talking time vs. silence time ratio
- Presence of a beep tone following extended speech
These heuristics are tunable via parameters in the VICIdial admin panel, but the fundamental approach cannot be changed without replacing the AMD engine entirely. Tuning helps at the margins; it cannot close the accuracy gap between rules-based and neural approaches.
The Integration Architecture
Connecting amdify.io to VICIdial works by intercepting the audio stream at the Asterisk level and routing it to the amdify.io API before the call is delivered to an agent.
The flow looks like this:
- VICIdial initiates an outbound call
- The call connects on the carrier side
- Instead of passing audio directly to VICIdial's built-in AMD, Asterisk sends the audio stream to the amdify.io endpoint
- amdify.io returns a classification — HUMAN or MACHINE — within 200ms
- Asterisk routes the call based on the classification: HUMAN calls go to the agent queue, MACHINE calls trigger your voicemail handling logic
This approach requires no changes to your VICIdial campaign configuration, agent workflows, or reporting. It is a drop-in replacement for the AMD decision, not a replacement for the dialer.
Prerequisites
Before starting, confirm you have:
- VICIdial version 2.14 or later (earlier versions may require additional configuration)
- Root or sudo access to your Asterisk server
- Your amdify.io API key from the dashboard
- Basic familiarity with editing Asterisk configuration files
The integration requires editing two files: extensions.conf (or your custom dialplan) and creating a small AGI script that handles the API call to amdify.io.
Step 1 — Disable VICIdial's Built-In AMD
In the VICIdial admin panel, navigate to Admin > System Settings. Find the AMD section and set the AMD mode to "DISABLED" for the campaigns you are migrating. Do not disable AMD globally until you have confirmed the new integration is working correctly.
Alternatively, you can set the AMD timeout to a very low value (500ms) which effectively disables it without changing the configuration flag — useful if you want to roll back quickly during testing.
Step 2 — Install the AGI Script
Create a file at /usr/share/asterisk/agi-bin/amdify_check.agi with the following content:
#!/usr/bin/perl
use strict;
use LWP::UserAgent;
use JSON;
my $api_key = 'YOUR_AMDIFY_API_KEY';
my $api_url = 'https://api.amdify.io/v1/classify';
# Read AGI environment
my %agi_vars;
while (my $line = <STDIN>) {
chomp $line;
last unless $line;
if ($line =~ /^agi_(\w+):\s*(.*)$/) {
$agi_vars{$1} = $2;
}
}
# Get audio file path from argument
my $audio_file = $ARGV[0];
# POST to amdify.io API
my $ua = LWP::UserAgent->new(timeout => 2);
my $response = $ua->post($api_url,
'Authorization' => "Bearer $api_key",
'Content-Type' => 'application/json',
Content => encode_json({ audio_file => $audio_file })
);
my $result = 'HUMAN'; # default to HUMAN on any error
if ($response->is_success) {
my $data = decode_json($response->decoded_content);
$result = $data->{classification} // 'HUMAN';
}
print "SET VARIABLE AMDIFY_RESULT $result\n";
my $ack = <STDIN>;
Make the script executable: chmod +x /usr/share/asterisk/agi-bin/amdify_check.agi
Step 3 — Modify the Dialplan
In your extensions.conf or custom dialplan, find the outbound call handling context. Add the AGI call after the call connects and before agent delivery:
[outbound-amd]
exten => s,1,Answer()
exten => s,n,Record(/tmp/amd_sample_${UNIQUEID}:wav,3,5)
exten => s,n,AGI(amdify_check.agi,/tmp/amd_sample_${UNIQUEID}.wav)
exten => s,n,GotoIf($["${AMDIFY_RESULT}" = "MACHINE"]?machine,s,1)
exten => s,n,Goto(agent-delivery,s,1)
[machine]
exten => s,1,Playback(your-voicemail-message)
exten => s,n,Hangup()
Reload Asterisk: asterisk -rx "dialplan reload"
Step 4 — Test Before Going Live
Run a test campaign of 50–100 calls with both the old AMD logs and new amdify.io classifications running in parallel. Compare the results:
- Calls classified as HUMAN by amdify.io but MACHINE by old AMD: listen to a sample — these are likely your recovered false positives
- Calls classified as MACHINE by amdify.io but HUMAN by old AMD: listen to a sample — verify these are actual voicemails
Expect amdify.io to classify more calls as HUMAN. That is the point — you are recovering calls that were previously being incorrectly dropped.
Step 5 — Monitor in the Dashboard
Once live, your amdify.io dashboard will show classification volumes, confidence scores, and detection latency in real time. Set up an alert if the HUMAN classification rate drops below your baseline — this can indicate a configuration issue or a shift in your call list quality.
Common Issues
API timeout causing calls to drop: The AGI script defaults the result to HUMAN on any API error. If you see unexplained HUMAN classifications, check your server's outbound connectivity to api.amdify.io.
Audio recording quality: The AMD classification is only as good as the audio sample. Ensure your recording captures the first 3–5 seconds of the call. Problems with carrier-side audio (excessive echo, very low volume) will reduce accuracy.
High latency on first classification: The first call after a server restart may have higher latency as connections are established. Subsequent calls use persistent connections and will be within the sub-200ms target.
Final Thoughts
The integration is a configuration change, not an infrastructure project. Once the AGI script is in place and the dialplan is updated, the change is transparent to your agents, your campaigns, and your reporting.
The accuracy improvement is immediate. Most operations see connect rate improvement within the first hour of going live — not because anything changed in their call lists, but because the same calls that were always connecting are now being correctly identified.