Inspiration

Banks are starting to receive calls from autonomous AI agents—ASR + LLM + synthetic voice—that impersonate real customers. The Altur challenge (HackMTY 2026) provided us with real, human, and synthetic calls and asked us to distinguish between them using only the audio—even with voices we’d never heard before.

How it works

Given a stereo call (channel 0 = caller, channel 1 = agent), Dragons.io returns a verdict and a confidence score:

\( P(\text{synthetic} \mid x) = \sigma(\mathbf{w}^\top x + b), \qquad \text{is_synthetic} = \mathbb{1}[P \geq 0.5] \)

It never analyzes timbre or words—only how the caller speaks: response latency, turn regularity, interruptions, overlap, and silence filling. This signal is independent of the voice engine.

How We Built It

An energy-based VAD (channel-adjusted) reconstructs speech turns from the raw WAV file; 22 timing features are extracted, and a calibrated logistic regression scores them. Served via FastAPI (POST /detect), deployed on Vultr + systemd, with verdicts stored in TimescaleDB for a live dashboard.

Challenges We Faced

Our first acoustic model (MFCC + RandomForest) achieved:

$$\text{accuracy}_{\text{random split}} = 1.00$$

— a red flag, not a triumph: the judge set contains voices we’ve never seen before, and a random split doesn’t test for that. We built eval_generalization.py (leave-one-voice-cluster-out) and measured:

Model Acc. Synthetic recall Worst cluster
Dialogue only \(0.887\) \(0.907\) \(0.800\)
+ Acoustic (mixed) \(0.829\) \(0.707\) \(0.313\)

The acoustic feature was removed from production—based on evidence, not intuition. We also detected and disabled an acoustic tiebreaker that had reactivated on its own due to an exact tie when integrating a colleague’s parallel work.

Achievements

\(0.958\) accuracy in validation without using voice timbre; a permanent rule (eval_generalization.py) that every new feature must pass before going into production; a /detect endpoint that has never failed in production.

What We Learned

A perfect score on an easy test is a red flag, not a sign of success. Aligning the evaluation with the real threat—unseen voices—mattered more than any new feature.

What’s Next

A semantic approach (transcriptions using Vosk) is subject to the same rule: it does not go into production without passing eval_generalization.py. Looking ahead: applying the same behavioral approach to other types of phone fraud (insurance, SIM swapping, benefit verification).

Built With

Share this project:

Updates