How to Build a loan approval Agent Using LangChain in TypeScript for retail banking
A loan approval agent helps retail banking teams collect applicant data, check policy rules, summarize risk signals, and produce a recommendation with a traceable rationale. It matters because loan decisions need to be fast, consistent, auditable, and compliant with internal credit policy and regulatory requirements.
Architecture
- •
Applicant intake layer
- •Accepts structured inputs like income, employment status, debt obligations, requested amount, and product type.
- •Normalizes missing fields and rejects incomplete applications before the LLM sees them.
- •
Policy retrieval layer
- •Pulls the bank’s underwriting rules, product eligibility criteria, and exception policies from a controlled knowledge base.
- •Keeps the agent aligned with current policy instead of model memory.
- •
Decision engine
- •Uses LangChain to classify the application as
approve,refer, ordecline. - •Produces a short explanation tied to policy and input data.
- •Uses LangChain to classify the application as
- •
Audit trail store
- •Persists every prompt, retrieved policy snippet, model output, and final decision.
- •Supports internal audit, model risk review, and dispute handling.
- •
Guardrail layer
- •Blocks unsupported advice, PII leakage, and decisions outside delegated authority.
- •Forces structured output so downstream systems can validate it.
- •
Integration layer
- •Sends the decision to LOS/CRM/core banking systems through an API.
- •Emits events for human review when the case needs manual underwriting.
Implementation
1. Install dependencies and define the decision schema
Use LangChain’s structured output pattern so the agent returns machine-readable decisions instead of free text. For banking workflows, that is non-negotiable.
npm install @langchain/openai @langchain/core zod
import { z } from "zod";
export const LoanDecisionSchema = z.object({
decision: z.enum(["approve", "refer", "decline"]),
confidence: z.number().min(0).max(1),
reasons: z.array(z.string()).min(1),
policyReferences: z.array(z.string()).default([]),
});
export type LoanDecision = z.infer<typeof LoanDecisionSchema>;
export interface LoanApplication {
applicantId: string;
annualIncome: number;
monthlyDebtPayments: number;
requestedAmount: number;
employmentStatus: "employed" | "self_employed" | "unemployed";
creditScore?: number;
}
2. Build a retriever-backed prompt with policy context
For retail banking, keep underwriting rules in a controlled document store. The agent should retrieve only the relevant policy excerpts for the specific product and jurisdiction.
import { ChatOpenAI } from "@langchain/openai";
import { PromptTemplate } from "@langchain/core/prompts";
import { StructuredOutputParser } from "@langchain/core/output_parsers";
import { RunnableSequence } from "@langchain/core/runnables";
import { LoanDecisionSchema, LoanApplication } from "./schema";
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
});
const parser = StructuredOutputParser.fromZodSchema(LoanDecisionSchema);
const prompt = PromptTemplate.fromTemplate(`
You are a retail banking loan underwriting assistant.
Use only the provided application data and policy context.
Do not invent missing facts.
If key information is missing or ambiguous, return "refer".
Application:
{application}
Policy context:
{policyContext}
Return your answer in the required structured format.
{formatInstructions}
`);
async function retrievePolicyContext(app: LoanApplication): Promise<string> {
// Replace with your vector store / document store retrieval
if (app.requestedAmount > 25000) {
return "Personal loans above $25,000 require manual review. Debt-to-income ratio must be below 40%.";
}
return "Standard personal loan policy: DTI below 45%, minimum credit score of 620 for auto-decision.";
}
3. Compose the LangChain runnable pipeline
This is the core pattern. Use RunnableSequence to keep preprocessing, retrieval, prompting, and parsing explicit. That makes audits easier than hiding everything inside one opaque chain.
type Input = LoanApplication;
const loanApprovalChain = RunnableSequence.from([
async (input: Input) => {
const policyContext = await retrievePolicyContext(input);
const dti =
input.monthlyDebtPayments / (input.annualIncome / 12);
return {
application: JSON.stringify({ ...input, debtToIncomeRatio: dti.toFixed(2) }, null, 2),
policyContext,
formatInstructions: parser.getFormatInstructions(),
};
},
prompt,
llm,
]);
export async function decideLoan(app: LoanApplication) {
const raw = await loanApprovalChain.invoke(app);
const parsed = await parser.parse(raw.content as string);
return parsed;
}
4. Add deterministic pre-checks before calling the model
Do not ask the LLM to do basic eligibility math if you can calculate it yourself. Banks need deterministic controls for hard rules like missing fields or impossible values.
export function validateApplication(app: LoanApplication): string[] {
const errors: string[] = [];
if (!app.applicantId) errors.push("Missing applicantId");
if (app.annualIncome <= 0) errors.push("annualIncome must be positive");
if (app.monthlyDebtPayments < 0) errors.push("monthlyDebtPayments cannot be negative");
if (app.requestedAmount <= 0) errors.push("requestedAmount must be positive");
if (errors.length > 0) return errors;
return [];
}
Then wire it into your service:
export async function handleLoanDecision(app: LoanApplication) {
const validationErrors = validateApplication(app);
if (validationErrors.length > len) {
return {
decision: "refer",
confidence: .99,
reasons: validationErrors,
policyReferences: ["Pre-check validation"],
};
}
return decideLoan(app);
}
Production Considerations
- •
Auditability
- •Store every input payload, retrieved policy fragment, final output, model version, and timestamp.
- •Keep immutable logs for model risk management and customer dispute resolution.
- •
Data residency
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