Catch the scam before the payment
Scores the SMS, WhatsApp message or call transcript that starts the scam, names the workflow (digital arrest, KYC block, task job…) and warns once. A payment to a new payee within 72 h gets a cool off period.
A layered AI filter for mule accounts and scam money flows. A small gatekeeper model clears most payments; the rest are scored by gradient boosted trees and linked into ring cases, with reasons. Built and benchmarked on synthetic datasets.
Each layer approves what it is confident is clean and passes the rest to a heavier model, so heavier models only see about one payment in five. Figures below are committed benchmark results on synthetic data.
Scores the SMS, WhatsApp message or call transcript that starts the scam, names the workflow (digital arrest, KYC block, task job…) and warns once. A payment to a new payee within 72 h gets a cool off period.
LightGBM scores each new application, now trained on BAF Base and all five bias variants. Separate thresholds per age group keep false alarms even across customers.
An XGBoost model of 30 trees reads each account's history (fan-out, pass-through, first time payees) and approves the obvious.
The live API averages an XGBoost and a LightGBM model. Reasons come from XGBoost's per feature contributions. Random Forest and LSTM/Transformer blends exist only in the offline benchmark.
With consent, the scam message is redacted and scored for cues, then fused with new payee, amount and mule signature signals. A high band needs two domains; context alone can only hold a payment for an analyst.
Alerts that share accounts are merged into one case per mule cluster, so analysts review rings, not rows. A block needs two different analysts, and every action lands in a hash chained audit log.
Scammers have the password and the OTP; what they cannot hide is the pattern around the payment. RuseTect now also reads the banking session (with consent), checks it is really the customer, links victims into campaigns, and answers with a pause, not a panic.
A live or video call, screen sharing, a remote access app, a pasted payee, long hesitation: a fourth evidence domain. Alone it only asks the customer; with payment or message evidence it holds the money for an analyst.
An unenrolled device right after a SIM swap gets no OTP and reverifies by video KYC. Typing and mouse rhythm check the person; account takeover chains (reset, new device, new payee, transfer) are caught in order.
"Has anyone said you are under digital arrest and must pay?" chosen from the evidence, in English or Hindi, with a 30 minute cool off. A duress PIN shows the scammer "payment successful" while the money is held and family is alerted.
Alerts link into a campaign when they share a payee, a payee identifier from the messages, or a near identical script, with the reason shown for every link.
A payee blocked by two analysts is published to a signed, hash chained ledger as an HMAC token. Other banks can match it without learning anything else. No blockchain needed.
Analysts act with their own keys, a block needs two different people, replays are rejected, and a ready to review STR draft is built from the evidence pack without sending data to any outside AI service.
A single transfer looks normal. The pattern around it does not.
31 features per payment, each computed only from earlier activity: money in then straight out, sudden fan-out, money flowing back.
Every block lists its top drivers in plain words, such as "minutes since money came in: 0" or "new counterparty", ready for the STR draft.
Offline benchmark against IBM's labelled synthetic rings: fan-in 90%, cycles 88%, gather scatter 87%, fan-out 86% caught. Bipartite rings are the hardest at 52%.
Each payment becomes 31 numbers about the accounts' past behaviour: how fast money moves on, how many new payees, how much flows back. Many are missing for new accounts, and laundering is under 0.2% of payments. Gradient boosted trees fit that shape well: they learn interactions without hand built crosses, handle missing values natively, train in seconds and score in well under a millisecond, and XGBoost gives per feature reasons for each alert.
XGBoost scores 0.172 PR-AUC on raw payment fields and 0.715 with account history features. The top four tree models sit between 0.699 and 0.715.
30 shallow trees approve about 80% of payments in about 0.3 ms while keeping about 99% of laundering for L2. The goal is speed with very few misses, not a final decision.
Two boosters grown differently give a steadier score. In the audit, the live average scored 0.716 PR-AUC on the test period against 0.722 for its XGBoost half alone, so the case for it is robustness, not accuracy.
| Model | Task · features | PR-AUC | Strengths | Limits | Status |
|---|---|---|---|---|---|
| XGBoost | Payments · account history | 0.715 | Best single score; native missing values; TreeSHAP reasons | Needs the engineered history features | live L1 + L2 |
| LightGBM | Payments · account history | 0.699 | Fast, compact; second opinion | Slightly lower alone | live L2 |
| Random Forest | Payments · account history | 0.706 | Robust with little tuning | Large model, slower per payment | offline blend only |
| CatBoost | Payments · account history | 0.700 | Strong defaults, categorical handling | Slower to train here; no gain | not used |
| MLP | Payments · account history | 0.574 | Flexible | Needs scaling; weaker on tabular data | not used |
| Decision Tree | Payments · account history | 0.533 | Fully readable | Unstable, lower ranking quality | not used |
| Logistic Regression | Payments · account history | 0.132 | Simple, calibrated | Cannot learn interactions | not used |
| XGBoost | Payments · raw fields only | 0.172 | Same model without account history: shows where the signal comes from | reference | |
| LightGBM | Account applications (BAF) | 0.190 | Slightly ahead of XGBoost (0.187); fast | Different task: not comparable with payment scores | live L0 |
PR-AUC (average precision) summarises precision across all recall levels. With 0.18% positives, a model that flags nothing is 99.8% accurate, so accuracy is meaningless here. Committed results from ml/bench_tabular.py and ml/bench_baf.py on synthetic data; a fresh comparison of more models (including TCN) is in the report. Details: docs/model-selection.md.
Committed results from this repository's benchmark scripts, on synthetic data later in time than the training data. They do not show performance on real banking traffic.
Same training rows, same threshold procedure, same held out test period. PR-AUC on laundering payments (0.18% of test traffic). Reported results from ml/bench_*.py.
Account history features matter most: XGBoost goes from 0.172 on raw payment fields to 0.715 with them. The GNN is tested with strictly past only graph data; published GNN results on this dataset let the test graph include future edges. Full report →
Open the live console and load earlier payments, so every account has context, as it would in a bank.
Open console60,000 recorded test period payments from the synthetic IBM dataset flow through the live path. Watch clears, blocks, reasons and ring cases, checked against ground truth.
Score your own payment or account application.
POST /api/v2/payment
{ "timestamp": "2022-09-09 10:00",
"from_bank": "070", "from_account": "A1",
"to_bank": "011", "to_account": "B2",
"amount_paid": 9300, "payment_format": "ACH" }
API docsBuilt and benchmarked on 6 million synthetic records. Real deployment would need retraining and revalidation on a bank's own data.