How to Build a loan approval Agent Using LangGraph in TypeScript for retail banking
A loan approval agent in retail banking takes a loan application, gathers the missing facts, checks policy rules, scores risk, and returns a decision with an audit trail. The point is not to replace credit policy; it is to make the decisioning flow faster, consistent, and easier to review under compliance constraints.
Architecture
- •
Application intake node
- •Normalizes applicant data from web forms, CRM, or branch systems.
- •Validates required fields like income, employment type, requested amount, and consent flags.
- •
Document verification node
- •Checks whether pay slips, bank statements, and identity documents are present.
- •Routes incomplete cases to a human review queue instead of guessing.
- •
Policy and eligibility node
- •Applies hard rules such as minimum age, debt-to-income thresholds, residency status, and product-specific limits.
- •Produces deterministic pass/fail outcomes for compliance review.
- •
Risk scoring node
- •Calls an internal scoring service or model endpoint.
- •Converts model output into a bounded decision input, never a raw final approval.
- •
Decision node
- •Combines policy results, risk score, and exceptions into approve / decline / refer.
- •Writes structured reasons for audit and customer communication.
- •
Audit and trace node
- •Persists every state transition, rule result, and final decision.
- •Supports regulator requests, internal QA, and adverse action explanations.
Implementation
1) Define the graph state
Use a typed state object so every node reads and writes predictable fields. In retail banking, this matters because you need stable audit logs and deterministic behavior across releases.
import { Annotation } from "@langchain/langgraph";
export const LoanState = Annotation.Root({
application: Annotation<{
applicantId: string;
amount: number;
income: number;
monthlyDebt: number;
age: number;
residencyCountry: string;
consentGiven: boolean;
documentsReceived: boolean;
}>(),
policyResult: Annotation<{
eligible: boolean;
reasons: string[];
}>(),
riskScore: Annotation<number | null>(),
decision: Annotation<{
outcome: "approve" | "decline" | "refer";
reasons: string[];
}>(),
auditTrail: Annotation<string[]>({
default: () => [],
reducer: (left, right) => left.concat(right),
}),
});
2) Build the nodes
Keep policy checks deterministic. If you use an ML model for risk scoring, isolate it behind one node so it can be monitored and swapped without changing the rest of the graph.
import { StateGraph, START, END } from "@langchain/langgraph";
const intakeNode = async (state: typeof LoanState.State) => {
return {
auditTrail: [`intake_received:${state.application.applicantId}`],
};
};
const policyNode = async (state: typeof LoanState.State) => {
const app = state.application;
const reasons: string[] = [];
if (!app.consentGiven) reasons.push("missing_consent");
if (!app.documentsReceived) reasons.push("missing_documents");
if (app.age < 18) reasons.push("underage");
if (app.residencyCountry !== "ZA") reasons.push("unsupported_residency");
const dti = app.monthlyDebt / Math.max(app.income / 12, 1);
if (dti > 0.45) reasons.push("debt_to_income_too_high");
return {
policyResult: { eligible: reasons.length === 0, reasons },
auditTrail: [`policy_checked:${reasons.join(",") || "pass"}`],
};
};
const riskNode = async (_state: typeof LoanState.State) => {
// Replace with your internal scoring service call.
const score = Math.floor(Math.random() * 100);
return {
riskScore: score,
auditTrail: [`risk_scored:${score}`],
};
};
const decisionNode = async (state: typeof LoanState.State) => {
const policy = state.policyResult!;
const score = state.riskScore ?? 100;
const decisionNode2 = async (state: typeof LoanState.State) => {
};
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit