Asterisk AMD's 15–20% False Positive Problem (And How to Fix It)
Why Asterisk's res_amd module hangs up on 15-20% of live humans, traced through the actual source logic — and the three remediation paths, from retuning amd.conf to replacing the detector entirely.
Marketing Team
VM Hunter

If you run outbound calling on Asterisk, your dialer is probably hanging up on somewhere between 15 and 20 percent of the live humans who answer your calls.
That is not a provocation. It is a direct consequence of how res_amd decides what a machine is, and it is derivable from the module's own source logic without needing to run a single test call. The reason almost nobody knows their actual number is not negligence — it is that the failure is structurally invisible in Asterisk's logs. A human you wrongly hung up on and a voicemail you correctly detected produce the same log entry.
This article traces the problem to its origin in the detection logic, quantifies what it costs, and covers the three remediation paths in ascending order of effectiveness — including an honest assessment of how much the cheapest option can actually buy you.
The Two Errors, and Why Only One Matters
Every classifier has two ways to be wrong, and answering machine detection has an unusually extreme cost asymmetry between them.
False negative — machine classified as human. A voicemail greeting reaches an agent. The agent hears "leave a message after the tone" and disconnects. Cost: six to ten seconds of paid agent time. Annoying, measurable, cheap.
False positive — human classified as machine. Your dialer hangs up on a real person who just said "hello." Cost: a burned contact, a negative brand impression, and in collections, healthcare, or financial services a potential compliance exposure — from the recipient's side, a silent hang-up is indistinguishable from an abandoned robocall.
Eight seconds of agent time versus a permanently lost contact. These are not comparable quantities, which is why any single blended "accuracy" number is close to useless. A detector can post 85% accuracy while generating a catastrophic false positive rate, or post the same 85% while being safe. The blended figure cannot distinguish those two systems.
Asterisk's defaults are tuned toward aggressively catching machines. That choice was made in 2006, in a telephony environment that no longer exists, and it is still the default today.
Where the 15–20% Comes From
res_amd implements a purely durational model. It measures how long sound occurs and how long silence occurs during the opening seconds of a connected call, then compares those durations against fixed thresholds. Here is the full parameter set from amd.conf:
| Parameter | Default | What it controls |
|---|---|---|
initial_silence | 2500 ms | Silence before any speech; exceeded → machine |
greeting | 1500 ms | Longest allowable single "human" greeting |
after_greeting_silence | 800 ms | Pause after speech stops |
total_analysis_time | 5000 ms | Hard decision deadline |
min_word_length | 100 ms | Minimum sound counted as a word |
between_words_silence | 50 ms | Gap that separates two words |
maximum_number_of_words | 3 | More than this → machine |
silence_threshold | 256 | Energy level treated as silence |
The decision logic reduces to a small set of rules evaluated as audio streams in. Expressed as pseudocode, this is essentially what the module does:
if silence_before_speech > initial_silence:
return MACHINE # cause: INITIALSILENCE
if word_count > maximum_number_of_words:
return MACHINE # cause: MAXWORDS
if single_greeting_duration > greeting:
return MACHINE # cause: LONGGREETING
if silence_after_speech > after_greeting_silence:
return HUMAN # cause: HUMAN
if elapsed > total_analysis_time:
return NOTSURE # cause: TOOLONG
Read those first three rules carefully, because each one is an independent way to hang up on a person.
Now notice the critical absence: nowhere in this logic is there any representation of what was said. The module has no access to greeting content. It cannot tell "Hello?" from "You've reached Dana." It only knows that sound happened for roughly this long, then stopped for roughly that long.
The governing assumption is: humans answer briefly then wait; machines talk longer then beep. Here is why that breaks on modern traffic.
Failure 1 — The talkative human (trips MAXWORDS and LONGGREETING). "Good morning, this is Dana speaking, how can I help you?" is eleven words over roughly 2.4 seconds. It exceeds maximum_number_of_words of 3 and greeting of 1500 ms. Classified as a machine, twice over. This is not an edge case — it is how professionals answer business phones, which means the failure concentrates precisely in B2B campaigns where contacts are most expensive.
Failure 2 — The terse voicemail (returns HUMAN). "Leave a message." Three words, under 1500 ms, followed by silence. Every rule says human. Routed to an agent.
Failure 3 — Mobile networks corrupt the measurements. Roughly 70% of outbound volume now terminates on mobile. Comfort-noise generation means "silence" is not silent, so silence_threshold of 256 misreads it as speech. Variable jitter stretches and compresses apparent durations. Codec transitions inject artifacts that read as words. The entire model rests on precise interval measurement, and mobile networks make those intervals unreliable.
Failure 4 — Slow answers trip INITIALSILENCE. Someone digging a phone out of a bag, or a call center's own ringback delay, can push pre-speech silence past 2500 ms. Machine.
Failure 5 — Everything that is neither. IVR trees, carrier screening announcements, "the person you are calling is not accepting calls" — the model has two output categories and these fit neither, producing effectively arbitrary results.
Aggregate these across realistic traffic and the 15–20% false positive figure is not surprising. It is what the rules predict.
Why You Have Never Seen the Number
Here is the part that makes this problem persistent rather than merely bad.
When res_amd returns MACHINE, your dialplan hangs up or drops a message, and the call is logged. Consider the two possible realities behind that log entry:
- It was genuinely a voicemail. Log says machine. Correct.
- It was a live human. Log says machine. Also says machine.
There is no field, flag, or report anywhere in a stock Asterisk or VICIdial installation that distinguishes these. The false positive rate is not merely unmeasured — it is unmeasurable without deliberately constructing an experiment. Your CDRs cannot contain it.
This produces a specific and damaging organizational dynamic. Managers see the metric that is visible — voicemails reaching agents, which is the false negative — and respond by tuning AMD more aggressively. Tightening greeting or lowering maximum_number_of_words reduces the visible problem while increasing the invisible one. The reporting actively rewards making false positives worse.
Meanwhile the symptom surfaces as unattributable noise: contact rates that underperform list quality, prospects who mention being hung up on, campaigns that mysteriously underperform on mobile-heavy lists. None of it traces back to the detector, because nothing connects them.
What It Costs
Take an operation running 50,000 dials per day at a 30% answer rate. That is 15,000 connected calls; roughly 40% reach live humans, so about 6,000 human contacts daily.
At a 15% false positive rate: about 900 live humans hung up on per day. Over a 250-day year, 225,000 people who were dialled, who answered, and who were disconnected before anyone spoke.
The costs stack in three layers:
Direct pipeline loss. Those 900 daily contacts were reachable and are now spent. At a 2% close rate and a $500 average contract value, roughly $9,000 per day in lost pipeline — call it $2.25M annually.
List degradation. Most dialers retry a "machine" result on a schedule. So the same human gets called again, answers again, gets hung up on again. Contacts that are reachable get progressively burned while the list reports them as machine-answered.
Compliance and brand. Silent hang-ups are exactly the pattern abandoned-call regulations exist to address. In regulated verticals a 15% rate of dropped live answers is a genuine exposure, not merely an inefficiency.
The recovered agent time from fixing false negatives — the visible problem — is worth a few thousand dollars a month. The invisible problem is worth two orders of magnitude more.
Fix 1: Retune amd.conf
The zero-cost option. It helps, and it has a hard ceiling.
The single highest-impact change is maximum_number_of_words, because a default of 3 is simply wrong for modern business calls:
[general]
; Safer settings biased against dropping humans
initial_silence = 4000 ; was 2500 - tolerate slow answers
greeting = 3000 ; was 1500 - allow real greetings
after_greeting_silence = 1200 ; was 800
total_analysis_time = 5000
min_word_length = 120 ; was 100 - fewer artifacts as words
between_words_silence = 60 ; was 50
maximum_number_of_words = 8 ; was 3 - the biggest single win
silence_threshold = 320 ; was 256 - accommodate mobile noise floor
Every one of those changes trades false negatives for false positives — you will see more voicemails reaching agents. Given the cost asymmetry, that is the correct trade.
Then instrument the decisions so you know which rule is firing:
exten => _X.,n,AMD()
exten => _X.,n,NoOp(AMD=${AMDSTATUS} CAUSE=${AMDCAUSE})
exten => _X.,n,Set(CDR(userfield)=${AMDSTATUS}:${AMDCAUSE})
Then count causes:
SELECT userfield, COUNT(*) AS calls
FROM cdr
WHERE calldate >= NOW() - INTERVAL 7 DAY
GROUP BY userfield
ORDER BY calls DESC;
If MACHINE:MAXWORDS and MACHINE:LONGGREETING dominate, you are dropping talkative humans. If MACHINE:INITIALSILENCE dominates, look at ringback timing and carrier behavior before touching thresholds.
The ceiling. Careful tuning typically moves false positives from 15–20% into the 8–12% range. That is a real improvement worth making today, but it is not a solution — because tuning cannot add information that was never captured. Consider these two clips, each 1.8 s of speech followed by 700 ms of silence:
- "Good morning, Dana speaking."
- "You've reached Dana Whitfield."
Durationally identical. Any parameter set must classify them the same way, and one of those classifications is wrong. No value of any threshold in amd.conf separates them, because the separating evidence is lexical and the module cannot see words.
That is an information ceiling, not a tuning problem.
Fix 2: Route Uncertainty to Humans
The second cheap improvement: stop treating NOTSURE as a machine.
Many dialplans lump NOTSURE with MACHINE, which converts every ambiguous call into a potential dropped human. Route it to an agent instead:
exten => _X.,n,GotoIf($["${AMDSTATUS}" = "MACHINE"]?machine,1)
exten => _X.,n,Dial(${TRUNK}/${EXTEN},,tTo) ; HUMAN and NOTSURE both reach an agent
You can also raise total_analysis_time so that genuinely ambiguous calls land in NOTSURE rather than being forced into a premature MACHINE verdict.
This does not improve the detector's discrimination at all — it changes what happens when the detector admits it does not know, which is a meaningful reduction in dropped humans for zero engineering effort.
Fix 3: Replace the Detector
Breaking the ceiling requires processing information res_amd never captures — starting with greeting content.
Modern AI detection evaluates several independent classes of evidence concurrently rather than as a threshold cascade:
- Tone detection for beeps and SIT tones
- Signalling and call-progress indicators
- Energy envelope shape
- Silence texture — distinguishing a live room's noise floor from digital silence
- Channel fingerprinting for codec and network path
- Playback artifacts indicating recorded rather than live audio
- Linguistic content of the greeting
- Learned fusion across all layers
Parallelism is what matters architecturally. In res_amd, any single threshold misfiring produces a wrong answer — the rules are a chain of independent failure points. When layers are evaluated concurrently and fused, individual signals can be inconclusive without the classification failing. A noisy mobile connection that destroys the silence measurement still yields a confident verdict from content and playback artifacts.
Content is what resolves the "Dana speaking" versus "You've reached Dana" case, because "you've reached" is among the strongest voicemail indicators in English and a durational model cannot use it.
This also enables categories res_amd cannot represent at all — IVR trees, carrier screening announcements, disconnect and SIT tones, fax tones — each of which deserves different handling. Screening announcements in particular may still connect to a human afterward, so hanging up wastes a reachable contact.
Measured false positive rates for this approach land around 0.2%, against 15–20% for stock res_amd and 8–12% for carefully tuned res_amd.
On Asterisk the integration is additive rather than a migration. You bypass res_amd, mirror the inbound RTP stream over a WebSocket as 8 kHz PCM, and write the result back into the same AMDSTATUS and AMDCAUSE channel variables your dialplan already branches on. Nothing downstream changes, and rollback is uncommenting one line.
Two implementation requirements are non-negotiable:
Fail open. If the classifier is unreachable or times out, return NOTSURE and route to an agent. Never let a network failure become a hang-up. Test this deliberately with a firewall rule mid-campaign — an untested fallback is not a fallback.
Set thresholds by campaign economics. Confidence required to act on a MACHINE label should reflect what a dropped contact costs:
| Campaign type | Confidence to act on MACHINE |
|---|---|
| Appointment reminders | 0.85 |
| Cold B2C prospecting | 0.90 |
| B2B outbound | 0.95 |
| Existing customer service | 0.97 |
| Collections / regulated | 0.98 |
Measure Your Own Rate First
Before choosing a fix, get your baseline. This protocol is the only way to obtain a number that does not exist in your logs.
1. Log AMD decisions with causes using the CDR(userfield) approach above.
2. Run in shadow mode. Route every call to an agent regardless of the verdict, while recording what the detector would have done.
3. Capture agent ground truth. Have agents disposition what they actually reached: live person, voicemail, IVR, disconnected.
4. Cross-tabulate.
| Agent reached human | Agent reached machine | |
|---|---|---|
| AMD said HUMAN | True negative | False negative |
| AMD said MACHINE | False positive | True positive |
Bottom-left divided by total humans reached is your false positive rate — the number that was previously invisible.
5. Segment it. Aggregates hide the failures. Break results down by mobile vs. landline, by carrier, by time of day, by greeting language, and by campaign type. Mobile-heavy B2B segments will almost always be worst, because that is where talkative greetings and corrupted silence measurement compound.
6. Include the hard cases deliberately. Any detector handles a clean landline voicemail with a loud beep. Make sure your sample contains talkative human greetings, terse voicemail, IVR trees, screening announcements, and calls answered in noisy environments.
Run at least 2,000 calls across a full week. A single afternoon overfits to that afternoon.
Conclusion
res_amd is not badly written. It is a faithful implementation of an approach whose useful life ended when mobile networks became the majority of outbound traffic and business greetings got longer than three words. The 15–20% false positive rate is not a bug — it is the predictable output of measuring durations while ignoring content.
Three things to do, in order:
- Retune
amd.conftoday. Raisingmaximum_number_of_wordsfrom 3 to 8 is the single highest-value line change available to you. Expect to reach 8–12% — better, not fixed. - Route
NOTSUREto agents. Free, immediate, and reduces dropped humans without touching the model. - Measure your actual rate, then decide about replacement. Shadow mode plus agent dispositions gives you the number in about a week.
Do the measurement regardless of which fix you choose. The false positive rate is the most consequential unknown quantity in most Asterisk outbound operations — it is invisible by construction, it compounds daily, and the reporting you already have will never surface it.
Start your free trial — 5,000 calls per month at no cost, no credit card required. Or read the setup guide for step-by-step integration details.