AI-powered SAR narrative generator for AML compliance teams
Project description
sar-narrative-gen
AI-powered SAR narrative generator for AML compliance teams — turns flagged transaction data into FinCEN-ready Suspicious Activity Report draft narratives using Claude.
Why this exists
Writing SAR narratives is one of the most time-consuming tasks in a BSA/AML program. A compliance analyst reviewing 800+ alerts a week spends a significant portion of their time translating transaction data into structured prose — describing the who, what, when, where, and why of each suspicious pattern, in language that meets FinCEN guidance.
This toolkit automates the first draft. Feed it flagged transactions and subject information; get back a structured SAR narrative that follows FinCEN best practices. Analysts review and refine rather than write from scratch.
How it works
The generator takes flagged transaction data, subject information, and a detected typology (structuring, layering, smurfing, rapid fund movement, dormant account) and constructs a structured prompt grounded in FinCEN SAR narrative guidance. It calls the Anthropic Claude API and returns a formatted narrative draft with metadata — transaction count, total flagged amount, date range, and generation timestamp.
The system prompt encodes FinCEN narrative requirements: objective language, no conclusory statements, specific transaction references, typology identification, and the standard who/what/when/where/why structure.
Quick start
pip install sar-narrative-gen
Set your Anthropic API key:
export ANTHROPIC_API_KEY=your_key_here
Generate a SAR narrative:
from sar import generate_sar_narrative
transactions = [
{"date": "2024-03-01", "amount": 9400.00, "type": "cash_deposit",
"from_account": "CASH", "to_account": "CHK-004821"},
{"date": "2024-03-04", "amount": 9200.00, "type": "cash_deposit",
"from_account": "CASH", "to_account": "CHK-004821"},
{"date": "2024-03-07", "amount": 8900.00, "type": "cash_deposit",
"from_account": "CASH", "to_account": "CHK-004821"},
]
subject = {
"name": "Meridian Auto Parts LLC",
"account_number": "CHK-004821",
"customer_since": "2021-06-15",
"business_type": "Auto parts retailer",
}
result = generate_sar_narrative(
transactions=transactions,
subject_info=subject,
typology="structuring",
filing_institution="First National Community Bank",
additional_context="Subject's reported annual revenue is $180,000.",
)
print(result["narrative"])
print(f"Total flagged: ${result['total_amount']:,.2f}")
print(f"Transactions: {result['transaction_count']}")
Supported typologies
| Typology | Description | Reference |
|---|---|---|
structuring |
Breaking up transactions below CTR threshold | 31 U.S.C. 5324 |
layering |
Moving funds through multiple accounts to obscure origin | FATF Typologies 2006 |
smurfing |
Multiple individuals conducting sub-threshold transactions | FinCEN FIN-2014-A005 |
rapid_movement |
Funds moving through accounts within 24–48 hours | FATF Guidance 2012 |
dormant_account |
Sudden high-volume activity in previously inactive account | FinCEN FIN-2022-A001 |
Batch processing
Generate narratives for multiple cases at once:
from sar import batch_generate, get_all_demo_cases
cases = get_all_demo_cases() # includes structuring, layering, dormant account
results = batch_generate(cases)
for r in results:
print(f"\n--- {r['case_id']} ---")
print(r["narrative"])
Demo cases
The package ships with three synthetic SAR cases for testing and demos:
from sar.synthetic import (
generate_structuring_case,
generate_layering_case,
generate_dormant_account_case,
)
case = generate_structuring_case()
print(case["transactions"])
All synthetic data — no real individuals, accounts, or institutions.
Works great with aml-analytics
sar-narrative-gen is designed to work alongside aml-analytics. Detect suspicious patterns with aml-analytics, then feed the flagged output directly into this generator:
from aml.graph import build_network, detect_structuring
from aml.synthetic import generate_transactions
from sar import generate_sar_narrative
# Detect with aml-analytics
txns = generate_transactions(n=1000)
G = build_network(txns)
flagged = detect_structuring(G, threshold=9000)
# Draft the SAR
result = generate_sar_narrative(
transactions=flagged,
subject_info={"name": "Subject LLC", "account_number": "CHK-001"},
typology="structuring",
)
print(result["narrative"])
Disclaimer
This toolkit is for educational and research purposes only. Generated narratives are AI-drafted first drafts and must be reviewed, verified, and approved by a qualified BSA/AML compliance officer before filing. It does not constitute legal or compliance advice. All demo data is entirely synthetic.
Citation
@software{sar_narrative_gen,
author = {Bhavesh Awalkar},
title = {sar-narrative-gen: AI-powered SAR narrative generator for AML compliance},
year = {2024},
url = {https://github.com/Bhavesh0205/sar-narrative-gen},
license = {MIT}
}
License
MIT — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sar_narrative_gen-0.1.0.tar.gz.
File metadata
- Download URL: sar_narrative_gen-0.1.0.tar.gz
- Upload date:
- Size: 12.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b483719796fa34abb7c78767e1f1d46542fbf8b62d82dea6537ee495a10d0a4
|
|
| MD5 |
d6b2c6948f377faba06b51448e9a450a
|
|
| BLAKE2b-256 |
6439873a5240b823f4b9ae1a68b783b0721738361c273f67c1d0c7e53a734e21
|
File details
Details for the file sar_narrative_gen-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sar_narrative_gen-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5821b0804c97c19d366b70c634d36c62d43fa3c45982e3e158876c45e7807512
|
|
| MD5 |
f590d619f3a9af0aa88db3fb63f606a2
|
|
| BLAKE2b-256 |
d150ab1715cbed4ab270093d9c31e8e0f949be3d369ab1d21f7cbbae80ce9de6
|