How to Build a claims processing Agent Using LlamaIndex in TypeScript for banking
A claims processing agent in banking takes a customer claim, pulls the right policy, transaction, and case data, then decides whether it can auto-resolve, needs more evidence, or must be escalated to a human reviewer. It matters because claims are high-volume, regulated workflows where speed is useful, but traceability, auditability, and policy adherence matter more.
Architecture
- •
Ingress API
- •Receives claim payloads from your banking app or case management system.
- •Validates identity, claim type, and required fields before any LLM call.
- •
Document retrieval layer
- •Uses LlamaIndex to index policy docs, product terms, dispute rules, and internal SOPs.
- •Keeps the agent grounded in approved bank-owned sources.
- •
Claim reasoning agent
- •Uses an LLM through LlamaIndex to classify the claim, extract missing fields, and draft a recommendation.
- •Must return structured output, not free-form prose.
- •
Decision policy engine
- •Applies bank rules for auto-approval thresholds, escalation triggers, and compliance checks.
- •Separates model output from final business action.
- •
Audit logger
- •Stores prompts, retrieved context IDs, model outputs, and final decisions.
- •Required for dispute handling and regulator review.
- •
Human review queue
- •Captures exceptions: low confidence, missing evidence, AML/KYC flags, or policy conflicts.
- •Keeps the agent assistive instead of fully autonomous.
Implementation
1) Install and wire up LlamaIndex
Use the TypeScript package with an OpenAI-compatible model provider. In banking systems, keep secrets in your vault and load them at runtime.
npm install llamaindex zod
import { OpenAI } from "llamaindex";
const llm = new OpenAI({
model: "gpt-4o-mini",
apiKey: process.env.OPENAI_API_KEY!,
});
2) Build a retrieval index over bank-approved claims documents
For claims processing, your corpus should include product terms, claims SOPs, chargeback rules, fraud handling guidance, and escalation criteria. Use VectorStoreIndex so the agent can cite relevant internal material instead of guessing.
import {
Document,
VectorStoreIndex,
} from "llamaindex";
const docs = [
new Document({
text: "A card-not-present dispute must be escalated if transaction evidence is incomplete or merchant response exceeds SLA.",
metadata: { source: "chargeback_policy_v3", region: "EU" },
}),
new Document({
text: "Claims under $250 with complete KYC and matching transaction metadata may be auto-reviewed for straight-through processing.",
metadata: { source: "claims_sop_v2", region: "EU" },
}),
];
const index = await VectorStoreIndex.fromDocuments(docs);
const retriever = index.asRetriever({ similarityTopK: 3 });
3) Define structured output for claim decisions
Do not let the model emit loose text. Use zod with asStructuredLLM patterns at the application boundary so you can validate fields before taking action.
import { z } from "zod";
import { QueryEngineTool } from "llamaindex";
const ClaimDecisionSchema = z.object({
status: z.enum(["approve", "reject", "escalate"]),
confidence: z.number().min(0).max(1),
reason: z.string(),
missingFields: z.array(z.string()),
});
const decisionTool = new QueryEngineTool({
queryEngine: index.asQueryEngine(),
metadata: {
name: "claims_policy_lookup",
description: "Retrieves approved banking policy context for claims decisions",
},
});
4) Run the agent with retrieval + policy checks
This pattern keeps retrieval separate from final decisioning. The LLM drafts a recommendation using retrieved context; your code enforces hard rules like residency restrictions and mandatory escalation conditions.
import {
ReActAgent,
} from "llamaindex";
const agent = new ReActAgent({
tools: [decisionTool],
llm,
});
type ClaimInput = {
claimId: string;
customerId: string;
amount: number;
region: string;
description: string;
};
export async function processClaim(input: ClaimInput) {
const prompt = `
You are a banking claims assistant.
Use only approved policy context from tools.
Return JSON with keys:
status | confidence | reason | missingFields
Claim:
${JSON.stringify(input)}
`;
const result = await agent.chat(prompt);
const rawText = typeof result.message === "string" ? result.message : result.message.content;
const parsed = ClaimDecisionSchema.safeParse(JSON.parse(rawText));
if (!parsed.success) {
return {
claimId: input.claimId,
status: "escalate",
reason: "Invalid model output; requires human review",
auditTag: "schema_validation_failed",
};
}
const decision = parsed.data;
if (input.region !== "EU") {
return {
claimId: input.claimId,
status: "escalate",
reason: "Data residency policy requires regional processing review",
auditTag: "residency_gate",
};
}
if (decision.status === "approve" && decision.confidence >= 0.85 && input.amount <= $250) {
return {
claimId: input.claimId,
status: "approve",
reason: decision.reason,
auditTag: "straight_through",
};
}
return {
claimId: input.claimId,
status: "escalate",
reason: decision.reason,
auditTag: "manual_review_required",
};
}
Production Considerations
- •
Deploy in-region
- •Keep document stores, vector indexes, logs, and inference endpoints inside the required banking jurisdiction.
- •If your bank has EU customers, do not route sensitive claim content through non-compliant regions.
- •
Log every decision path
- •Store claim ID, retrieved document IDs, prompt version, model version, output schema validation result, and final action.
- •That gives you a defensible audit trail when disputes or regulators ask why a claim was approved or escalated.
- •
Add hard guardrails outside the model
- •Enforce amount thresholds, sanctioned geography checks, KYC completeness checks, and fraud flags in code.
- •Never rely on the LLM to decide whether a regulated exception is allowed.
- •
Monitor drift and retrieval quality
- •Track escalation rate, invalid JSON rate, average confidence by claim type, and top retrieved sources.
- •If retrieval starts surfacing stale policies or irrelevant docs that’s an operational incident.
Common Pitfalls
- •
Letting the model make final business decisions
- •Bad pattern: “if the LLM says approve it.”
- •Fix it by treating the model as a recommender and applying deterministic bank rules in code after validation.
- •
Indexing uncontrolled documents
- •Bad pattern: ingesting email threads or outdated PDFs into the same knowledge base as approved policies.
- •Fix it by curating source documents and tagging them by version, region, and approval status before indexing.
- •
Skipping schema validation
- •Bad pattern: parsing raw model text directly into workflow actions.
- •Fix it with
zodvalidation and fail closed to human review when output is malformed or incomplete.
- •
Ignoring residency and audit requirements
- •Bad pattern: sending customer claims data to whatever endpoint is easiest.
- •Fix it by enforcing regional routing, redacting unnecessary PII before prompting where possible, and persisting immutable audit records for every run.
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