How to Build a loan approval Agent Using CrewAI in TypeScript for pension funds
A loan approval agent for pension funds takes a borrower’s application, checks it against policy, validates risk and compliance constraints, and produces a recommendation with an audit trail. For pension funds, this matters because lending decisions are not just about credit quality; they must also respect fiduciary duty, member protection rules, data residency, and strict approval governance.
Architecture
- •
Application intake service
- •Receives borrower data, loan purpose, collateral details, and required documents.
- •Normalizes input into a structured payload the agent can inspect.
- •
Policy retrieval layer
- •Pulls fund-specific lending rules, risk appetite limits, and jurisdiction constraints.
- •Keeps policy outside the prompt so compliance can change without code changes.
- •
CrewAI agent layer
- •Uses a small set of specialized agents:
- •Underwriter agent for credit and affordability analysis
- •Compliance agent for pension-fund rules and regulatory checks
- •Risk reviewer agent for concentration, tenor, and exposure analysis
- •Uses a small set of specialized agents:
- •
Tooling layer
- •Connects agents to internal systems:
- •Credit bureau lookup
- •KYC/AML status
- •Document verification
- •Portfolio exposure service
- •Connects agents to internal systems:
- •
Decision and audit store
- •Persists the recommendation, reasoning summary, tool outputs, timestamps, and policy version.
- •Required for internal audit and regulator review.
Implementation
1) Install dependencies and define your data model
Use the TypeScript CrewAI SDK plus a schema library for request validation. Keep the request contract explicit; pension fund workflows break when inputs are loosely typed.
npm install @crewai/typescript zod dotenv
import { z } from "zod";
export const LoanApplicationSchema = z.object({
applicantId: z.string(),
amount: z.number().positive(),
tenorMonths: z.number().int().positive(),
purpose: z.string(),
jurisdiction: z.string(),
annualIncome: z.number().nonnegative(),
existingDebtService: z.number().nonnegative(),
collateralValue: z.number().nonnegative().optional(),
kycStatus: z.enum(["verified", "pending", "failed"]),
amlStatus: z.enum(["clear", "review", "blocked"]),
});
export type LoanApplication = z.infer<typeof LoanApplicationSchema>;
2) Create tools for policy and risk checks
The agent should not guess policy. Give it tools that return deterministic facts from your internal systems.
import { Tool } from "@crewai/typescript";
export const getPolicyTool = new Tool({
name: "get_pension_fund_lending_policy",
description: "Fetches current lending policy by jurisdiction and product type.",
async execute(input: { jurisdiction: string }) {
// Replace with real policy service call
return {
maxTenorMonths: input.jurisdiction === "ZA" ? 60 : 48,
maxAmountMultipleOfIncome: 8,
requireKycVerified: true,
requireAmlClear: true,
prohibitedPurposes: ["speculation", "crypto_trading"],
dataResidency: input.jurisdiction === "ZA" ? "za" : "eu",
policyVersion: "2026.01",
};
},
});
export const getExposureTool = new Tool({
name: "get_portfolio_exposure",
description: "Returns current exposure by sector and borrower.",
async execute(input: { applicantId: string }) {
return {
currentExposureAmount: 125000,
concentrationLimitBreached: false,
};
},
});
3) Wire up CrewAI agents and tasks
Use separate agents for underwriting and compliance. That keeps prompts narrow and makes audits easier.
import { Agent, Task, Crew } from "@crewai/typescript";
import { getPolicyTool, getExposureTool } from "./tools";
import { LoanApplicationSchema } from "./schema";
const underwriter = new Agent({
role: "Senior Underwriter",
goal: "Assess affordability, repayment capacity, and collateral strength.",
backstory:
"You underwrite consumer and secured loans for regulated pension fund lending programs.",
});
const complianceOfficer = new Agent({
role: "Compliance Officer",
goal: "Check the application against pension fund policy and regulatory constraints.",
backstory:
"You enforce pension fund lending rules, data residency requirements, and auditability.",
});
underwriter.tools = [getExposureTool];
complianceOfficer.tools = [getPolicyTool];
export function buildLoanApprovalCrew(rawInput: unknown) {
const application = LoanApplicationSchema.parse(rawInput);
const underwritingTask = new Task({
description:
`Analyze this loan application for affordability and risk:\n${JSON.stringify(application)}`,
expectedOutput:
"A structured underwriting assessment with approve/reject recommendation.",
agent: underwriter,
});
const complianceTask = new Task({
description:
`Validate this loan application against pension fund policy:\n${JSON.stringify(application)}`,
expectedOutput:
"A compliance assessment with any rule breaches or approval conditions.",
agent: complianceOfficer,
context: [underwritingTask],
});
return new Crew({
agents: [underwriter, complianceOfficer],
tasks: [underwritingTask, complianceTask],
verbose: true,
process_type: "sequential",
});
}
4) Run the crew and persist an auditable decision
Do not let the agent directly approve money movement. Return a recommendation that a workflow engine or human approver can finalize.
import dotenv from "dotenv";
dotenv.config();
async function main() {
const crew = buildLoanApprovalCrew({
applicantId: "APP-10291",
amount: 250000,
tenorMonths: 48,
purpose: "home_improvement",
jurisdiction: "ZA",
annualIncome: 520000,
existingDebtService: 90000,
collateralValue": undefined,
kycStatus": "verified",
amlStatus": "clear"
}
``
---
## Keep learning
- [The complete AI Agents Roadmap](/blog/ai-agents-roadmap-2026) — my full 8-step breakdown
- [Free: The AI Agent Starter Kit](/starter-kit) — PDF checklist + starter code
- [Work with me](/contact) — I build AI for banks and insurance companies
*By Cyprian Aarons, AI Consultant at [Topiax](https://topiax.xyz).*
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