Comprehensive guide to implementing banking AI workflows with compliance monitoring
class CustomerOnboardingWorkflow {
constructor(monitor) {
this.monitor = monitor;
this.agentId = 'onboarding-agent';
}
async processNewCustomer(customerData, sessionId) {
try {
this.monitor.trackConversationStart(this.agentId, sessionId, null, {
workflowType: 'customer_onboarding',
customerType: customerData.type,
channel: customerData.channel
});
// Step 1: Identity Verification
const identityResult = await this.verifyIdentity(customerData, sessionId);
// Step 2: KYC Compliance Check
const kycResult = await this.performKYCCheck(customerData, sessionId);
// Step 3: Risk Assessment
const riskResult = await this.assessCustomerRisk(customerData, sessionId);
// Step 4: Account Setup
if (identityResult.verified && kycResult.compliant && riskResult.acceptable) {
const accountResult = await this.createCustomerAccount(customerData, sessionId);
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 300000, // 5 minutes
messageCount: 8,
resolutionStatus: 'resolved',
workflowOutcome: 'account_created',
customerRiskLevel: riskResult.level
});
return { success: true, accountId: accountResult.accountId };
} else {
// Handle rejection or additional verification needed
return await this.handleOnboardingIssues(
customerData,
sessionId,
{ identityResult, kycResult, riskResult }
);
}
} catch (error) {
this.monitor.trackError(this.agentId, sessionId, error, {
errorType: 'OnboardingWorkflowError',
severity: 'high',
stage: 'customer_onboarding'
});
throw error;
}
}
async verifyIdentity(customerData, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'verify_identity',
{
ssn: customerData.ssn,
driversLicense: customerData.driversLicense,
address: customerData.address,
dateOfBirth: customerData.dateOfBirth
},
{
verified: true,
identityScore: 95,
documentsValid: true,
addressVerified: true
},
2500
);
return { verified: true, score: 95 };
}
async performKYCCheck(customerData, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'kyc_compliance_check',
{
fullName: customerData.fullName,
ssn: customerData.ssn,
address: customerData.address,
occupation: customerData.occupation,
sourceOfFunds: customerData.sourceOfFunds
},
{
compliant: true,
watchlistMatch: false,
pepCheck: false, // Politically Exposed Person
sanctionsMatch: false,
riskRating: 'low'
},
3200
);
return { compliant: true, riskRating: 'low' };
}
async assessCustomerRisk(customerData, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'assess_customer_risk',
{
creditScore: customerData.creditScore,
income: customerData.income,
occupation: customerData.occupation,
accountType: customerData.requestedAccountType,
initialDeposit: customerData.initialDeposit
},
{
riskLevel: 'medium',
riskScore: 45,
factors: ['new_customer', 'moderate_income'],
recommendedLimits: {
dailyWithdrawal: 1000,
monthlyTransfer: 10000
}
},
1800
);
return { acceptable: true, level: 'medium', score: 45 };
}
}
class TransactionProcessingWorkflow {
constructor(monitor) {
this.monitor = monitor;
this.agentId = 'transaction-processor';
}
async processTransaction(transaction, sessionId) {
try {
this.monitor.trackConversationStart(this.agentId, sessionId, transaction.customerId, {
transactionType: transaction.type,
amount: transaction.amount,
merchant: transaction.merchant
});
// Step 1: Pre-transaction Validation
const validationResult = await this.validateTransaction(transaction, sessionId);
if (!validationResult.valid) {
return await this.rejectTransaction(transaction, sessionId, validationResult.reason);
}
// Step 2: Fraud Detection
const fraudResult = await this.detectFraud(transaction, sessionId);
if (fraudResult.flagged) {
return await this.handleFraudDetection(transaction, sessionId, fraudResult);
}
// Step 3: Balance Check and Authorization
const authResult = await this.authorizeTransaction(transaction, sessionId);
if (!authResult.authorized) {
return await this.rejectTransaction(transaction, sessionId, authResult.reason);
}
// Step 4: Execute Transaction
const executionResult = await this.executeTransaction(transaction, sessionId);
// Step 5: Post-transaction Processing
await this.postTransactionProcessing(transaction, sessionId, executionResult);
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 1500, // Fast transaction processing
messageCount: 1,
resolutionStatus: 'resolved',
transactionOutcome: 'completed',
amount: transaction.amount
});
return { success: true, transactionId: executionResult.transactionId };
} catch (error) {
this.monitor.trackError(this.agentId, sessionId, error, {
errorType: 'TransactionProcessingError',
severity: 'critical',
transactionId: transaction.id,
amount: transaction.amount
});
return { success: false, error: error.message };
}
}
async validateTransaction(transaction, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'validate_transaction',
{
customerId: transaction.customerId,
amount: transaction.amount,
accountId: transaction.accountId,
transactionType: transaction.type
},
{
valid: true,
accountActive: true,
sufficientFunds: true,
limitsOk: true
},
150
);
return { valid: true };
}
async detectFraud(transaction, sessionId) {
// Calculate fraud risk score
const riskScore = this.calculateFraudRisk(transaction);
this.monitor.trackToolCall(
this.agentId,
sessionId,
'detect_fraud',
{
transactionId: transaction.id,
customerId: transaction.customerId,
amount: transaction.amount,
merchant: transaction.merchant,
location: transaction.location,
timestamp: transaction.timestamp
},
{
riskScore: riskScore,
flagged: riskScore > 75,
riskFactors: this.identifyRiskFactors(transaction, riskScore),
recommendation: riskScore > 75 ? 'block' : 'allow'
},
300
);
return {
flagged: riskScore > 75,
riskScore: riskScore,
factors: this.identifyRiskFactors(transaction, riskScore)
};
}
calculateFraudRisk(transaction) {
let score = 0;
// Amount-based risk
if (transaction.amount > 5000) score += 25;
if (transaction.amount > 10000) score += 35;
// Location-based risk
if (transaction.location !== transaction.customerLocation) score += 20;
// Time-based risk
const hour = new Date(transaction.timestamp).getHours();
if (hour < 6 || hour > 22) score += 15;
// Merchant risk
if (this.isHighRiskMerchant(transaction.merchant)) score += 30;
return Math.min(score, 100);
}
identifyRiskFactors(transaction, riskScore) {
const factors = [];
if (transaction.amount > 5000) factors.push('high_amount');
if (transaction.location !== transaction.customerLocation) factors.push('unusual_location');
if (this.isHighRiskMerchant(transaction.merchant)) factors.push('high_risk_merchant');
return factors;
}
isHighRiskMerchant(merchant) {
const highRiskCategories = ['gambling', 'cryptocurrency', 'money_transfer'];
return highRiskCategories.some(cat => merchant.toLowerCase().includes(cat));
}
}
class CreditApplicationWorkflow {
constructor(monitor) {
this.monitor = monitor;
this.agentId = 'credit-application-agent';
}
async processCreditApplication(application, sessionId) {
try {
this.monitor.trackConversationStart(this.agentId, sessionId, application.customerId, {
applicationType: 'credit_application',
requestedAmount: application.requestedAmount,
creditType: application.creditType,
applicantIncome: application.income
});
// Step 1: Application Completeness Check
const completenessResult = await this.validateApplicationCompleteness(application, sessionId);
if (!completenessResult.complete) {
return await this.requestAdditionalInfo(application, sessionId, completenessResult.missingFields);
}
// Step 2: Credit Bureau Check
const creditResult = await this.performCreditCheck(application, sessionId);
// Step 3: Income Verification
const incomeResult = await this.verifyIncome(application, sessionId);
// Step 4: Debt-to-Income Analysis
const dtiResult = await this.calculateDebtToIncome(application, sessionId, creditResult);
// Step 5: Fair Lending Compliance Check
const fairLendingResult = await this.checkFairLending(application, sessionId);
// Step 6: Credit Decision
const decision = await this.makeCreditDecision(
application,
sessionId,
{ creditResult, incomeResult, dtiResult, fairLendingResult }
);
// Step 7: Document Decision with Adverse Action Notice if needed
if (!decision.approved) {
await this.generateAdverseActionNotice(application, sessionId, decision);
}
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 420000, // 7 minutes for credit decision
messageCount: 12,
resolutionStatus: decision.approved ? 'approved' : 'declined',
creditDecision: decision.approved,
requestedAmount: application.requestedAmount,
approvedAmount: decision.approvedAmount || 0
});
return decision;
} catch (error) {
this.monitor.trackError(this.agentId, sessionId, error, {
errorType: 'CreditApplicationError',
severity: 'high',
applicantId: application.customerId,
creditType: application.creditType
});
throw error;
}
}
async performCreditCheck(application, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'credit_bureau_check',
{
ssn: application.ssn,
customerId: application.customerId,
requestType: 'full_report'
},
{
creditScore: 720,
creditHistory: {
accounts: 8,
oldestAccount: 84, // months
avgAccountAge: 36,
totalCredit: 45000,
utilization: 0.25
},
paymentHistory: 0.96,
derogatory: 0,
inquiries: 2
},
3500
);
return {
score: 720,
grade: 'good',
qualifiesForCredit: true
};
}
async checkFairLending(application, sessionId) {
// Ensure fair lending compliance by checking for prohibited factors
this.monitor.trackToolCall(
this.agentId,
sessionId,
'fair_lending_check',
{
applicantData: {
income: application.income,
creditScore: 720,
employment: application.employment,
requestedAmount: application.requestedAmount,
// Note: Race, gender, religion, etc. should NOT be included
},
decisionFactors: ['income', 'credit_score', 'employment_history', 'debt_to_income']
},
{
compliant: true,
prohibitedFactorsUsed: false,
decisionBasisValid: true,
documentationComplete: true
},
800
);
return { compliant: true, valid: true };
}
async makeCreditDecision(application, sessionId, analysisResults) {
const { creditResult, incomeResult, dtiResult, fairLendingResult } = analysisResults;
// AI-assisted decision making with compliance
this.monitor.trackToolCall(
this.agentId,
sessionId,
'make_credit_decision',
{
creditScore: creditResult.score,
income: incomeResult.verifiedIncome,
debtToIncome: dtiResult.ratio,
requestedAmount: application.requestedAmount,
fairLendingCompliant: fairLendingResult.compliant
},
{
approved: creditResult.score >= 680 && dtiResult.ratio <= 0.43,
approvedAmount: Math.min(application.requestedAmount, incomeResult.verifiedIncome * 0.3),
interestRate: this.calculateInterestRate(creditResult.score),
terms: 60, // months
reasonCodes: creditResult.score < 680 ? ['credit_score'] : []
},
1200
);
const approved = creditResult.score >= 680 && dtiResult.ratio <= 0.43;
return {
approved: approved,
approvedAmount: approved ? Math.min(application.requestedAmount, incomeResult.verifiedIncome * 0.3) : 0,
interestRate: approved ? this.calculateInterestRate(creditResult.score) : null,
terms: approved ? 60 : null,
reasonCodes: !approved ? this.getDeclineReasons(creditResult, dtiResult) : [],
decisionDate: new Date().toISOString()
};
}
calculateInterestRate(creditScore) {
if (creditScore >= 750) return 6.99;
if (creditScore >= 700) return 8.99;
if (creditScore >= 650) return 12.99;
return 16.99;
}
getDeclineReasons(creditResult, dtiResult) {
const reasons = [];
if (creditResult.score < 680) reasons.push('insufficient_credit_history');
if (dtiResult.ratio > 0.43) reasons.push('excessive_debt_obligations');
return reasons;
}
}
class AccountManagementWorkflow {
constructor(monitor) {
this.monitor = monitor;
this.agentId = 'account-management-agent';
}
async handleAccountInquiry(customerId, inquiryType, details, sessionId) {
try {
this.monitor.trackConversationStart(this.agentId, sessionId, customerId, {
inquiryType: inquiryType,
channel: details.channel,
customerTier: details.customerTier
});
switch (inquiryType) {
case 'balance_inquiry':
return await this.processBalanceInquiry(customerId, sessionId, details);
case 'transaction_history':
return await this.processTransactionHistory(customerId, sessionId, details);
case 'account_closure':
return await this.processAccountClosure(customerId, sessionId, details);
case 'dispute_transaction':
return await this.processTransactionDispute(customerId, sessionId, details);
case 'update_information':
return await this.processInformationUpdate(customerId, sessionId, details);
default:
throw new Error(`Unknown inquiry type: ${inquiryType}`);
}
} catch (error) {
this.monitor.trackError(this.agentId, sessionId, error, {
errorType: 'AccountManagementError',
inquiryType: inquiryType,
customerId: customerId
});
throw error;
}
}
async processBalanceInquiry(customerId, sessionId, details) {
// Verify customer identity first
const identityResult = await this.verifyCustomerIdentity(customerId, sessionId, details);
if (!identityResult.verified) {
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 30000,
resolutionStatus: 'unresolved',
endReason: 'identity_verification_failed'
});
return { error: 'Identity verification failed' };
}
// Retrieve account information
this.monitor.trackToolCall(
this.agentId,
sessionId,
'get_account_balance',
{
customerId: customerId,
accountType: details.accountType || 'all',
includeAvailableCredit: true
},
{
checkingBalance: 2547.83,
savingsBalance: 15420.50,
creditCardBalance: 1250.75,
availableCredit: 8749.25,
lastUpdate: new Date().toISOString()
},
450
);
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 45000,
messageCount: 3,
resolutionStatus: 'resolved',
inquiryType: 'balance_inquiry'
});
return {
success: true,
balances: {
checking: 2547.83,
savings: 15420.50,
creditCard: 1250.75
}
};
}
async processTransactionDispute(customerId, sessionId, details) {
// High-priority workflow for transaction disputes
this.monitor.trackUserMessage(this.agentId, sessionId,
`Customer disputes transaction: ${details.transactionId}`, customerId);
// Retrieve transaction details
this.monitor.trackToolCall(
this.agentId,
sessionId,
'get_transaction_details',
{
transactionId: details.transactionId,
customerId: customerId
},
{
transactionId: details.transactionId,
amount: details.amount,
merchant: details.merchant,
date: details.date,
disputeEligible: true,
provisionalCredit: details.amount <= 500
},
600
);
// Create dispute case
this.monitor.trackToolCall(
this.agentId,
sessionId,
'create_dispute_case',
{
transactionId: details.transactionId,
customerId: customerId,
disputeReason: details.reason,
amount: details.amount,
supportingDocuments: details.documents || []
},
{
disputeId: `DISPUTE-${Date.now()}`,
status: 'under_investigation',
provisionalCreditIssued: details.amount <= 500,
estimatedResolution: 10, // business days
nextAction: 'merchant_notification'
},
1200
);
this.monitor.trackAgentResponse(
this.agentId,
sessionId,
`Dispute case DISPUTE-${Date.now()} has been created for transaction ${details.transactionId}. ${details.amount <= 500 ? 'Provisional credit has been issued.' : 'Investigation will be completed within 10 business days.'}`,
{
disputeCreated: true,
provisionalCredit: details.amount <= 500,
highPriority: details.amount > 1000
}
);
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 300000, // 5 minutes for dispute creation
messageCount: 8,
resolutionStatus: 'escalated',
disputeCreated: true,
amount: details.amount
});
return {
success: true,
disputeId: `DISPUTE-${Date.now()}`,
provisionalCredit: details.amount <= 500
};
}
async verifyCustomerIdentity(customerId, sessionId, details) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'verify_customer_identity',
{
customerId: customerId,
verificationMethod: details.verificationMethod || 'security_questions',
channel: details.channel,
deviceFingerprint: details.deviceFingerprint
},
{
verified: true,
verificationScore: 95,
method: 'security_questions',
riskLevel: 'low'
},
800
);
return { verified: true, score: 95 };
}
}
class ComplianceMonitoringWorkflow {
constructor(monitor) {
this.monitor = monitor;
this.agentId = 'compliance-monitor';
}
async monitorForBSAAML(interactions, sessionId) {
// Monitor for Bank Secrecy Act / Anti-Money Laundering compliance
this.monitor.trackConversationStart(this.agentId, sessionId, 'system', {
monitoringType: 'bsa_aml',
interactionCount: interactions.length,
automated: true
});
for (const interaction of interactions) {
const suspiciousActivity = await this.detectSuspiciousActivity(interaction, sessionId);
if (suspiciousActivity.detected) {
await this.generateSARAlert(interaction, sessionId, suspiciousActivity);
}
}
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 60000,
resolutionStatus: 'completed',
alertsGenerated: interactions.filter(i => i.suspicious).length
});
}
async detectSuspiciousActivity(interaction, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'analyze_suspicious_activity',
{
transactionAmount: interaction.amount,
transactionPattern: interaction.pattern,
customerProfile: interaction.customerProfile,
frequency: interaction.frequency,
cashActivity: interaction.cashActivity
},
{
suspiciousActivityScore: 75,
indicators: ['large_cash_deposits', 'structuring_pattern', 'unusual_frequency'],
requiresSAR: true,
confidence: 0.85
},
1500
);
return {
detected: true,
score: 75,
indicators: ['large_cash_deposits', 'structuring_pattern'],
requiresSAR: true
};
}
async generateSARAlert(interaction, sessionId, suspiciousActivity) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'generate_sar_alert',
{
customerId: interaction.customerId,
transactionData: interaction,
suspiciousIndicators: suspiciousActivity.indicators,
analysisScore: suspiciousActivity.score
},
{
sarId: `SAR-${Date.now()}`,
priority: 'high',
assignedTo: 'compliance_team',
dueDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
status: 'pending_review'
},
2000
);
this.monitor.track(this.agentId, {
sessionId: sessionId,
interactionType: 'compliance_violation',
metadata: {
violationType: 'bsa_aml',
severity: 'violation',
description: 'Suspicious activity requiring SAR filing',
sarId: `SAR-${Date.now()}`,
indicators: suspiciousActivity.indicators,
riskScore: suspiciousActivity.score
}
});
}
async monitorFairLending(lendingDecisions, sessionId) {
this.monitor.trackConversationStart(this.agentId, sessionId, 'system', {
monitoringType: 'fair_lending',
decisionCount: lendingDecisions.length,
automated: true
});
const analysisResults = [];
for (const decision of lendingDecisions) {
const fairnessAnalysis = await this.analyzeLendingFairness(decision, sessionId);
analysisResults.push(fairnessAnalysis);
if (fairnessAnalysis.concernsDetected) {
await this.flagLendingConcern(decision, sessionId, fairnessAnalysis);
}
}
// Generate fair lending report
await this.generateFairLendingReport(analysisResults, sessionId);
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: 180000,
resolutionStatus: 'completed',
decisionsAnalyzed: lendingDecisions.length,
concernsFound: analysisResults.filter(r => r.concernsDetected).length
});
}
async analyzeLendingFairness(decision, sessionId) {
this.monitor.trackToolCall(
this.agentId,
sessionId,
'analyze_lending_fairness',
{
applicantData: {
income: decision.income,
creditScore: decision.creditScore,
employment: decision.employment,
requestedAmount: decision.requestedAmount
},
decisionOutcome: decision.approved,
decisionFactors: decision.factors,
interestRate: decision.interestRate
},
{
fairnessScore: 92,
concernsDetected: false,
disparateImpact: false,
reasonCodesAppropriate: true,
decisionConsistent: true
},
1000
);
return {
fairnessScore: 92,
concernsDetected: false,
decision: decision
};
}
async flagLendingConcern(decision, sessionId, analysis) {
this.monitor.track(this.agentId, {
sessionId: sessionId,
interactionType: 'compliance_violation',
metadata: {
violationType: 'fair_lending',
severity: 'warning',
description: 'Potential fair lending concern detected',
applicantId: decision.applicantId,
fairnessScore: analysis.fairnessScore,
concerns: analysis.concerns
}
});
}
}
class WorkflowOrchestrator {
constructor(monitor) {
this.monitor = monitor;
this.workflows = new Map();
this.agentId = 'workflow-orchestrator';
}
async executeWorkflow(workflowType, data, sessionId) {
const workflow = this.getWorkflow(workflowType);
this.monitor.trackConversationStart(this.agentId, sessionId, data.customerId, {
workflowType: workflowType,
orchestrated: true,
estimatedDuration: workflow.estimatedDuration
});
try {
const result = await workflow.execute(data, sessionId);
this.monitor.trackConversationEnd(this.agentId, sessionId, {
duration: result.actualDuration,
resolutionStatus: result.success ? 'resolved' : 'failed',
workflowType: workflowType,
stepsCompleted: result.stepsCompleted
});
return result;
} catch (error) {
this.monitor.trackError(this.agentId, sessionId, error, {
errorType: 'WorkflowOrchestrationError',
workflowType: workflowType,
stage: 'execution'
});
throw error;
}
}
registerWorkflow(workflowType, workflow) {
this.workflows.set(workflowType, workflow);
}
getWorkflow(workflowType) {
const workflow = this.workflows.get(workflowType);
if (!workflow) {
throw new Error(`Unknown workflow type: ${workflowType}`);
}
return workflow;
}
}
// Example usage
async function setupBankingWorkflows() {
const monitor = new AgentMonitor({
apiKey: process.env.AGENT_GOVERNANCE_API_KEY,
organizationId: process.env.AGENT_GOVERNANCE_ORG_ID,
enableComplianceChecks: true
});
const orchestrator = new WorkflowOrchestrator(monitor);
// Register workflows
orchestrator.registerWorkflow('customer_onboarding', new CustomerOnboardingWorkflow(monitor));
orchestrator.registerWorkflow('transaction_processing', new TransactionProcessingWorkflow(monitor));
orchestrator.registerWorkflow('credit_application', new CreditApplicationWorkflow(monitor));
orchestrator.registerWorkflow('account_management', new AccountManagementWorkflow(monitor));
return { orchestrator, monitor };
}
Security and Authentication
Compliance Monitoring
Error Handling and Recovery
Performance and Scalability