AMD screens a just-answered call for a few seconds to decide whether a human or an answering machine picked up, before the call is attached to a CXB Core bot. It protects bot/conversation cost from being spent on voicemail greetings.

Where it sits in the flow

When AMD is enabled, an answered call transitions ringing → amd_screening before attaching. A lightweight screener joins the LiveKit room, listens briefly, classifies, then either attaches the call or tears it down.
ringing → amd_screening → attaching → in_progress
                  ↓ (machine/unknown, per action)
              torn down
If AMD is disabled, answered calls go straight ringing → attaching.

Configuration

AMD is configured in system settings under dialler.amd (the AMDConfig block). Common fields:
SettingDefaultMeaning
enabledfalseTurn AMD on for the deployment.
total_analysis_ms2000How long to listen before deciding (clamped 0.25–5s).
initial_silence_ms2000Silence before any speech that implies a machine.
greeting_ms2000Greeting length threshold for “long greeting” → machine.
max_words4More words than this in the greeting → machine.
beep_detection_enabledtrueDetect the voicemail beep tone (~850–1500 Hz) → machine.
action_on_machineteardownWhat to do when a machine is detected.
action_on_unknowncontinueWhat to do when the result is uncertain.
The detector is a deterministic audio-energy model (Asterisk/VICIdial-style timings) — it counts words, greeting length, silence, and beep tone.

Outcomes

The screen returns one of three decisions, which the loop maps to a campaign-call state:
DecisionCause examplesDefault actionResulting state
humanShort greeting then silence (a person saying “hello?”).Attach to bot.attachingin_progress
machineBeep, too many greeting words, very long greeting, initial silence.action_on_machine (teardown).amd_machine (terminal) when torn down.
unknownListen window elapsed without a confident decision.action_on_unknown (continue).Attaches when continue; closes as exhausted when teardown.
Actions are configurable. With action_on_machine = continue, a detected machine is still attached to the bot (no teardown). With action_on_unknown = teardown, uncertain results are closed instead of attached. Choose based on how aggressive you want machine suppression to be versus the risk of dropping real humans.

Metrics

Metric / statMeaning
machine_detected_countCampaign-level count of calls torn down as amd_machine.
amd_result / amd_causePer-attempt decision and reason (e.g. machine / BEEP), stored on the attempt and call docs.
amd_duration_msHow long screening took for that attempt.
Review machine_detected_count against expectations: a very high rate may mean AMD is too aggressive (dropping humans); a near-zero rate on a list with many landlines/voicemail may mean it is too lax.

Stale safety

AMD screening should last ~2 seconds. If the dialler dies mid-screen, a stale reaper closes any amd_screening row older than ~15s, tearing down the LiveKit room first so an answered call is never left stranded billing minutes.

Ops notes

  • AMD is a deployment-level setting (system settings), not a per-campaign toggle in the wizard.
  • AMD adds a short delay to every answered call before the bot speaks — keep total_analysis_ms modest.
  • Callback calls are screened too; a callback detected as a machine is closed like any other machine answer and its callback counters update.