The ComplianceEngine class provides offline compliance monitoring with built-in and custom rules for banking and financial services. It evaluates agent interactions against regulatory requirements like PII detection, fair lending, and BSA/AML compliance.

Constructor

ComplianceEngine(config)

Creates a new ComplianceEngine instance with the specified configuration.
config
ComplianceEngineConfig
required
Configuration object for the compliance engine.
Example:
import { ComplianceEngine } from '@agent-governance/node';

const complianceEngine = new ComplianceEngine({
  organizationId: 'first-national-bank',
  logger: myLogger,
  customRules: [
    {
      id: 'bank-specific-rule',
      name: 'Banking Hours Compliance',
      description: 'Ensures banking hours are mentioned correctly',
      category: 'consumer_protection',
      severity: 'warning',
      isActive: true,
      ruleFunction: (context) => {
        // Custom rule implementation
        return {
          isCompliant: true,
          violations: [],
          riskScore: 0,
          requiresReview: false
        };
      }
    }
  ]
});

Core Methods

evaluateInteraction(context)

Evaluates an agent interaction against all active compliance rules.
context
InteractionContext
required
The interaction context to evaluate for compliance violations.
Returns: ComplianceResult Example:
const result = complianceEngine.evaluateInteraction({
  agentId: 'banking-assistant',
  agentCategory: 'tool_calling',
  agentSpecialty: 'personal_banking',
  userMessage: 'What is my account balance?',
  agentResponse: 'Your account balance is $2,547.83. Your SSN is 123-45-6789.',
  sessionId: 'session-123',
  timestamp: Date.now(),
  userId: 'customer-456'
});

console.log('Compliance Result:', {
  isCompliant: result.isCompliant,
  violations: result.violations.length,
  riskScore: result.riskScore,
  requiresReview: result.requiresReview
});

Rule Management

addRule(rule)

Adds a new compliance rule to the engine or updates an existing rule.
rule
ComplianceRule
required
The compliance rule to add or update.
Returns: void Example:
// Add a custom fair lending rule
complianceEngine.addRule({
  id: 'discriminatory-language-check',
  name: 'Discriminatory Language Detection',
  description: 'Detects potentially discriminatory language in lending decisions',
  category: 'fair_lending',
  severity: 'violation',
  isActive: true,
  ruleFunction: (context) => {
    const violations = [];
    const text = (context.agentResponse || '').toLowerCase();

    const discriminatoryPhrases = [
      'people like you',
      'your kind',
      'typical for your background',
      'not suitable for your demographic'
    ];

    discriminatoryPhrases.forEach(phrase => {
      if (text.includes(phrase)) {
        violations.push({
          rule: 'discriminatory-language-check',
          severity: 'violation',
          description: `Potentially discriminatory phrase detected: "${phrase}"`,
          context: { detectedPhrase: phrase, fullText: text },
          recommendation: 'Remove discriminatory language and provide objective reasoning'
        });
      }
    });

    return {
      isCompliant: violations.length === 0,
      violations,
      riskScore: violations.length * 75, // High risk for discriminatory language
      requiresReview: violations.length > 0
    };
  }
});

removeRule(ruleId)

Removes a compliance rule from the engine.
ruleId
string
required
The ID of the rule to remove.
Returns: boolean - True if the rule was found and removed, false otherwise. Example:
const removed = complianceEngine.removeRule('old-custom-rule');
if (removed) {
  console.log('Rule removed successfully');
} else {
  console.log('Rule not found');
}

setRuleActive(ruleId, isActive)

Activates or deactivates a compliance rule without removing it.
ruleId
string
required
The ID of the rule to activate/deactivate.
isActive
boolean
required
Whether the rule should be active.
Returns: boolean - True if the rule was found and updated, false otherwise. Example:
// Temporarily disable a rule for testing
complianceEngine.setRuleActive('pii-detection', false);

// Re-enable the rule
complianceEngine.setRuleActive('pii-detection', true);

getActiveRules()

Returns all currently active compliance rules. Returns: ComplianceRule[] Example:
const activeRules = complianceEngine.getActiveRules();
console.log(`${activeRules.length} active compliance rules:`);
activeRules.forEach(rule => {
  console.log(`- ${rule.name} (${rule.category})`);
});

getAllRules()

Returns all compliance rules (both active and inactive). Returns: ComplianceRule[] Example:
const allRules = complianceEngine.getAllRules();
const activeCount = allRules.filter(rule => rule.isActive).length;
console.log(`${activeCount}/${allRules.length} rules are active`);

getRule(ruleId)

Retrieves a specific compliance rule by ID.
ruleId
string
required
The ID of the rule to retrieve.
Returns: ComplianceRule | undefined Example:
const rule = complianceEngine.getRule('pii-detection');
if (rule) {
  console.log(`Rule: ${rule.name}`);
  console.log(`Status: ${rule.isActive ? 'Active' : 'Inactive'}`);
  console.log(`Severity: ${rule.severity}`);
}

Built-in Compliance Rules

The ComplianceEngine comes with several built-in rules for common banking compliance requirements:

PII Detection Rules

Fair Lending Rules

BSA/AML Rules

Additional BSA/AML rules can be added through custom rule implementation.

Custom Rule Examples

Advanced PII Detection

complianceEngine.addRule({
  id: 'advanced-pii-detection',
  name: 'Advanced PII Detection',
  description: 'Detects credit card numbers, bank account numbers, and other sensitive data',
  category: 'privacy',
  severity: 'violation',
  isActive: true,
  ruleFunction: (context) => {
    const violations = [];
    const text = `${context.userMessage || ''} ${context.agentResponse || ''}`;

    // Credit card number pattern (simplified)
    const ccPattern = /\b(?:\d{4}[\s-]?){3}\d{4}\b/g;
    let match;

    while ((match = ccPattern.exec(text)) !== null) {
      violations.push({
        rule: 'advanced-pii-detection',
        severity: 'violation',
        description: 'Potential credit card number detected',
        context: { detected: match[0].replace(/\d(?=\d{4})/g, '*') },
        recommendation: 'Remove or mask credit card information'
      });
    }

    // Bank account number pattern (simplified)
    const accountPattern = /\b\d{8,17}\b/g;
    while ((match = accountPattern.exec(text)) !== null) {
      if (match[0].length >= 10) { // Likely account number
        violations.push({
          rule: 'advanced-pii-detection',
          severity: 'violation',
          description: 'Potential bank account number detected',
          context: { detected: match[0].substring(0, 4) + '***' },
          recommendation: 'Remove or mask account information'
        });
      }
    }

    return {
      isCompliant: violations.length === 0,
      violations,
      riskScore: violations.length * 40,
      requiresReview: violations.length > 0
    };
  }
});

BSA/AML Suspicious Activity Detection

complianceEngine.addRule({
  id: 'bsa-aml-suspicious-activity',
  name: 'BSA/AML Suspicious Activity Detection',
  description: 'Detects keywords and patterns associated with money laundering',
  category: 'bsa_aml',
  severity: 'warning',
  isActive: true,
  ruleFunction: (context) => {
    const violations = [];
    const text = `${context.userMessage || ''} ${context.agentResponse || ''}`.toLowerCase();

    const suspiciousKeywords = [
      'large cash deposit',
      'avoid reporting',
      'split transaction',
      'just under 10000',
      'cash business',
      'money transfer',
      'hawala',
      'informal transfer'
    ];

    const structuringPatterns = [
      /\$9[5-9]\d{2}/g, // Amounts just under $10,000
      /multiple.*deposit.*same.*day/gi,
      /cash.*structur/gi,
      /avoid.*report/gi
    ];

    // Check for suspicious keywords
    suspiciousKeywords.forEach(keyword => {
      if (text.includes(keyword)) {
        violations.push({
          rule: 'bsa-aml-suspicious-activity',
          severity: 'warning',
          description: `Suspicious activity keyword detected: "${keyword}"`,
          context: { keyword, category: 'suspicious_keyword' },
          recommendation: 'Review transaction for potential SAR filing'
        });
      }
    });

    // Check for structuring patterns
    structuringPatterns.forEach((pattern, index) => {
      let match;
      while ((match = pattern.exec(text)) !== null) {
        violations.push({
          rule: 'bsa-aml-suspicious-activity',
          severity: 'warning',
          description: 'Potential structuring pattern detected',
          context: {
            pattern: match[0],
            category: 'structuring_pattern',
            patternType: `pattern_${index + 1}`
          },
          recommendation: 'Investigate for potential structuring activity'
        });
      }
    });

    return {
      isCompliant: violations.filter(v => v.severity === 'violation').length === 0,
      violations,
      riskScore: violations.length * 25,
      requiresReview: violations.length > 2 || violations.some(v => v.context.category === 'structuring_pattern')
    };
  }
});

Consumer Protection Rule

complianceEngine.addRule({
  id: 'consumer-protection-disclosures',
  name: 'Consumer Protection Disclosures',
  description: 'Ensures required disclosures are provided for financial products',
  category: 'consumer_protection',
  severity: 'warning',
  isActive: true,
  ruleFunction: (context) => {
    const violations = [];
    const agentResponse = (context.agentResponse || '').toLowerCase();

    // Check for product sales without proper disclosures
    const productKeywords = [
      'loan', 'credit card', 'mortgage', 'investment', 'insurance',
      'account opening', 'deposit account', 'certificate of deposit'
    ];

    const requiredDisclosures = [
      'terms and conditions',
      'annual percentage rate',
      'fees may apply',
      'fdic insured',
      'disclosure',
      'agreement'
    ];

    const hasProductMention = productKeywords.some(keyword =>
      agentResponse.includes(keyword)
    );

    if (hasProductMention) {
      const hasDisclosure = requiredDisclosures.some(disclosure =>
        agentResponse.includes(disclosure)
      );

      if (!hasDisclosure) {
        violations.push({
          rule: 'consumer-protection-disclosures',
          severity: 'warning',
          description: 'Financial product mentioned without required disclosures',
          context: {
            productMentioned: true,
            disclosureProvided: false,
            agentResponse: agentResponse.substring(0, 100) + '...'
          },
          recommendation: 'Include appropriate disclosures when discussing financial products'
        });
      }
    }

    return {
      isCompliant: violations.length === 0,
      violations,
      riskScore: violations.length * 15,
      requiresReview: violations.length > 0
    };
  }
});

ComplianceResult Type

The result returned by evaluateInteraction() and rule functions:
interface ComplianceResult {
  isCompliant: boolean;           // Overall compliance status
  violations: ComplianceViolation[]; // Array of detected violations
  riskScore: number;              // Calculated risk score (0-100)
  requiresReview: boolean;        // Whether human review is needed
}

interface ComplianceViolation {
  rule: string;                   // ID of the rule that detected the violation
  severity: 'info' | 'warning' | 'violation'; // Severity level
  description: string;            // Human-readable description
  context?: any;                  // Additional context about the violation
  recommendation?: string;        // Suggested remediation action
}

Best Practices

Error Handling

The ComplianceEngine handles errors gracefully:
try {
  const result = complianceEngine.evaluateInteraction(context);
  console.log('Compliance evaluation completed:', result);
} catch (error) {
  console.error('Compliance evaluation failed:', error.message);
  // Continue with monitoring - don't let compliance failures break the application
}
Individual rule failures are logged but don’t prevent other rules from executing.

Next Steps