Skip to main content

Compliance Reasoning Templates (Pillar 2 -- Red Flag Engine)

Jurisdiction-specific compliance playbooks with deterministic red flag detection. No LLM involved in rule evaluation -- every triggered rule is traceable to a specific regulatory article and reproducible with the same inputs.

Business Value

Different business types and jurisdictions require different compliance checks. A Belgian PSP onboarding a merchant must verify KBO registration, NBB financial accounts, and inhoudingsplicht status. A Czech bank onboarding a corporate client must check ARES/ICO, the Justice.cz insolvency register, and CNB licensing. Reasoning Templates codify this expert knowledge into reusable, auditable playbooks that:

  • Drive investigation depth -- verification chains tell OSINT agents which registries to query
  • Flag specific risks -- red flag rules fire deterministically against investigation findings
  • Ensure regulatory coverage -- every rule references its regulatory basis (AMLD-VI Art. 30, GwG s. 15, WWFT Art. 8, etc.)
  • Inject EDD tasks -- triggered rules generate mandatory or recommended Enhanced Due Diligence tasks
  • Cap confidence scores -- when a critical red flag fires, the confidence score is capped regardless of other positive signals

This is Pillar 2 of the compliance architecture: deterministic rules that complement Pillar 1's AI-driven confidence scoring.

Architecture

How It Works

The red flag engine operates at two points in the investigation pipeline:

  1. During confidence scoring (compute_confidence_score activity) -- after OSINT agents complete and before the officer review, the engine evaluates all rules in the selected template against the accumulated findings and discrepancies. Triggered rules produce confidence caps and evidence gates that constrain the final confidence score.

  2. During task generation -- EDD tasks from triggered rules are injected alongside AI-generated follow-up tasks, ensuring mandatory compliance requirements are never omitted.

Evaluation Flow

Investigation Complete
|
v
get_reasoning_template_for_case(country, workflow_template_id)
|
v
evaluate_template(template, findings, discrepancies, metadata)
|
+--> For each RedFlagRule:
| evaluate_rule(rule, findings, discrepancies, sources, docs, metadata)
| +--> For each RuleCondition (AND logic):
| | _evaluate_condition(type, value, ...)
| | -> (matched: bool, description: str)
| |
| +--> If ALL conditions match:
| Execute all RuleActions
|
+--> Aggregate results into ReasoningResult:
- confidence_cap: min of all CAP_CONFIDENCE actions
- evidence_gate: min of all GATE_EVIDENCE actions
- edd_tasks: all FORCE_EDD_TASK actions
- additional_findings: all FLAG actions

Determinism Guarantee

The engine is fully deterministic -- no LLM calls, no randomness, no external API calls during evaluation. Given identical inputs (findings, discrepancies, metadata), the engine always produces identical outputs. This is critical for:

  • Regulatory audits -- evaluators can reproduce any past evaluation
  • EU AI Act compliance -- Art. 14 human oversight requires explainable automated decisions
  • Regression testing -- rule changes can be validated against known test cases

Template Structure

ReasoningTemplate

The top-level model that encapsulates all compliance logic for a specific country and vertical.

FieldTypeDescription
idstrUnique template identifier (e.g., be_psp_merchant_reasoning)
namestrHuman-readable name (e.g., "Belgian PSP Merchant Onboarding")
countrystrISO 3166-1 alpha-2 code (BE, FR, CZ, DE, NL, EU)
verticalstrBusiness vertical (e.g., psp_merchant, fiscal_rep, hvg_dealer, banking_kyb, kyc)
versionintTemplate version (default: 1)
workflow_template_idstrLinks to the corresponding WorkflowTemplate
regulatory_frameworklist[str]Applicable regulations (e.g., ["AMLD-VI", "Belgian AML Law"])
verification_chainlist[VerificationStep]Ordered steps the investigation must complete
red_flag_ruleslist[RedFlagRule]Deterministic rules evaluated against findings
confidence_adjustmentslist[ConfidenceAdjustment]Template-specific score adjustments

VerificationStep

Defines a single step in the investigation verification chain.

FieldTypeDescription
orderintExecution order in the chain
namestrStep name (e.g., "KBO Registry Lookup")
descriptionstrWhat this step verifies
sourcestrData source to check (kbo, nbb, ares, justice_cz, etc.)
requiredboolIf true, investigation is incomplete without this step
auto_verifiableboolCan be checked automatically vs. needs officer review

RedFlagRule

A single red flag with conditions and actions.

FieldTypeDescription
idstrRule identifier (e.g., be_psp_ubo_mismatch)
namestrHuman-readable name
descriptionstrExplanation of what the rule detects
severityRuleSeverityCRITICAL, HIGH, MEDIUM, or LOW
conditionslist[RuleCondition]ALL must match (AND logic)
actionslist[RuleAction]ALL are executed when the rule fires
edd_levelEDDLevel | NoneMANDATORY or RECOMMENDED (if set, triggers EDD)
edd_task_templatestrTask description template for EDD
regulatory_basisstrSpecific regulation reference (e.g., "AMLD-VI Art. 30")
enabledboolCan be disabled without removing (default: true)
service_scopelist[str]Service-scoped rules only fire for matching selected services

Condition Types (10)

Condition TypeEvaluatesExample
FINDING_CATEGORYFinding's category matches valuesanctions_hit, pep_match, nominee_director
FINDING_SOURCEFinding's source matches valuekbo, nbb, sanctions_list
SEVERITY_GTEAny finding has severity >= thresholdhigh, critical
RISK_SCORE_GTECase risk score >= threshold75.0
DISCREPANCY_FIELDDiscrepancy exists on specified fieldubo_ownership
SOURCE_MISSINGExpected source absent from findingsnbb, inpi_accounts
DOC_MISSINGRequired document not uploadedkbis_extract, source_of_goods
FIELD_VALUE_MATCHfinding.details[field] matches patternidentity_verified: false
NACE_CODE_MISMATCHNACE codes don't include expected values46.72,47.77
COMPANY_AGE_LTCompany registered less than N months ago6, 12

Action Types (5)

Action TypeEffectExample
FLAGInject a finding with the rule's severityAdds red_flag:be_psp_ubo_mismatch finding
CAP_CONFIDENCECap total confidence at a maximum valueCap at 40 for UBO mismatch
FORCE_EDD_TASKGenerate a mandatory follow-up task"Request ITAA membership certificate"
BOOST_SEVERITYIncrease finding severity to rule's levelEscalate to critical
GATE_EVIDENCEWithout this doc, evidence dimension cappedEvidence capped at 15/25 without insurance

EDD Levels

LevelBehavior
MANDATORYTask must be generated; cannot proceed without completion
RECOMMENDEDTask is suggested; officer can override and proceed

Available Templates

Trust Relay ships with 9 reasoning templates covering 6 jurisdictions:

Template IDCountryVerticalRulesVerification StepsRegulatory Framework
be_psp_merchant_reasoningBEPSP Merchant89AMLD-VI, Belgian AML Law, PSD2
be_fiscal_rep_reasoningBEFiscal Rep47AMLD-VI, Belgian AML Law, ITAA Regulations
be_hvg_dealer_reasoningBEHVG Dealer711AMLR, Belgian AML Law, EU Conflict Minerals Reg. 2017/821
be_kyc_natural_personBEKYC (Natural Person)96AMLD-VI, Belgian AML Law, eIDAS Regulation
fr_psp_merchant_reasoningFRPSP Merchant1010AMLR, CMF Art. L561-1 et seq., PSD2
cz_banking_kyb_reasoningCZBanking KYB1010AMLR, Czech AML Act 253/2008, CNB Decree 67/2018
de_psp_merchant_reasoningDEPSP Merchant109AMLR, GwG, PSD2, BaFin AuA
nl_psp_merchant_reasoningNLPSP Merchant1010AMLR, WWFT, PSD2, DNB Guidance
eu_generic_cdd_reasoningEUGeneric CDD108AMLR 2024/1624, 6AMLD, EU Funds Transfer Reg.

Per-Country Detail

Belgium (BE) -- 4 Templates

Belgium is the home jurisdiction with the deepest template coverage, spanning four distinct verticals.

BE PSP Merchant (8 rules, 9 verification steps)

Verification chain: KBO Registry -> NBB CBSO Financial Health -> PEPPOL Registration -> UBO Register Cross-Reference -> Inhoudingsplicht Check -> Gazette Review -> Sanctions/PEP Screening -> Adverse Media Scan -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
be_psp_young_companyHIGHCompany age < 6 monthsFlag high riskBelgian AML Law Art. 19
be_psp_nominee_directorMEDIUMnominee_director findingFlag medium riskAMLD-VI Art. 13
be_psp_ubo_mismatchCRITICALUBO discrepancy detectedFlag + cap confidence at 40 + mandatory EDDAMLD-VI Art. 30
be_psp_missing_accountsHIGHNBB source missingFlag + recommended EDD for financial dataBelgian AML Law
be_psp_social_tax_debtHIGHsocial_debt findingFlag + cap confidence at 55Belgian AML Law
be_psp_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDD (senior management + source of funds)AMLD-VI Art. 18
be_psp_pep_matchHIGHpep_match findingFlag + mandatory EDD (source of wealth + source of funds)AMLD-VI Art. 20-22
be_psp_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15EU Sanctions Regulations

Confidence adjustments: Full Belgian source coverage (KBO + NBB + PEPPOL + Gazette + UBO Register) boosts source diversity by +25.

BE Fiscal Representative (4 rules, 7 verification steps)

Verification chain: KBO Registry -> ITAA Registration -> NBB CBSO Financial Health -> Professional Liability Insurance -> UBO Register Cross-Reference -> Sanctions/PEP Screening -> Adverse Media Scan

Rule IDSeverityConditionActionRegulatory Basis
be_fiscal_no_itaaCRITICALITAA source missingFlag + cap confidence at 35 + mandatory EDDITAA Regulations
be_fiscal_insurance_expiredHIGHProfessional liability insurance missingFlag + gate evidence at 15/25Belgian Professional Requirements
be_fiscal_high_risk_clientsMEDIUMhigh_risk_jurisdiction_clients findingFlag medium riskAMLD-VI Art. 18
be_fiscal_disciplinaryCRITICALdisciplinary_action findingFlag + cap confidence at 30ITAA Regulations

Confidence adjustments: ITAA verification is gating (confidence capped at 35 without it). Professional liability insurance is gating for the evidence dimension (capped at 15/25 without it).

BE High-Value Goods Dealer (7 rules, 11 verification steps)

Verification chain: KBO Registry -> NBB CBSO -> Gazette Corporate Governance -> PEPPOL Trade Verification -> UBO Register -> eID UBO Verification -> Source-of-Goods Verification -> Inhoudingsplicht Check -> Sanctions/PEP Screening -> Adverse Media Investigation -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
be_hvg_nace_mismatchHIGHNACE codes exclude 46.72/47.77Flag + cap confidence at 30Sector risk assessment
be_hvg_young_companyHIGHCompany age < 12 monthsFlag high riskSector risk assessment
be_hvg_source_of_goods_missingHIGHSource-of-goods doc missingFlag + mandatory EDD (LBMA, supply chain)EU Reg. 2017/821 Art. 4-7
be_hvg_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15EU Sanctions Regulations
be_hvg_pep_matchHIGHpep_match findingFlag + mandatory EDDAMLD-VI Art. 20-22
be_hvg_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDDAMLD-VI Art. 18
be_hvg_adverse_mediaHIGHadverse_media_hit findingFlag + recommended EDD (media assessment)AMLD-VI Art. 18

Confidence adjustments: NACE code verification is gating (confidence capped at 30 for wrong NACE). Source-of-goods documentation is weighted 2x in evidence completeness.

BE KYC Natural Person (9 rules, 6 verification steps)

The only template that routes through the KYC activity fork in the workflow (not the KYB path). Used for natural persons: consumers, HVG customers, and beneficial owners undergoing Enhanced Due Diligence.

Verification chain: Identity Verification (eID/itsme) -> National Register Validation (NRN mod97 / BSN 11-proof) -> IBAN + Verification of Payee -> Sanctions Screening -> PEP Screening -> Adverse Media Check

Rule IDSeverityConditionActionRegulatory Basis
kyc_sanctions_matchCRITICALsanctions_hit findingCap confidence at 15 + mandatory EDDAMLD-VI Art. 18
kyc_identity_failedCRITICALidentity_verified = falseCap confidence at 20 + mandatory EDD (in-person verification)Belgian AML Law Art. 27
kyc_pep_matchHIGHpep_match findingFlag + mandatory EDD (source-of-wealth)AMLD-VI Art. 20-23
kyc_adverse_mediaHIGHadverse_media findingFlag + recommended EDDAMLD-VI Art. 18
kyc_high_volumeHIGHExpected volume > 100kForce EDD (source-of-funds)Belgian AML Law Art. 21
kyc_vop_mismatchHIGHVoP name does not matchForce EDD (account verification)AMLD-VI Art. 13
kyc_non_euMEDIUMNon-EU nationalityFlag medium risk--
kyc_residence_mismatchMEDIUMResidence != nationalityFlag medium risk--
kyc_nrn_invalidMEDIUMNRN/BSN checksum failedFlag + cap confidence at 50--

Confidence adjustments: Full verification suite passed (eID + IBAN + screening clean) boosts evidence by +25. Complete screening coverage (sanctions + PEP + adverse media all clean) boosts source diversity by +20. NRN validation passed boosts consistency by +10. Volume > 50k without source-of-funds caps total confidence at 55.

Note: populate_knowledge_graph and assign_automation_tier are skipped for KYC cases. Natural persons do not produce company graph data.

France (FR) -- 1 Template

FR PSP Merchant (10 rules, 10 verification steps)

Verification chain: SIREN/SIRET Verification (INSEE SIRENE) -> INPI/RNE Registry Lookup -> BODACC Publication Monitoring -> RBE Beneficial Ownership (Greffe) -> Kbis Extract Verification -> VIES VAT Validation -> Financial Accounts Review (INPI) -> Sanctions/PEP Screening -> Adverse Media Scan -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
fr_psp_young_companyHIGHCompany age < 6 monthsFlag high riskCMF Art. L561-10-2
fr_psp_siren_inactiveCRITICALsiren_inactive findingFlag + cap confidence at 15CMF Art. L561-5
fr_psp_ubo_mismatchCRITICALUBO discrepancy (RBE vs. declared)Flag + cap confidence at 40 + mandatory EDD (RBE extract)CMF Art. L561-46
fr_psp_bodacc_judicialCRITICALjudicial_proceedings findingFlag + cap confidence at 25 + mandatory EDD (Tribunal judgment)Code de commerce Art. L631-1
fr_psp_kbis_missingHIGHKbis extract not providedFlag + recommended EDD (Kbis < 3 months)CMF Art. L561-5
fr_psp_nominee_directorMEDIUMnominee_director findingFlag medium riskCMF Art. L561-10-2
fr_psp_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDD (incl. TRACFIN declaration)CMF Art. L561-10-2
fr_psp_pep_matchHIGHpep_match findingFlag + mandatory EDD (CMF Art. L561-10)CMF Art. L561-10
fr_psp_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15CMF Art. L562-1 (gel des avoirs)
fr_psp_missing_accountsHIGHINPI accounts source missingFlag + recommended EDD (liasse fiscale)Code de commerce Art. L232-21

Confidence adjustments: Full French source coverage (SIREN + INPI + BODACC + RBE + VIES) boosts source diversity by +25. Verified Kbis extract (< 3 months, matching INPI data) boosts evidence by +15.

Czech Republic (CZ) -- 1 Template

CZ Banking KYB (10 rules, 10 verification steps)

Verification chain: ARES/ICO Registry Lookup -> Justice.cz Commercial Register -> ISIR Insolvency Register -> Beneficial Ownership Register (Evidence skutecnych majitelu) -> VIES VAT Validation -> Financial Statements Review (Sbirka listin) -> CNB License Verification -> Sanctions/PEP Screening -> Adverse Media Scan -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
cz_bank_young_companyHIGHCompany age < 12 monthsFlag high riskCzech AML Act s. 9(2)(b)
cz_bank_isir_insolvencyCRITICALinsolvency_proceedings findingFlag + cap confidence at 20 + mandatory EDDCzech AML Act s. 9(2)
cz_bank_ubo_mismatchCRITICALUBO discrepancy (register vs. declared)Flag + cap confidence at 40 + mandatory EDDCzech AML Act s. 29
cz_bank_justice_mismatchHIGHregistry_data_mismatch findingFlag + recommended EDD (Vypis z obchodniho rejstriku)Czech AML Act s. 8
cz_bank_missing_accountsHIGHJustice.cz accounts source missingFlag + recommended EDD (ucelni zaverka)Czech AML Act s. 9(2)
cz_bank_nominee_directorMEDIUMnominee_director findingFlag medium riskCzech AML Act s. 9(2)(d)
cz_bank_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDDCzech AML Act s. 9(2)(a)
cz_bank_pep_matchHIGHpep_match findingFlag + mandatory EDD (Czech AML Act s. 10)Czech AML Act s. 10
cz_bank_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15Czech AML Act s. 18
cz_bank_high_capital_turnoverMEDIUMcapital_turnover_discrepancy findingFlag medium risk (shell company indicator)CNB Decree 67/2018

Confidence adjustments: Full Czech source coverage (ARES + Justice.cz + ISIR + UBO register) boosts source diversity by +25. All Czech registries corroborating each other boosts consistency by +15.

Note: The CZ template uses a 12-month young company threshold (vs. 6 months for PSP templates) because banking KYB requires heightened scrutiny for recently incorporated entities per CNB Decree 67/2018.

Germany (DE) -- 1 Template

DE PSP Merchant (10 rules, 9 verification steps)

Verification chain: Handelsregister Lookup -> Unternehmensregister/Bundesanzeiger Financial Data -> Transparenzregister UBO Verification -> VIES VAT Validation -> Gewerbeanmeldung Verification -> GLEIF/LEI Verification -> Sanctions/PEP Screening -> Adverse Media Scan -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
de_psp_young_companyHIGHCompany age < 6 monthsFlag high riskGwG s. 15(3) Nr. 1
de_psp_hr_deletedCRITICALhr_deleted_liquidation findingFlag + cap confidence at 15GwG s. 10(1) Nr. 1
de_psp_ubo_mismatchCRITICALUBO discrepancy (Transparenzregister)Flag + cap confidence at 40 + mandatory EDDGwG s. 20
de_psp_missing_accountsHIGHBundesanzeiger source missingFlag + recommended EDD (Jahresabschluss)HGB s. 325
de_psp_bafin_thresholdMEDIUMbafin_threshold_exceeded findingFlag medium risk (enhanced monitoring)GwG s. 10(3) Nr. 2
de_psp_nominee_directorMEDIUMnominee_director findingFlag medium riskGwG s. 15(3) Nr. 3(b)
de_psp_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDD (GwG s. 15(2))GwG s. 15(2)
de_psp_pep_matchHIGHpep_match findingFlag + mandatory EDD (GwG s. 15(4))GwG s. 15(4)
de_psp_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15AWG s. 4 (Aussenwirtschaftsgesetz)
de_psp_gwg_suspiciousHIGHgwg_suspicious_indicators findingFlag + recommended EDD (Verdachtsmeldung assessment)GwG s. 43 (Meldepflicht)

Confidence adjustments: Full German source coverage (Handelsregister + Bundesanzeiger + Transparenzregister + VIES) boosts source diversity by +25. All German registries corroborating each other boosts consistency by +15.

Netherlands (NL) -- 1 Template

NL PSP Merchant (10 rules, 10 verification steps)

Verification chain: KvK Extract Verification -> KvK UBO Register -> Annual Accounts (KvK Jaarrekeningen) -> VIES VAT Validation -> GLEIF/LEI Verification -> Staatscourant Monitoring -> Faillissementsverslag Check (CIR) -> Sanctions/PEP Screening -> Adverse Media Scan -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
nl_psp_young_companyHIGHCompany age < 6 monthsFlag high riskWWFT Art. 8(6)(a)
nl_psp_kvk_inactiveCRITICALkvk_inactive findingFlag + cap confidence at 15WWFT Art. 3(1)
nl_psp_ubo_mismatchCRITICALUBO discrepancy (KvK UBO)Flag + cap confidence at 40 + mandatory EDDWWFT Art. 3(1)(b) + Implementatiewet UBO-register
nl_psp_bankruptcyCRITICALbankruptcy_proceedings findingFlag + cap confidence at 20 + mandatory EDD (CIR ruling)WWFT Art. 8(6)
nl_psp_missing_accountsHIGHKvK jaarrekeningen source missingFlag + recommended EDD (jaarrekening)BW2 Titel 9 (Dutch Civil Code)
nl_psp_wwft_indicatorsHIGHwwft_unusual_indicators findingFlag + recommended EDD (FIU-Nederland assessment)WWFT Art. 16 (meldingsplicht)
nl_psp_nominee_directorMEDIUMnominee_director findingFlag medium riskWWFT Art. 8(6)(c)
nl_psp_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDD (WWFT Art. 8(5))WWFT Art. 8(5)
nl_psp_pep_matchHIGHpep_match findingFlag + mandatory EDD (WWFT Art. 8(5))WWFT Art. 8(5)(a)-(c)
nl_psp_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15Sanctiewet 1977

Confidence adjustments: Full Dutch source coverage (KvK + KvK UBO + KvK Jaarrekeningen + VIES) boosts source diversity by +25. All Dutch registries corroborating each other (KvK active + UBO matched + Jaarrekeningen filed + CIR clean) boosts consistency by +15.

EU Generic Fallback (10 rules, 8 verification steps)

The fallback template for any EU/EEA country without a country-specific template. Provides baseline CDD coverage per AMLR 2024/1624.

Verification chain: National Commercial Register -> VIES VAT Validation -> GLEIF/LEI Verification -> UBO Verification -> Sanctions/PEP Screening -> PEP Database Check -> Adverse Media Scan -> Document Cross-Reference

Rule IDSeverityConditionActionRegulatory Basis
eu_generic_young_companyHIGHCompany age < 6 monthsFlag high riskAMLR Art. 28(4)(a)
eu_generic_ubo_mismatchCRITICALUBO discrepancyFlag + cap confidence at 40 + mandatory EDDAMLR Art. 45
eu_generic_vies_invalidMEDIUMVIES source missingFlag medium riskAMLR Art. 28
eu_generic_gleif_no_leiLOWGLEIF source missingFlag low risk (reduced transparency)AMLR Art. 28
eu_generic_nominee_directorMEDIUMnominee_director findingFlag medium riskAMLR Art. 28(4)(a)
eu_generic_fatf_uboHIGHhigh_risk_country_ubo findingFlag + mandatory EDD (AMLR Art. 32)AMLR Art. 32
eu_generic_pep_matchHIGHpep_match findingFlag + mandatory EDD (AMLR Art. 35)AMLR Art. 35-37
eu_generic_sanctions_hitCRITICALsanctions_hit findingFlag + cap confidence at 15EU Council Regulations
eu_generic_adverse_mediaHIGHadverse_media_hit findingFlag + recommended EDDAMLR Art. 28(4)(c)
eu_generic_missing_registryHIGHNational registry source missingFlag + mandatory EDD (certified extract)AMLR Art. 28(1)

Confidence adjustments: VIES validated + GLEIF/LEI found + UBO register matched boosts source diversity by +20. National registry unavailable caps total confidence at 60 (cannot go higher without the primary registry).

Fallback Logic

get_reasoning_template_for_case(country, workflow_template_id) resolves the template in three steps:

1. Exact match: country + workflow_template_id
-> Found? Return template.

2. EU generic match: EU country + same workflow_template_id
-> Found? Return EU template with that workflow.

3. Last resort: EU generic CDD baseline
-> Always returns eu_generic_cdd_reasoning.

This ensures every case gets at least the EU CDD baseline, even for countries without a dedicated template (e.g., a Spanish or Italian entity would receive the EU generic rules).

A DB-first variant (get_reasoning_template_for_case_from_db) checks the workflow_templates table first for tenant-specific or system templates stored in PostgreSQL, falling back to the in-memory registry on DB failure. This guard-and-swallow pattern ensures a database outage never blocks the compliance engine.

Source Alias Normalization

The engine normalizes source names to handle variations in how OSINT agents report their data source:

CanonicalAliases
nbbnbb cbso, nbb annual, nationale bank
kbokbo/bce, kbo bce, kruispuntbank, crossroads
gazettebelgian gazette, staatsblad, moniteur belge
inhoudingsplichtwithholding obligation

This prevents SOURCE_MISSING rules from firing incorrectly when an agent reports the source as "KBO/BCE Public Search" instead of "kbo".

Adding a New Template

To add a new country template (e.g., Spain):

Step 1: Research regulatory requirements

Identify the country's AML law, commercial register, UBO register, insolvency register, and FIU reporting requirements. Map each to specific regulatory articles.

Step 2: Define the verification chain

List the data sources the investigation must check, in order. Mark each as required (investigation incomplete without it) and auto_verifiable (can be checked via API vs. needs manual review).

Step 3: Define red flag rules

For each risk scenario, create a RedFlagRule with:

  • Conditions using the 10 available ConditionType values
  • Actions using the 5 available ActionType values
  • A specific regulatory_basis citation
  • An edd_level if the rule should generate follow-up tasks

Step 4: Add to the registry

Add the template constant to backend/app/services/reasoning_template_registry.py:

ES_PSP_TEMPLATE = ReasoningTemplate(
id="es_psp_merchant_reasoning",
name="Spanish PSP Merchant Onboarding",
country="ES",
vertical="psp_merchant",
workflow_template_id="psp_merchant_onboarding",
regulatory_framework=["AMLR", "Ley 10/2010 de prevenci\u00f3n del blanqueo de capitales"],
verification_chain=[...],
red_flag_rules=[...],
confidence_adjustments=[...],
)

Register it in REASONING_TEMPLATE_REGISTRY:

REASONING_TEMPLATE_REGISTRY: dict[str, ReasoningTemplate] = {
# ... existing templates ...
# Spain
ES_PSP_TEMPLATE.id: ES_PSP_TEMPLATE,
}

Step 5: Write tests

Add test cases to verify:

  • Template is returned by get_reasoning_template_for_case("ES", "psp_merchant_onboarding")
  • Each rule fires when its conditions are met
  • Confidence caps are applied correctly
  • EDD tasks are generated for mandatory rules

Step 6: Update documentation

Update this page with the new country section and add a row to the Available Templates table.

Relationship to Other Pillars

Pillar 1: Confidence Scoring (AI-driven)

Pillar 1 computes a 4-dimension confidence score (evidence, source diversity, consistency, calibration). Pillar 2 constrains that score: when a critical red flag fires, it caps the confidence regardless of how positive the other signals are. A UBO mismatch (Pillar 2, cap at 40) overrides a high source diversity score (Pillar 1) -- this ensures the system never suppresses risk signals.

Pillar 3: Cross-Case Patterns

Pillar 3 (compliance memory) learns patterns across cases. Pillar 2 rules are static per template; Pillar 3 extends them with learned patterns like "companies with this NACE code in this region have a 40% rejection rate." Future: Pillar 3 findings could feed into Pillar 2 as dynamic rule generation.

EBA Risk Matrix (ADR-0020)

The EBA risk matrix scores risk across 5 dimensions (customer, geographic, product, channel, delivery). Reasoning template rules produce findings that feed into EBA dimension scoring -- for example, a high_risk_country_ubo finding increases the Geographic risk dimension.

Regulatory Segments (ADR-0031)

Regulatory segment profiles compile country+vertical YAML definitions into workflow configurations. Reasoning templates are the runtime enforcement mechanism for these segment definitions -- the YAML compiler generates the verification chain and red flag rules that become a reasoning template.

Key Components

FileRole
app/models/reasoning_template.pyRe-export shim (ADR-0037) for the Pydantic models that now live in trustrelay_models.reasoning_template: ReasoningTemplate, RedFlagRule, RuleCondition, RuleAction, VerificationStep, ConfidenceAdjustment, ReasoningResult, plus ConditionType/ActionType/RuleSeverity/EDDLevel enums
app/services/reasoning_template_registry.pyIn-memory registry with 9 seed templates, lookup functions (get_reasoning_template_for_case, DB-first variant)
app/services/red_flag_engine.pyDeterministic rule evaluation: evaluate_rule(), evaluate_template(), source alias normalization
app/services/rule_evaluation_service.pyPostgreSQL persistence of evaluation results for audit trail
frontend/src/components/dashboard/RulesAppliedCard.tsxVisual display of triggered rules in the Compliance tab

API Endpoints

MethodPathDescription
GET/api/reasoning-templatesList available templates (optionally filtered by country)
GET/api/reasoning-templates/{template_id}Get template details including all rules and verification steps
GET/api/cases/{workflow_id}/rule-evaluationsGet rule evaluation results for a case/workflow

The router (app/api/reasoning.py) is mounted under /api and requires an authenticated user (Depends(get_current_user)).

Configuration

  • Alembic migration: 007_reasoning_templates (reasoning template storage)
  • Rule evaluations stored in rule_evaluations table for audit trail
  • DB-first lookup queries workflow_templates table, falls back to in-memory registry