How to Build a KYC verification Agent Using LlamaIndex in TypeScript for pension funds
A KYC verification agent for pension funds checks whether a member, beneficiary, or employer contact has the right identity documents, whether those documents match the policy rules, and whether anything needs human review. For pension funds, this matters because onboarding and benefit changes are compliance-heavy, audit-sensitive, and often tied to strict data residency and retention rules.
Architecture
A production KYC agent for pension funds usually needs these components:
- •
Document ingestion layer
- •Pulls PDFs, scans, ID images, proof-of-address files, and application forms from secure storage.
- •Normalizes them into text and metadata before indexing.
- •
LlamaIndex document index
- •Stores extracted KYC policy docs, internal SOPs, jurisdiction rules, and checklist templates.
- •Lets the agent retrieve the exact rule that applies to a case.
- •
Verification workflow
- •Takes a KYC case as input.
- •Compares submitted evidence against fund policy and returns pass/fail/escalate outcomes.
- •
Human review queue
- •Routes ambiguous cases to compliance staff.
- •Keeps an audit trail of model output and reviewer decisions.
- •
Audit and evidence store
- •Persists prompts, retrieved chunks, decisions, timestamps, and document hashes.
- •Required for regulator review and internal controls.
- •
Access control and residency controls
- •Ensures only approved staff can query sensitive member data.
- •Keeps processing inside approved regions where required.
Implementation
1. Install the TypeScript packages
Use the TypeScript LlamaIndex SDK plus a document loader. For this pattern, the agent retrieves pension-fund KYC policy snippets and uses them to verify a case.
npm install llamaindex dotenv
Set your API key in .env:
OPENAI_API_KEY=your_key_here
2. Load pension fund KYC policies into an index
You want your agent grounded in policy text, not free-form reasoning. Store your KYC handbook, AML rules, and jurisdiction notes as Document objects, then build a VectorStoreIndex.
import "dotenv/config";
import {
Document,
Settings,
VectorStoreIndex,
} from "llamaindex";
async function buildPolicyIndex() {
Settings.chunkSize = 1024;
Settings.chunkOverlap = 150;
const docs = [
new Document({
text: `
Pension Fund KYC Policy:
1. Verify government-issued ID.
2. Verify proof of address dated within 90 days.
3. Escalate if name mismatch exceeds minor spelling variance.
4. Reject if sanctions screening is unresolved.
5. Retain audit evidence for seven years.
`,
metadata: { source: "kyc-policy", jurisdiction: "ZA" },
}),
new Document({
text: `
Beneficiary Change Policy:
1. Require certified identity documents for beneficiaries.
2. Require trustee approval for high-value changes.
3. Route politically exposed persons to enhanced due diligence.
`,
metadata: { source: "beneficiary-policy", jurisdiction: "ZA" },
}),
];
return await VectorStoreIndex.fromDocuments(docs);
}
3. Create a retrieval-backed verification function
The key pattern is: retrieve relevant policy context first, then ask the LLM to classify the case using only that context. In pension operations, that keeps answers tied to written rules and makes audits easier.
import {
QueryEngineTool,
ReActAgent,
} from "llamaindex";
type KycCase = {
memberId: string;
fullName: string;
idType: string;
proofOfAddressDateDaysOld: number;
sanctionsClear: boolean;
};
async function createKycAgent() {
const index = await buildPolicyIndex();
const queryEngine = index.asQueryEngine({ similarityTopK: 3 });
const kycTool = QueryEngineTool.from(
queryEngine,
"kyc_policy_lookup",
"Use this tool to retrieve pension fund KYC policy rules."
);
return ReActAgent.fromTools([kycTool], {
systemPrompt: `
You are a KYC verification agent for a pension fund.
Only use retrieved policy context.
Return one of: PASS, FAIL, ESCALATE.
Always cite the rule summary used for the decision.
If sanctions are unresolved or evidence is incomplete, escalate or fail based on policy.
`,
verbose: false,
});
}
async function verifyCase(agent: ReturnType<typeof createKycAgent>, kycCase: KycCase) {
const prompt = `
Verify this pension fund KYC case:
Member ID: ${kycCase.memberId}
Name: ${kycCase.fullName}
ID Type: ${kycCase.idType}
Proof of Address Age (days): ${kycCase.proofOfAddressDateDaysOld}
Sanctions Clear: ${kycCase.sanctionsClear}
Decision required with short rationale.
`;
const result = await (await agent).chat({ message: prompt });
console.log(result.response);
}
(async () => {
const agent = await createKycAgent();
await verifyCase(agent, {
memberId: "PF-10293",
fullName: "Amina Dlamini",
idType: "National ID",
proofOfAddressDateDaysOld: 42,
sanctionsClear: true,
});
})();
4. Add structured outputs for downstream systems
For production you do not want prose-only output. Wrap the result in a schema so your case management system can route it cleanly.
type VerificationDecision = {
decision: "PASS" | "FAIL" | "ESCALATE";
};
function parseDecision(text: string): VerificationDecision {
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