How to Build a compliance checking Agent Using LlamaIndex in TypeScript for wealth management
A compliance checking agent in wealth management reads client communications, proposed trades, suitability notes, and policy documents, then flags potential breaches before they hit production. It matters because the cost of a missed restriction is not just a bad trade — it can mean regulatory exposure, client harm, and an audit trail that does not hold up under review.
Architecture
- •Policy corpus
- •Store firm policies, product restrictions, KYC/AML rules, suitability standards, and jurisdiction-specific regulations in a retrievable index.
- •Document ingestion layer
- •Pull in emails, chat transcripts, investment proposals, meeting notes, and order tickets as structured text.
- •Compliance reasoning engine
- •Use LlamaIndex to retrieve relevant policy chunks and evaluate the client artifact against them.
- •Decision output schema
- •Return a strict JSON result with
status,violations,risk_level, andevidence.
- •Return a strict JSON result with
- •Audit logging
- •Persist prompts, retrieved chunks, model outputs, and timestamps for review by compliance officers.
- •Human review fallback
- •Route borderline cases to a compliance analyst instead of auto-approving them.
Implementation
1) Install LlamaIndex for TypeScript and define your data model
You want the agent to work on plain text artifacts first. In wealth management, that usually means a recommendation memo, an email thread, or a trade rationale.
npm install llamaindex
type ComplianceCheckInput = {
clientId: string;
jurisdiction: string;
documentText: string;
};
type ComplianceCheckResult = {
status: "pass" | "review" | "fail";
riskLevel: "low" | "medium" | "high";
violations: Array<{
ruleId: string;
description: string;
evidence: string;
}>;
};
2) Build a policy index with VectorStoreIndex
For compliance work, your policy corpus is the source of truth. Use Document, VectorStoreIndex, and a retriever so the agent only reasons over relevant policy sections.
import {
Document,
VectorStoreIndex,
Settings,
} from "llamaindex";
const policyDocs = [
new Document({
text: `
Rule WM-001: Do not recommend concentrated positions above 20% of portfolio value for retail clients.
Rule WM-002: Do not recommend illiquid private placements to clients without accredited status.
Rule WM-003: Any equity trade for restricted securities must be escalated to compliance.
`,
metadata: { source: "wealth_policy_manual", version: "2025.01" },
}),
new Document({
text: `
Rule WM-010: Suitability must consider risk tolerance, investment horizon, liquidity needs, and tax status.
Rule WM-011: Client communications must not promise guaranteed returns unless explicitly approved products are used.
`,
metadata: { source: "suitability_policy", version: "2025.01" },
}),
];
Settings.chunkSize = 512;
const index = await VectorStoreIndex.fromDocuments(policyDocs);
const retriever = index.asRetriever({ similarityTopK: 3 });
3) Retrieve policy context and run a structured compliance check
This is the core pattern. Retrieve only the applicable rules, then ask the LLM to classify the document against those rules using a strict output format.
import { OpenAI } from "llamaindex";
const llm = new OpenAI({
model: "gpt-4o-mini",
});
export async function checkCompliance(
input: ComplianceCheckInput
): Promise<ComplianceCheckResult> {
const query = `
Review this wealth management document for compliance issues in ${input.jurisdiction}.
Focus on suitability, concentration limits, restricted securities,
illiquid products, and misleading performance claims.
Document:
${input.documentText}
`;
const nodes = await retriever.retrieve(query);
const policyContext = nodes.map((n) => n.node.getContent()).join("\n\n");
const prompt = `
You are a compliance reviewer for a wealth management firm.
Use only the policy context below to assess the document.
Return valid JSON with:
{
"status": "pass" | "review" | "fail",
"riskLevel": "low" | "medium" | "high",
"violations": [
{
"ruleId": string,
"description": string,
"evidence": string
}
]
}
Policy context:
${policyContext}
Document:
${input.documentText}
`;
const response = await llm.complete({ prompt });
return JSON.parse(response.text) as ComplianceCheckResult;
}
4) Add an audit trail around every decision
Wealth management teams need traceability. Log what was checked, which policies were retrieved, and what the model returned.
export async function auditedComplianceCheck(input: ComplianceCheckInput) {
const startedAt = new Date().toISOString();
const result = await checkCompliance(input);
const auditRecord = {
clientId: input.clientId,
jurisdiction: input.jurisdiction,
startedAt,
checkedAt: new Date().toISOString(),
result,
documentHashHint: input.documentText.slice(0, 200),
reviewerType: result.status === "pass" ? "auto" : "human_required",
};
console.log(JSON.stringify(auditRecord));
return auditRecord;
}
Production Considerations
- •
Data residency
Keep client documents and policy indexes inside the required region. If your firm serves EU clients or cross-border accounts, make sure embeddings storage and model inference stay within approved jurisdictions.
- •
Monitoring
Track false positives, false negatives, escalation rate, and average retrieval latency. In wealth management, a noisy agent gets ignored; a quiet agent misses real breaches.
- •
Guardrails
Never let the agent auto-execute trades or send client-facing messages. Use it as a decision-support layer with hard approval gates for restricted securities, suitability exceptions, and concentration breaches.
- •
Auditability
Persist retrieved policy snippets alongside the final decision. During an exam or internal review, you need to show exactly which rule text informed the outcome.
Common Pitfalls
- •
Using generic RAG without firm-specific rules
- •A public finance model will miss internal restrictions like house lists or approved product shelves.
- •Fix it by indexing your own policies first and treating external regulations as secondary context.
- •
Letting the model free-form its answer
- •Unstructured output breaks downstream workflows and makes audits painful.
- •Fix it by forcing JSON output with fields like
status,riskLevel, andviolations.
- •
Ignoring jurisdiction boundaries
- •A rule valid for US retail clients may be wrong for UK discretionary mandates or offshore structures.
- •Fix it by passing jurisdiction into retrieval and keeping separate policy sets per region.
- •
Skipping human review on borderline cases
- •Suitability decisions often depend on nuanced context that models will miss.
- •Fix it by routing anything with missing KYC data, ambiguous language, or high-risk assets to compliance staff.
A good compliance agent does not replace judgment. It narrows the search space fast enough that your reviewers spend time on real exceptions instead of reading every memo line by line.
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