How to Build a claims processing Agent Using LangChain in TypeScript for lending
A claims processing agent for lending takes in borrower claims, supporting documents, and policy rules, then classifies the claim, extracts the relevant facts, checks them against lending policy, and routes the case for approval, denial, or human review. It matters because lending operations live or die on consistency: if two similar claims get different outcomes, you create compliance risk, customer friction, and audit pain.
Architecture
- •
Claim intake layer
- •Accepts structured payloads from your loan servicing system.
- •Normalizes fields like borrower ID, loan ID, claim type, amount, and incident date.
- •
Document extraction layer
- •Pulls text from PDFs, emails, and uploaded forms.
- •Uses an LLM to extract key facts into a typed schema.
- •
Policy reasoning layer
- •Compares extracted facts against lending rules.
- •Decides whether the claim is eligible, incomplete, suspicious, or ready for settlement.
- •
Decision orchestration layer
- •Routes low-risk claims to auto-resolution.
- •Sends edge cases to a human adjuster or compliance reviewer.
- •
Audit logging layer
- •Stores prompts, model outputs, policy decisions, and timestamps.
- •Keeps a traceable record for internal audit and regulatory review.
- •
Data boundary controls
- •Redacts PII where possible.
- •Keeps processing inside approved regions for data residency requirements.
Implementation
1) Define the claim schema and load the model
Use a strict schema so the agent returns predictable output. For lending workflows, that matters more than clever prompting.
import { z } from "zod";
import { ChatOpenAI } from "@langchain/openai";
const ClaimSchema = z.object({
claimId: z.string(),
loanId: z.string(),
borrowerId: z.string(),
claimType: z.enum(["hardship", "payment_dispute", "fraud", "insurance_gap"]),
claimedAmount: z.number().nonnegative(),
incidentDate: z.string(),
summary: z.string(),
});
const DecisionSchema = z.object({
decision: z.enum(["approve", "deny", "needs_review"]),
reason: z.string(),
missingFields: z.array(z.string()).default([]),
});
const model = new ChatOpenAI({
model: "gpt-4o-mini",
temperature: 0,
});
2) Build an extraction chain with withStructuredOutput
This is the cleanest pattern when you want the model to convert messy claim text into a typed object. It avoids free-form parsing logic later.
import { PromptTemplate } from "@langchain/core/prompts";
const extractionPrompt = PromptTemplate.fromTemplate(`
You are a claims intake assistant for a lending platform.
Extract the claim details from the text below.
Return only fields that match the schema.
Claim text:
{claimText}
`);
const extractionChain = extractionPrompt.pipe(
model.withStructuredOutput(ClaimSchema)
);
async function extractClaim(claimText: string) {
return extractionChain.invoke({ claimText });
}
3) Add policy evaluation with explicit rules
Do not ask the model to “decide” without guardrails. In lending, eligibility should be driven by deterministic checks first, then LLM judgment only for ambiguous cases.
function evaluatePolicy(claim: z.infer<typeof ClaimSchema>) {
const missingFields: string[] = [];
if (!claim.claimId) missingFields.push("claimId");
if (!claim.loanId) missingFields.push("loanId");
if (!claim.borrowerId) missingFields.push("borrowerId");
const amountLimit = claim.claimType === "fraud" ? 5000 : 2000;
if (missingFields.length > 0) {
return {
decision: "needs_review" as const,
reason: "Required fields are missing",
missingFields,
};
}
if (claim.claimedAmount > amountLimit) {
return {
decision: "needs_review" as const,
reason: `Claim amount exceeds auto-processing threshold of ${amountLimit}`,
missingFields: [],
};
}
return {
decision: "approve" as const,
reason: "Meets basic policy thresholds",
missingFields: [],
};
}
4) Orchestrate extraction + policy + final response
This is the actual agent pattern. The LLM handles structured extraction; your code handles business logic; the final step produces an auditable outcome.
export async function processClaim(claimText: string) {
const extracted = await extractClaim(claimText);
const policyResult = evaluatePolicy(extracted);
if (policyResult.decision === "needs_review") {
return {
status: "queued_for_human_review",
extracted,
policyResult,
};
}
return {
status: "auto_processed",
extracted,
policyResult,
};
}
If you need retrieval over loan policies or product terms, add createRetrievalChain with a vector store containing approved policy docs. Keep those documents versioned so every decision can be tied back to the exact rule set used at runtime.
Production Considerations
- •
Deploy in-region
- •If your lending stack has residency constraints, keep model calls and vector stores in the same jurisdiction.
- •Do not send borrower PII to unmanaged third-party endpoints.
- •
Log every decision path
- •Store input hashes, extracted fields, policy version, model version, and final disposition.
- •This is what makes audits survivable when someone asks why a claim was denied.
- •
Put hard guardrails around approvals
- •Never let an LLM directly approve high-value claims without deterministic thresholds.
- •Use human review for fraud indicators, legal disputes, and incomplete documentation.
- •
Monitor drift and exception rates
- •Track extraction accuracy by claim type.
- •Watch for spikes in
needs_review, which usually means upstream form changes or broken document ingestion.
Common Pitfalls
- •
Letting the model make final credit decisions
- •Fix this by separating extraction from adjudication.
- •The model can summarize facts; your rules engine should decide eligibility.
- •
Using untyped outputs
- •Free-form JSON parsing breaks fast in production.
- •Use
zodschemas withwithStructuredOutputso bad outputs fail early.
- •
Ignoring policy versioning
- •If your underwriting or claims rules change weekly and you do not version them, your audit trail becomes useless.
- •Persist
policyVersion,promptVersion, andmodelNamewith every transaction.
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