back to projects
2026 Fintech

SAR-AI — Multi-Agent AML Compliance

Five-agent Suspicious Activity Report (SAR) narrative generator with a per-sentence evidence panel. A deterministic Fact Checker re-reads every generated sentence, scores each claim against the database, and marks the ones a human must review.

SAR-AI — Multi-Agent AML Compliance cover image

// problem

AML SARs are written by analysts under deadline pressure. The result is inconsistency, speculation, and — the part that matters later — no audit trail back to the underlying evidence. When a filing is challenged, the analyst has to reconstruct the reasoning by hand.

// approach

Five agents in sequence over a six-table schema: a Data Analyst that runs the aggregate SQL and flags five suspicious patterns, a Compliance Specialist that classifies the typology against seven FinCEN activity codes, a Narrative Writer, a Fact Checker, and an Editor. The Fact Checker is the important one — it is not a model at all.

// results

  • Click any sentence to open an evidence panel: the SQL, the query results, and a per-claim confidence bar
  • Five regex claim types extracted from every generated sentence — numbers, INR amounts, dates, account references, FinCEN codes
  • Claims scored against database aggregates with a 1% tolerance; unresolved claims are capped and flagged for review
  • Six hand-written transaction-graph detectors: collection, high-risk jurisdiction, layering, structuring, round-trip and rapid activity
  • Six curated FinCEN / FATF / PMLA reference documents injected into the generation prompt

// screens

SAR-AI — Multi-Agent AML Compliance — screen 2
SAR-AI — Multi-Agent AML Compliance — screen 3

// in depth

Why per-sentence provenance

A regulator does not ask whether the document is trustworthy. They ask about the assertion. If a filing says ₹9,889 was deposited on 30 January, the question is which deposit, not whether the system is generally reliable. So the unit of audit in this system is the sentence.

Each sentence in the narrative is clickable, and the panel behind it carries the SQL that was run, the rows it returned, a confidence bar, and the verdict on each individual claim the sentence makes.

The five agents

#AgentUses a model?Job
1Data AnalystNoPull the alert and customer, run the aggregate SQL, flag five suspicious patterns
2Compliance SpecialistOllama, rule-based fallbackClassify the typology and assign the FinCEN activity code
3Narrative WriterOllama, template fallbackDraft the narrative, then apply the constitutional checks
4Fact CheckerNoExtract the claims, verify each one, annotate what needs review
5EditorOllama, rule-based fallbackGrammar and style only — no new information

The orchestration is a plain async sequence with a progress callback in fixed bands (0–20 / 20–40 / 40–70 / 70–90 / 90–100 %), and the front end polls the task endpoint once a second to draw the progress bar.

Every model call has a rule-based fallback, so the pipeline degrades in quality rather than failing outright.

The Fact Checker is the point

The Writer is allowed to generate freely — it sees only a small sample of transactions and only the last four digits of any account number. What it is not allowed to do is assert something unsupported.

So after generation, a second pass re-reads the text and pulls out five kinds of claim with regular expressions: numbers, currency amounts (with Indian lakh/crore parsing), dates, account references, and FinCEN activity codes. Each is then checked against the database:

  • Numbers against the transaction count, the distinct source count and the sentence count, within 1% relative tolerance.
  • Currency against the aggregate total.
  • Dates against the transaction date range — exact is 1.0, inside a 30-day buffer is 0.85, outside it is 0.3.

A sentence’s confidence is the minimum across its claims, and a claim that cannot be matched at all returns 0.5 — which means any sentence containing an unmatched number or an account reference is flagged rather than trusted.

Below 0.70 the sentence is marked [REVIEW REQUIRED: Confidence NN%]; between 0.70 and 0.95 it gets a [*]. Those markers persist into the final narrative and into the exported PDF, so the analyst sees exactly which sentences need a human.

The constitutional principles

Five principles govern what the narrative may assert, each with a severity:

PrincipleEnforcement
Only state facts supported by transaction dataChecked downstream by the Fact Checker
Do not speculate about customer intentBanned phrases: appears to be, seems like, probably, might be, clearly trying to
Use formal regulatory languageBanned words: shady, sketchy, weird, fishy, bad
Include specific dates, amounts, account numbersChecked downstream by the Fact Checker
Cite FinCEN activity codesRequired by the prompt

The two rules that can be checked mechanically are checked by the Fact Checker rather than the Writer, which keeps the Writer from having to police its own output. The writer’s own enforcement is a filter that strips the banned phrases and formalises contractions — and the Editor’s instruction is explicit that it must not add information, change amounts or alter dates.

The transaction graph, without a graph library

The graph is built from plain dicts rather than a graph package, and the analysis is six hand-written detectors:

DetectorRule
Collection patternMore than 10 distinct inbound sources to the subject account
High-risk jurisdictionAny node in a flagged offshore jurisdiction
LayeringSame-day or next-day outbound ≥50% of that day’s inbound, over ≥3 instances
StructuringAmount inside the 85–99% band below the CTR threshold, across ≥3 transactions
Round-tripAccounts that both sent to and received from the subject
Rapid activity5 or more transactions inside 24 hours

Node labels carry only the last four digits of an account number, and the React Flow view lays the graph out on a fixed five-column grid — edges coloured and weighted by amount, the subject account in blue and anything high-risk in red.

Regulatory context

Six curated reference documents — FinCEN guidance on structuring, layering, collection and rapid movement, FATF Recommendation 20, and India’s PMLA 2002 — are injected into the generation prompt, scoped to the typology the Compliance Specialist assigned. Seven FinCEN typologies are supported, each with its activity code.

Schema

Six tables: customers, alerts, transactions, sars, audit_logs and knowledge_docs. The audit table is the one that matters — it is keyed on (sar_id, sentence_index, entry_type), and three rows are written per sentence: the sql_query, the fact_verification and the llm_generation record.

The seed database carries ten customers, ten alerts and 240 transactions worth about ₹18.3 Cr, across collection, structuring, layering and rapid-movement scenarios.

Scope

The pipeline, the evidence panel, the graph and the detectors are implemented and runnable. The audit rows are written per sentence against the aggregate query the Data Analyst ran — they are a genuine evidence trail, but they are not a row-level link from a sentence to specific transaction IDs, and the design docs treat that as the next step rather than a shipped feature.

// stack

FastAPIPython 3.11SQLAlchemy 2Ollama (Llama 3.1 8B)React 18TypeScriptReact Flow 11ReportLab