How to Build a compliance checking Agent Using LlamaIndex in TypeScript for fintech
A compliance checking agent takes a policy, a customer interaction, or a transaction narrative and tells you whether it violates internal controls or regulatory rules. For fintech, this matters because the cost of missing a prohibited statement, an unsuitable recommendation, or a sanctions-related red flag is not just rework — it is audit findings, regulatory exposure, and broken trust.
Architecture
Build this agent with a narrow, auditable pipeline:
- •
Policy corpus
- •Internal compliance manuals, product disclosures, AML/KYC rules, marketing approval guidelines
- •Store as versioned documents with source metadata
- •
Document ingestion layer
- •Loads PDFs, markdown, HTML exports, and policy snippets into LlamaIndex
- •Preserves provenance: document name, section, version, jurisdiction
- •
Vector index
- •Powers retrieval over the policy corpus
- •Lets the agent cite the exact clauses used to make a decision
- •
Compliance reasoning engine
- •Takes the user input plus retrieved policy chunks
- •Produces a structured result: pass/fail/risk level/reason/citations
- •
Audit log store
- •Persists prompt, retrieved context IDs, model output, timestamps, and reviewer actions
- •Needed for model governance and regulatory review
- •
Guardrail layer
- •Blocks unsupported claims, PII leakage, and out-of-scope advice
- •Enforces deterministic output schema for downstream systems
Implementation
1. Install dependencies and load policy documents
Use LlamaIndex’s TypeScript package and keep your source documents cleanly separated by jurisdiction or product line.
npm install llamaindex dotenv
import "dotenv/config";
import { Document } from "llamaindex";
import { SimpleDirectoryReader } from "llamaindex";
async function loadPolicies() {
const reader = new SimpleDirectoryReader({
inputDir: "./policies",
recursive: true,
});
const docs = await reader.loadData();
return docs.map(
(doc) =>
new Document({
text: doc.text,
metadata: {
fileName: doc.metadata?.fileName,
jurisdiction: doc.metadata?.jurisdiction ?? "unknown",
version: doc.metadata?.version ?? "unknown",
sourceType: "policy",
},
})
);
}
2. Build the index over compliance content
For a compliance agent, retrieval quality matters more than raw generation quality. You want the model to answer from policy text, not memory.
import { VectorStoreIndex } from "llamaindex";
async function buildIndex() {
const documents = await loadPolicies();
const index = await VectorStoreIndex.fromDocuments(documents);
return index;
}
3. Query with an explicit compliance prompt and structured output
The key pattern is: retrieve relevant policy context first, then ask for a bounded judgment. In fintech workflows, keep the output machine-readable so your case management system can route it.
import { Settings } from "llamaindex";
import OpenAI from "openai";
async function runComplianceCheck(inputText: string) {
const index = await buildIndex();
const queryEngine = index.asQueryEngine({
similarityTopK: 4,
systemPrompt:
"You are a compliance checking agent for fintech. Use only the provided policy context. If the context is insufficient, say INSUFFICIENT_CONTEXT.",
});
const response = await queryEngine.query({
query:
`Review this content for compliance issues:\n\n${inputText}\n\n` +
`Return JSON with keys: decision (PASS|FAIL|REVIEW|INSUFFICIENT_CONTEXT), ` +
`riskLevel (LOW|MEDIUM|HIGH), reasons (array of strings), citations (array of strings).`,
});
console.log(String(response));
}
That gives you retrieval-backed analysis without letting the model wander into unsupported advice. In production you should validate the response against a JSON schema before acting on it.
4. Add audit logging around every decision
Fintech teams need to reconstruct why an item was flagged months later. Log input hashes, retrieved document IDs, model version, and final decision.
import crypto from "crypto";
import fs from "fs/promises";
function hashText(text: string) {
return crypto.createHash("sha256").update(text).digest("hex");
}
async function auditDecision(inputText: string, result: string) {
const record = {
timestamp: new Date().toISOString(),
inputHash: hashText(inputText),
result,
modelProvider: "openai",
workflow: "compliance-check",
};
await fs.appendFile("./audit-log.jsonl", JSON.stringify(record) + "\n");
}
Production Considerations
- •
Deploy in-region
- •Keep policy data and logs in approved regions to satisfy data residency requirements.
- •If you operate across jurisdictions, isolate indexes per region instead of mixing policies in one global store.
- •
Treat every decision as evidence
- •Store retrieved chunk IDs and document versions alongside outputs.
- •If legal asks why something was blocked, you need clause-level traceability.
- •
Add deterministic guardrails
- •Reject outputs that are not valid JSON.
- •Force
INSUFFICIENT_CONTEXTwhen retrieval confidence is weak instead of letting the model guess.
- •
Monitor drift and false positives
- •Track approval rate by product line and jurisdiction.
- •A spike in
REVIEWorFAILoften means stale policies or bad chunking before it means “better compliance.”
Common Pitfalls
- •
Mixing policies from different jurisdictions in one index
- •A UK retail banking rule can look similar to a US lending rule but mean something different.
- •Fix it by partitioning indexes by jurisdiction and product.
- •
Letting the model answer without citations
- •If the agent cannot point to the clause it used, your audit trail is weak.
- •Require citations from retrieved chunks and reject uncited decisions.
- •
Using free-form text outputs in downstream systems
- •Free-form responses break automation and create brittle review workflows.
- •Force a strict schema like
decision,riskLevel,reasons, andcitations, then validate before routing.
- •
Ignoring prompt injection inside uploaded documents
- •A malicious or malformed document can try to override instructions.
- •Strip unsafe instructions during ingestion and keep system prompts higher priority than document text.
A good compliance agent does not replace legal review. It reduces manual triage by turning policy lookup into a repeatable control point with retrieval evidence attached. In fintech that is what makes it useful: faster screening without losing traceability.
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