How to Build a loan approval Agent Using CrewAI in TypeScript for insurance
A loan approval agent for insurance automates the first pass on financing requests tied to policies, premiums, or broker-dealer arrangements. It reads applicant data, checks underwriting rules, flags compliance issues, and produces a decision package that an underwriter can approve, reject, or escalate.
Architecture
- •
Input adapter
- •Pulls loan application data from your CRM, policy admin system, or case management queue.
- •Normalizes fields like applicant identity, income, policy status, claim history, and requested amount.
- •
Policy/rules layer
- •Enforces insurance-specific constraints before any LLM reasoning.
- •Handles hard stops such as sanctions hits, missing consent, lapsed policy status, or prohibited jurisdictions.
- •
CrewAI crew
- •Coordinates specialized agents for risk review, compliance review, and final decision synthesis.
- •Produces a structured recommendation instead of free-form text.
- •
Audit trail store
- •Persists prompts, tool calls, intermediate outputs, and final decisions.
- •Needed for model governance, adverse action review, and regulator audits.
- •
Human review queue
- •Routes borderline cases to an underwriter.
- •Keeps the agent in assistive mode where regulations require human sign-off.
Implementation
1. Install CrewAI for TypeScript and define your decision schema
Use TypeScript types first. In lending workflows you want a strict output shape so downstream systems can validate the result without parsing prose.
// types.ts
export type LoanDecision = "approve" | "reject" | "escalate";
export interface LoanApplication {
applicationId: string;
applicantName: string;
applicantCountry: string;
annualIncome: number;
requestedAmount: number;
policyNumber?: string;
policyStatus?: "active" | "lapsed" | "cancelled";
consentToProcessData: boolean;
sanctionsHit: boolean;
}
export interface DecisionResult {
decision: LoanDecision;
riskScore: number; // 0-100
reasons: string[];
requiredActions: string[];
}
2. Create agents with explicit responsibilities
CrewAI works best when each agent has one job. For insurance lending, split compliance from risk so you can audit each reasoning path separately.
// crew.ts
import { Agent } from "@crew-ai/crewai";
import { ChatOpenAI } from "@langchain/openai";
const llm = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
});
export const complianceAgent = new Agent({
role: "Insurance Compliance Reviewer",
goal: "Check whether the loan application violates insurance compliance rules.",
backstory:
"You review insurance-linked lending applications for consent, sanctions, jurisdictional restrictions, and policy status.",
llm,
});
export const riskAgent = new Agent({
role: "Credit and Policy Risk Analyst",
goal: "Assess repayment risk using application facts and insurance context.",
backstory:
"You evaluate financial capacity alongside policy conditions and claim-related indicators.",
llm,
});
export const decisionAgent = new Agent({
role: "Loan Decision Synthesizer",
goal: "Combine compliance and risk findings into a structured recommendation.",
backstory:
"You produce a final underwriting recommendation for human review or automated routing.",
llm,
});
3. Add tasks with structured outputs and build the crew
Keep task descriptions concrete. The agent should not invent missing data; it should escalate when fields are absent or contradictory.
// workflow.ts
import { Crew } from "@crew-ai/crewai";
import { Task } from "@crew-ai/crewai";
import { complianceAgent, riskAgent, decisionAgent } from "./crew";
import type { LoanApplication } from "./types";
export function buildLoanApprovalCrew(application: LoanApplication) {
const complianceTask = new Task({
description: `
Review this insurance-linked loan application for compliance issues.
Rules:
- Reject if consentToProcessData is false.
- Reject if sanctionsHit is true.
- Escalate if policyStatus is lapsed or cancelled.
- Escalate if applicantCountry is outside approved jurisdictions.
Application:
${JSON.stringify(application)}
`,
agent: complianceAgent,
expectedOutput:
"A concise compliance summary with explicit pass/fail/escalate signals.",
outputJsonSchema: {
type: "object",
properties: {
status: { type: "string", enum: ["pass", "fail", "escalate"] },
reasons: { type: "array", items: { type: "string" } },
},
required: ["status", "reasons"],
additionalProperties: false,
},
});
const riskTask = new Task({
description: `
Assess repayment and portfolio risk for this application.
Consider income vs requestedAmount ratio, policy status stability, and any red flags from the application data.
Do not make legal/compliance determinations here.
`,
agent: riskAgent,
expectedOutput:
"A numeric risk assessment with reasons and recommended handling.",
outputJsonSchema: {
type: "object",
properties: {
riskScore: { type: "number" },
reasons: { type: "array", items: { type: "string" } },
},
required: ["riskScore", "reasons"],
additionalProperties: false,
},
context:[complianceTask],
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