How to Build a compliance checking Agent Using LlamaIndex in TypeScript for lending

By Cyprian AaronsUpdated 2026-04-21
compliance-checkingllamaindextypescriptlending

A compliance checking agent for lending reviews loan applications, supporting documents, and policy rules before a human underwriter makes a decision. Its job is to flag missing disclosures, inconsistent borrower data, prohibited terms, and policy violations early enough to reduce regulatory risk and manual review time.

Architecture

  • Document ingestion layer

    • Pulls loan applications, income proofs, bank statements, KYC docs, and policy manuals from approved sources.
    • Normalizes PDFs, text, and structured JSON into LlamaIndex Document objects.
  • Compliance knowledge index

    • Stores lending policy text, regulatory guidance, product rules, and internal SOPs.
    • Uses VectorStoreIndex for semantic retrieval over policy language.
  • Rule evaluation layer

    • Applies deterministic checks for hard requirements like minimum disclosures, DTI thresholds, or jurisdiction-specific constraints.
    • Keeps non-negotiable lending rules out of the model’s interpretation path.
  • Agent orchestration layer

    • Uses LlamaIndex tools plus an OpenAI LLM to inspect application context and call retrieval/query tools.
    • Produces structured findings with reasons and citations.
  • Audit and evidence store

    • Persists every decision input, retrieved passage, model output, and rule hit.
    • Supports regulator review and internal QA.

Implementation

1) Index lending policies with LlamaIndex

Start by loading your lending policy documents into a VectorStoreIndex. Keep policy content separate from applicant PII so you can control access and residency more easily.

import { Document } from "llamaindex";
import { VectorStoreIndex } from "llamaindex";

async function buildPolicyIndex() {
  const docs = [
    new Document({
      text: `
        Personal Loan Policy v3:
        - Minimum credit score: 680
        - Maximum debt-to-income ratio: 40%
        - Income must be verified with recent payslips or bank statements
        - Adverse action notices required when declining applications
      `,
      metadata: { source: "policy/personal-loan-v3", jurisdiction: "US" },
    }),
    new Document({
      text: `
        Mortgage Policy:
        - Verify employment history for at least 24 months
        - Require property valuation before approval
        - Escalate any inconsistent address history
      `,
      metadata: { source: "policy/mortgage", jurisdiction: "US" },
    }),
  ];

  return await VectorStoreIndex.fromDocuments(docs);
}

This gives you a searchable compliance corpus. In lending, the important part is not just retrieval quality; it is traceability back to the exact policy version used during review.

2) Add deterministic checks for hard lending rules

Do not ask the LLM to decide whether a DTI limit is breached. Compute that yourself. Use the model only for interpretation, explanation, and exception spotting.

type LoanApplication = {
  applicantId: string;
  requestedAmount: number;
  monthlyIncome: number;
  monthlyDebtPayments: number;
  creditScore: number;
};

function evaluateHardRules(app: LoanApplication) {
  const dti = app.monthlyDebtPayments / app.monthlyIncome;

  const findings = [];
  if (app.creditScore < 680) {
    findings.push({ rule: "min_credit_score", status: "fail", value: app.creditScore });
  }
  if (dti > 0.4) {
    findings.push({ rule: "max_dti", status: "fail", value: dti });
  }

  return {
    dti,
    findings,
    passed: findings.length === 0,
  };
}

This pattern matters because regulators care about consistent application of underwriting rules. If the rule is numeric or binary, keep it outside the model.

3) Wire retrieval plus an agent for explanation and exception review

Use QueryEngineTool with an index-backed query engine so the agent can cite policy passages when explaining a finding. Then combine that with an LLM-powered agent built through ReActAgent.

import {
  OpenAI,
  QueryEngineTool,
  ToolMetadata,
  ReActAgent,
} from "llamaindex";

async function createComplianceAgent(index: VectorStoreIndex) {
  const queryEngine = index.asQueryEngine();

  const policyTool = new QueryEngineTool({
    queryEngine,
    metadata: new ToolMetadata({
      name: "lending_policy_lookup",
      description:
        "Look up internal lending policy language for compliance questions.",
    }),
  });

  const llm = new OpenAI({
    model: "gpt-4o-mini",
    temperature: 0,
    apiKey: process.env.OPENAI_API_KEY,
  });

  return ReActAgent.fromTools({
    tools: [policyTool],
    llm,
    systemPrompt:
      "You are a lending compliance reviewer. Cite policy evidence. Do not invent rules. Distinguish hard failures from review items.",
  });
}

async function runReview() {
  const index = await buildPolicyIndex();
  

Keep learning

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

Related Guides