Skip to main content

Complete Example: Loan Approval Process

A comprehensive loan approval workflow demonstrating validation, user approvals, dynamic routing, and notifications.

Process Overview

Business Scenario

A customer submits a loan application. The system validates the application, performs risk assessment, routes to the appropriate approval level, and notifies the customer of the decision.

Process Flow

Start

Validate Application (Script)

Calculate Risk Score (Script)

Risk Assessment Gateway
├── Low Risk → Auto-Approve
├── Medium Risk → Loan Officer Review (User)
├── High Risk → Manager Review (User)
└── Very High Risk → Reject

Approval Decision Gateway
├── Approved → Send Approval Notification (Send)
└── Rejected → Send Rejection Notification (Send)

End

Features Demonstrated

  • ScriptTask - Data validation and calculations
  • UserTask - Human approvals
  • Gateway - Dynamic routing based on risk
  • SendTask - Email notifications
  • Variables - Data flow throughout process
  • Conditional Routing - Multi-path decisions

Complete BPMN XML

Save this as loan-approval-complete.bpmn:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:custom="http://banklingo.com/schema/bpmn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
targetNamespace="http://banklingo.com/bpmn"
id="Definitions_LoanApproval">

<bpmn:process id="LoanApprovalComplete" name="Complete Loan Approval Process" isExecutable="true">

<!-- ========== START EVENT ========== -->
<bpmn:startEvent id="StartEvent_1" name="Loan Application Received" />
<bpmn:sequenceFlow sourceRef="StartEvent_1" targetRef="Task_ValidateApplication" />

<!-- ========== TASK 1: VALIDATE APPLICATION ========== -->
<bpmn:scriptTask id="Task_ValidateApplication" name="Validate Application Data">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Validate required fields
const errors = [];

if (!loanAmount || loanAmount &lt;= 0) {
errors.push('Invalid loan amount');
}
if (loanAmount > 500000) {
errors.push('Loan amount exceeds maximum of $500,000');
}
if (!customerName || customerName.trim() === '') {
errors.push('Customer name is required');
}
if (!customerEmail || !customerEmail.includes('@')) {
errors.push('Valid email is required');
}
if (!loanPurpose || loanPurpose.trim() === '') {
errors.push('Loan purpose is required');
}
if (!termMonths || termMonths &lt; 12 || termMonths > 360) {
errors.push('Term must be between 12 and 360 months');
}

// Check if validation passed
if (errors.length > 0) {
throw new Error('Validation failed: ' + errors.join(', '));
}

// Set validation metadata
validationStatus = 'Passed';
validationDate = new Date().toISOString();
validationErrors = [];

console.log('Application validated successfully');
" />
<custom:property name="ScriptLanguage" value="javascript" />
<custom:property name="EntityState" value="Validating" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>StartEvent_1</bpmn:incoming>
<bpmn:outgoing>Flow_ToRiskCalculation</bpmn:outgoing>
</bpmn:scriptTask>

<bpmn:sequenceFlow id="Flow_ToRiskCalculation" sourceRef="Task_ValidateApplication" targetRef="Task_CalculateRisk" />

<!-- ========== TASK 2: CALCULATE RISK SCORE ========== -->
<bpmn:scriptTask id="Task_CalculateRisk" name="Calculate Risk Score">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Calculate risk score based on multiple factors
let riskScore = 0;

// Factor 1: Loan amount (0-30 points)
if (loanAmount &lt; 10000) riskScore += 5;
else if (loanAmount &lt; 50000) riskScore += 10;
else if (loanAmount &lt; 100000) riskScore += 20;
else riskScore += 30;

// Factor 2: Term length (0-20 points)
if (termMonths &lt;= 36) riskScore += 5;
else if (termMonths &lt;= 60) riskScore += 10;
else if (termMonths &lt;= 120) riskScore += 15;
else riskScore += 20;

// Factor 3: Credit score (if provided) (0-50 points)
if (creditScore) {
if (creditScore &lt; 580) riskScore += 50;
else if (creditScore &lt; 640) riskScore += 40;
else if (creditScore &lt; 680) riskScore += 25;
else if (creditScore &lt; 720) riskScore += 15;
else riskScore += 5;
} else {
// No credit score = higher risk
riskScore += 30;
}

// Calculate risk level
if (riskScore &lt; 30) {
riskLevel = 'Low';
autoApproveEligible = true;
} else if (riskScore &lt; 50) {
riskLevel = 'Medium';
autoApproveEligible = false;
} else if (riskScore &lt; 70) {
riskLevel = 'High';
autoApproveEligible = false;
} else {
riskLevel = 'VeryHigh';
autoApproveEligible = false;
}

// Calculate estimated interest rate
baseRate = 5.0;
if (riskLevel === 'Low') estimatedRate = baseRate + 1.0;
else if (riskLevel === 'Medium') estimatedRate = baseRate + 2.5;
else if (riskLevel === 'High') estimatedRate = baseRate + 4.0;
else estimatedRate = baseRate + 6.0;

// Calculate monthly payment
const monthlyRate = estimatedRate / 12 / 100;
monthlyPayment = loanAmount *
(monthlyRate * Math.pow(1 + monthlyRate, termMonths)) /
(Math.pow(1 + monthlyRate, termMonths) - 1);
monthlyPayment = Math.round(monthlyPayment * 100) / 100;

riskCalculatedAt = new Date().toISOString();

console.log('Risk Score:', riskScore, 'Level:', riskLevel);
" />
<custom:property name="EntityState" value="RiskAssessment" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_ToRiskCalculation</bpmn:incoming>
<bpmn:outgoing>Flow_ToRiskGateway</bpmn:outgoing>
</bpmn:scriptTask>

<bpmn:sequenceFlow id="Flow_ToRiskGateway" sourceRef="Task_CalculateRisk" targetRef="Gateway_RiskRouting" />

<!-- ========== GATEWAY: RISK-BASED ROUTING ========== -->
<bpmn:exclusiveGateway id="Gateway_RiskRouting" name="Risk Assessment" default="Flow_Reject">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
// Route based on risk level
if (riskLevel === 'Low' &amp;&amp; autoApproveEligible) {
return 'Flow_AutoApprove';
} else if (riskLevel === 'Medium') {
return 'Flow_OfficerReview';
} else if (riskLevel === 'High') {
return 'Flow_ManagerReview';
}
// Very high risk goes to rejection
return 'Flow_Reject';
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_ToRiskGateway</bpmn:incoming>
<bpmn:outgoing>Flow_AutoApprove</bpmn:outgoing>
<bpmn:outgoing>Flow_OfficerReview</bpmn:outgoing>
<bpmn:outgoing>Flow_ManagerReview</bpmn:outgoing>
<bpmn:outgoing>Flow_Reject</bpmn:outgoing>
</bpmn:exclusiveGateway>

<!-- ========== PATH 1: AUTO-APPROVE (LOW RISK) ========== -->
<bpmn:sequenceFlow id="Flow_AutoApprove" name="Low Risk - Auto-Approve"
sourceRef="Gateway_RiskRouting" targetRef="Task_SetApproved" />

<bpmn:scriptTask id="Task_SetApproved" name="Set Auto-Approved">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
approvalDecision = 'Approved';
approvalMethod = 'Automatic';
approvedBy = 'System';
approvalDate = new Date().toISOString();
approvalNotes = 'Auto-approved based on low risk assessment';
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_AutoApprove</bpmn:incoming>
<bpmn:outgoing>Flow_AutoToNotify</bpmn:outgoing>
</bpmn:scriptTask>

<bpmn:sequenceFlow id="Flow_AutoToNotify" sourceRef="Task_SetApproved" targetRef="Gateway_DecisionMerge" />

<!-- ========== PATH 2: LOAN OFFICER REVIEW (MEDIUM RISK) ========== -->
<bpmn:sequenceFlow id="Flow_OfficerReview" name="Medium Risk - Officer Review"
sourceRef="Gateway_RiskRouting" targetRef="Task_OfficerReview" />

<bpmn:userTask id="Task_OfficerReview" name="Loan Officer Review">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="FormKey" value="loan-officer-review" />
<custom:property name="UserActions" value="Approve,Reject,RequestMoreInfo" />
<custom:property name="EntityState" value="PendingOfficerReview" />
<custom:property name="ResponsibleTeams" value="LoanOfficers" />
<custom:property name="Description" value="Review medium-risk loan application and make approval decision" />
<custom:property name="InputMapping" value="{
&quot;application&quot;: &quot;{customerName, loanAmount, loanPurpose, termMonths}&quot;,
&quot;risk&quot;: &quot;{riskLevel, riskScore, estimatedRate}&quot;,
&quot;payment&quot;: &quot;monthlyPayment&quot;
}" />
<custom:property name="OutputMapping" value="{
&quot;approvalDecision&quot;: &quot;decision&quot;,
&quot;approverComments&quot;: &quot;comments&quot;,
&quot;approvedBy&quot;: &quot;officerName&quot;
}" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_OfficerReview</bpmn:incoming>
<bpmn:outgoing>Flow_OfficerToMerge</bpmn:outgoing>
</bpmn:userTask>

<bpmn:sequenceFlow id="Flow_OfficerToMerge" sourceRef="Task_OfficerReview" targetRef="Gateway_DecisionMerge" />

<!-- ========== PATH 3: MANAGER REVIEW (HIGH RISK) ========== -->
<bpmn:sequenceFlow id="Flow_ManagerReview" name="High Risk - Manager Review"
sourceRef="Gateway_RiskRouting" targetRef="Task_ManagerReview" />

<bpmn:userTask id="Task_ManagerReview" name="Manager Review (High Risk)">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="FormKey" value="manager-review" />
<custom:property name="UserActions" value="Approve,Reject,EscalateToBoard" />
<custom:property name="EntityState" value="PendingManagerReview" />
<custom:property name="ResponsibleTeams" value="Managers,SeniorManagers" />
<custom:property name="Description" value="High-risk loan application requiring manager approval" />
<custom:property name="InputMapping" value="{
&quot;application&quot;: &quot;{customerName, loanAmount, loanPurpose, termMonths}&quot;,
&quot;risk&quot;: &quot;{riskLevel, riskScore, estimatedRate}&quot;,
&quot;payment&quot;: &quot;monthlyPayment&quot;
}" />
<custom:property name="OutputMapping" value="{
&quot;approvalDecision&quot;: &quot;decision&quot;,
&quot;approverComments&quot;: &quot;comments&quot;,
&quot;approvedBy&quot;: &quot;managerName&quot;
}" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_ManagerReview</bpmn:incoming>
<bpmn:outgoing>Flow_ManagerToMerge</bpmn:outgoing>
</bpmn:userTask>

<bpmn:sequenceFlow id="Flow_ManagerToMerge" sourceRef="Task_ManagerReview" targetRef="Gateway_DecisionMerge" />

<!-- ========== PATH 4: AUTO-REJECT (VERY HIGH RISK) ========== -->
<bpmn:sequenceFlow id="Flow_Reject" name="Very High Risk - Reject"
sourceRef="Gateway_RiskRouting" targetRef="Task_SetRejected" />

<bpmn:scriptTask id="Task_SetRejected" name="Set Auto-Rejected">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
approvalDecision = 'Rejected';
approvalMethod = 'Automatic';
approvedBy = 'System';
approvalDate = new Date().toISOString();
rejectionReason = 'Application does not meet minimum risk criteria';
approvalNotes = 'Auto-rejected due to very high risk assessment';
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_Reject</bpmn:incoming>
<bpmn:outgoing>Flow_RejectToMerge</bpmn:outgoing>
</bpmn:scriptTask>

<bpmn:sequenceFlow id="Flow_RejectToMerge" sourceRef="Task_SetRejected" targetRef="Gateway_DecisionMerge" />

<!-- ========== MERGE GATEWAY ========== -->
<bpmn:exclusiveGateway id="Gateway_DecisionMerge" name="Merge Paths" />

<bpmn:incoming>Flow_AutoToNotify</bpmn:incoming>
<bpmn:incoming>Flow_OfficerToMerge</bpmn:incoming>
<bpmn:incoming>Flow_ManagerToMerge</bpmn:incoming>
<bpmn:incoming>Flow_RejectToMerge</bpmn:incoming>
<bpmn:outgoing>Flow_ToFinalDecision</bpmn:outgoing>

<bpmn:sequenceFlow id="Flow_ToFinalDecision" sourceRef="Gateway_DecisionMerge" targetRef="Gateway_FinalDecision" />

<!-- ========== GATEWAY: FINAL DECISION ROUTING ========== -->
<bpmn:exclusiveGateway id="Gateway_FinalDecision" name="Approved?" default="Flow_ToRejectionNotification">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
return approvalDecision === 'Approved' ? 'Flow_ToApprovalNotification' : 'Flow_ToRejectionNotification';
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_ToFinalDecision</bpmn:incoming>
<bpmn:outgoing>Flow_ToApprovalNotification</bpmn:outgoing>
<bpmn:outgoing>Flow_ToRejectionNotification</bpmn:outgoing>
</bpmn:exclusiveGateway>

<!-- ========== APPROVED PATH: SEND NOTIFICATION ========== -->
<bpmn:sequenceFlow id="Flow_ToApprovalNotification" name="Approved"
sourceRef="Gateway_FinalDecision" targetRef="Task_SendApprovalEmail" />

<bpmn:sendTask id="Task_SendApprovalEmail" name="Send Approval Notification">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Destination" value="/api/notifications/send" />
<custom:property name="Method" value="POST" />
<custom:property name="PayloadTemplate" value="{
&quot;recipientEmail&quot;: &quot;{{customerEmail}}&quot;,
&quot;recipientName&quot;: &quot;{{customerName}}&quot;,
&quot;subject&quot;: &quot;Loan Application Approved&quot;,
&quot;templateId&quot;: &quot;loan-approval&quot;,
&quot;templateData&quot;: {
&quot;customerName&quot;: &quot;{{customerName}}&quot;,
&quot;loanAmount&quot;: &quot;{{loanAmount}}&quot;,
&quot;interestRate&quot;: &quot;{{estimatedRate}}&quot;,
&quot;monthlyPayment&quot;: &quot;{{monthlyPayment}}&quot;,
&quot;termMonths&quot;: &quot;{{termMonths}}&quot;,
&quot;approvedBy&quot;: &quot;{{approvedBy}}&quot;,
&quot;nextSteps&quot;: &quot;Please visit your nearest branch to complete the loan documentation.&quot;
},
&quot;priority&quot;: &quot;high&quot;
}" />
<custom:property name="Retries" value="3" />
<custom:property name="TimeoutMs" value="10000" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_ToApprovalNotification</bpmn:incoming>
<bpmn:outgoing>Flow_ToApprovedEnd</bpmn:outgoing>
</bpmn:sendTask>

<bpmn:sequenceFlow id="Flow_ToApprovedEnd" sourceRef="Task_SendApprovalEmail" targetRef="EndEvent_Approved" />
<bpmn:endEvent id="EndEvent_Approved" name="Application Approved" />

<!-- ========== REJECTED PATH: SEND NOTIFICATION ========== -->
<bpmn:sequenceFlow id="Flow_ToRejectionNotification" name="Rejected"
sourceRef="Gateway_FinalDecision" targetRef="Task_SendRejectionEmail" />

<bpmn:sendTask id="Task_SendRejectionEmail" name="Send Rejection Notification">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Destination" value="/api/notifications/send" />
<custom:property name="Method" value="POST" />
<custom:property name="PayloadTemplate" value="{
&quot;recipientEmail&quot;: &quot;{{customerEmail}}&quot;,
&quot;recipientName&quot;: &quot;{{customerName}}&quot;,
&quot;subject&quot;: &quot;Loan Application Decision&quot;,
&quot;templateId&quot;: &quot;loan-rejection&quot;,
&quot;templateData&quot;: {
&quot;customerName&quot;: &quot;{{customerName}}&quot;,
&quot;loanAmount&quot;: &quot;{{loanAmount}}&quot;,
&quot;rejectionReason&quot;: &quot;{{rejectionReason}}&quot;,
&quot;nextSteps&quot;: &quot;You may reapply after addressing the concerns mentioned.&quot;
},
&quot;priority&quot;: &quot;normal&quot;
}" />
<custom:property name="Retries" value="3" />
<custom:property name="TimeoutMs" value="10000" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_ToRejectionNotification</bpmn:incoming>
<bpmn:outgoing>Flow_ToRejectedEnd</bpmn:outgoing>
</bpmn:sendTask>

<bpmn:sequenceFlow id="Flow_ToRejectedEnd" sourceRef="Task_SendRejectionEmail" targetRef="EndEvent_Rejected" />
<bpmn:endEvent id="EndEvent_Rejected" name="Application Rejected" />

</bpmn:process>
</bpmn:definitions>

Deployment

1. Deploy the Process Definition

POST /api/process-definitions
Content-Type: application/json
Authorization: Bearer YOUR_API_TOKEN

{
"processKey": "LoanApprovalComplete",
"name": "Complete Loan Approval Process",
"description": "End-to-end loan approval with validation, risk assessment, and notifications",
"bpmnXml": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>...",
"version": 1,
"isActive": true
}

Execution Examples

Example 1: Low Risk - Auto-Approved

Start Process:

{
"processKey": "LoanApprovalComplete",
"businessKey": "LOAN-2025-001",
"variables": {
"customerName": "John Doe",
"customerEmail": "john.doe@example.com",
"loanAmount": 8000,
"loanPurpose": "Home Improvement",
"termMonths": 24,
"creditScore": 750
}
}

Expected Flow:

  1. Validation ✓
  2. Risk Calculation → riskLevel: "Low", riskScore: 20
  3. Gateway → Auto-Approve path
  4. Set Approved
  5. Send Approval Email
  6. End (Approved)

No user interaction needed!


Example 2: Medium Risk - Officer Review

Start Process:

{
"processKey": "LoanApprovalComplete",
"businessKey": "LOAN-2025-002",
"variables": {
"customerName": "Jane Smith",
"customerEmail": "jane.smith@example.com",
"loanAmount": 45000,
"loanPurpose": "Business Expansion",
"termMonths": 60,
"creditScore": 680
}
}

Expected Flow:

  1. Validation ✓
  2. Risk Calculation → riskLevel: "Medium", riskScore: 40
  3. Gateway → Officer Review path
  4. PAUSES at Task_OfficerReview (UserTask)

Complete UserTask:

POST /api/user-tasks/complete

{
"instanceGuid": "{guid}",
"taskId": "Task_OfficerReview",
"userAction": "Approve",
"variables": {
"decision": "Approved",
"comments": "Strong business plan. Approved with standard terms.",
"officerName": "Mike Johnson"
}
}

Continues: 5. Gateway → Approved path 6. Send Approval Email 7. End (Approved)


Example 3: High Risk - Manager Review

Start Process:

{
"processKey": "LoanApprovalComplete",
"businessKey": "LOAN-2025-003",
"variables": {
"customerName": "Bob Wilson",
"customerEmail": "bob.wilson@example.com",
"loanAmount": 150000,
"loanPurpose": "Real Estate Investment",
"termMonths": 180,
"creditScore": 620
}
}

Expected Flow:

  1. Validation ✓
  2. Risk Calculation → riskLevel: "High", riskScore: 65
  3. Gateway → Manager Review path
  4. PAUSES at Task_ManagerReview (UserTask)

Complete UserTask:

POST /api/user-tasks/complete

{
"instanceGuid": "{guid}",
"taskId": "Task_ManagerReview",
"userAction": "Approve",
"variables": {
"decision": "Approved",
"comments": "Approved with higher interest rate and additional collateral requirement.",
"managerName": "Sarah Lee"
}
}

Continues: 5. Gateway → Approved path 6. Send Approval Email 7. End (Approved)


Example 4: Very High Risk - Auto-Rejected

Start Process:

{
"processKey": "LoanApprovalComplete",
"businessKey": "LOAN-2025-004",
"variables": {
"customerName": "Alex Brown",
"customerEmail": "alex.brown@example.com",
"loanAmount": 300000,
"loanPurpose": "Investment",
"termMonths": 240,
"creditScore": 550
}
}

Expected Flow:

  1. Validation ✓
  2. Risk Calculation → riskLevel: "VeryHigh", riskScore: 80
  3. Gateway → Reject path
  4. Set Rejected
  5. Send Rejection Email
  6. End (Rejected)

No user interaction needed!

Variables Throughout Process

Initial Variables (Input)

{
"customerName": "John Doe",
"customerEmail": "john.doe@example.com",
"loanAmount": 45000,
"loanPurpose": "Business Expansion",
"termMonths": 60,
"creditScore": 680
}

After Validation

{
...initial,
"validationStatus": "Passed",
"validationDate": "2025-12-18T10:00:00Z",
"validationErrors": []
}

After Risk Calculation

{
...previous,
"riskScore": 40,
"riskLevel": "Medium",
"autoApproveEligible": false,
"estimatedRate": 7.5,
"monthlyPayment": 891.33,
"riskCalculatedAt": "2025-12-18T10:00:01Z"
}

After Approval (UserTask)

{
...previous,
"approvalDecision": "Approved",
"approverComments": "Strong business plan",
"approvedBy": "Mike Johnson",
"approvalDate": "2025-12-18T10:15:00Z",
"approvalMethod": "Manual"
}

Final Variables

{
...all_previous,
"notificationSent": true,
"notificationSentAt": "2025-12-18T10:15:05Z",
"processCompletedAt": "2025-12-18T10:15:05Z"
}

Customization Ideas

1. Add Parallel Credit Checks

Replace risk calculation with parallel checks:

<bpmn:parallelGateway id="Gateway_ParallelChecks" />
<!-- Add multiple ServiceTasks for credit bureaus -->
<bpmn:parallelGateway id="Gateway_JoinChecks" />

2. Add Document Upload Requirements

Insert after approval, before notification:

<bpmn:userTask id="Task_UploadDocuments" name="Upload Required Documents">
<custom:property name="FormKey" value="document-upload" />
</bpmn:userTask>

3. Add SLA Timers

Add boundary timer events for escalation:

<bpmn:boundaryEvent id="Event_ReviewTimeout" attachedToRef="Task_OfficerReview">
<bpmn:timerEventDefinition>
<bpmn:timeDuration>PT24H</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:boundaryEvent>

4. Integrate with External Systems

Replace script-based risk calculation with API call:

<bpmn:serviceTask id="Task_CreditBureauCheck" name="Credit Bureau Check">
<custom:property name="Endpoint" value="https://credit-bureau-api.com/check" />
<custom:property name="Method" value="POST" />
</bpmn:serviceTask>

5. Add SMS Notifications

Add parallel notification tasks:

<bpmn:parallelGateway id="Gateway_NotifySplit" />
<bpmn:sendTask id="Task_SendEmail" ... />
<bpmn:sendTask id="Task_SendSMS" ... />
<bpmn:parallelGateway id="Gateway_NotifyJoin" />

Testing

Test in Supervised Mode

{
"processKey": "LoanApprovalComplete",
"businessKey": "TEST-001",
"variables": { ... },
"executionMode": "Supervised"
}

Then use step-forward to verify each task executes correctly.

Test Different Risk Levels

Credit ScoreLoan AmountExpected RiskExpected Path
750+< $10,000LowAuto-Approve
680-720$25,000-$75,000MediumOfficer Review
620-680$100,000+HighManager Review
< 580AnyVery HighAuto-Reject

Next Steps