How to Build a KYC verification Agent Using LlamaIndex in Python for retail banking

By Cyprian AaronsUpdated 2026-04-21
kyc-verificationllamaindexpythonretail-banking

A KYC verification agent checks customer identity documents, extracts key fields, compares them against policy and watchlist sources, and produces a decision with evidence. In retail banking, that matters because onboarding speed, fraud control, and regulatory compliance all depend on getting KYC right the first time.

Architecture

  • Document ingestion layer

    • Accepts passport scans, national IDs, utility bills, and selfie metadata.
    • Stores raw files in an approved object store with retention controls.
  • LlamaIndex document parsing layer

    • Uses SimpleDirectoryReader or direct Document objects for text inputs.
    • Converts OCR output into structured text chunks for downstream retrieval.
  • KYC knowledge index

    • Holds policy docs, jurisdiction rules, acceptable document lists, and escalation playbooks.
    • Built with VectorStoreIndex so the agent can retrieve bank-specific guidance.
  • Verification agent

    • Uses ReActAgent or a tool-enabled agent to reason over extracted facts.
    • Calls tools for document lookup, policy retrieval, and rule evaluation.
  • Decision and audit layer

    • Produces approve, reject, or manual_review.
    • Persists the prompt, retrieved context, tool calls, and final rationale for audit.
  • Controls layer

    • Enforces PII redaction, access control, data residency rules, and human override.

Implementation

1) Load KYC policy documents into a retrieval index

Start by indexing internal KYC policies. This gives the agent a grounded source of truth for country-specific requirements instead of relying on model memory.

from llama_index.core import SimpleDirectoryReader, VectorStoreIndex

# Internal policy docs:
# ./kyc_policies/
#   - onboarding_policy.md
#   - acceptable_documents_uk.md
#   - pep_escalation_rules.md

docs = SimpleDirectoryReader("./kyc_policies").load_data()
policy_index = VectorStoreIndex.from_documents(docs)
policy_retriever = policy_index.as_retriever(similarity_top_k=3)

2) Define tools for policy lookup and rule checks

The agent should not make compliance decisions from free-form chat alone. Wrap deterministic checks as tools so you can trace exactly what happened.

from typing import Literal
from llama_index.core.tools import FunctionTool

def check_document_type(doc_type: str) -> str:
    allowed = {"passport", "national_id", "drivers_license", "utility_bill"}
    return "allowed" if doc_type.lower() in allowed else "not_allowed"

def retrieve_policy(query: str) -> str:
    nodes = policy_retriever.retrieve(query)
    return "\n\n".join([node.node.get_content() for node in nodes])

document_type_tool = FunctionTool.from_defaults(fn=check_document_type)
policy_tool = FunctionTool.from_defaults(fn=retrieve_policy)

3) Build the verification agent with LlamaIndex

Use an agent that can reason over both tools. In production I prefer explicit tool use over a pure chat workflow because it gives better auditability.

from llama_index.core.agent import ReActAgent
from llama_index.llms.openai import OpenAI

llm = OpenAI(model="gpt-4o-mini", temperature=0)

agent = ReActAgent.from_tools(
    tools=[document_type_tool, policy_tool],
    llm=llm,
    verbose=True,
)

kyc_case = """
Customer submitted:
- document_type: passport
- country: Kenya
- address_proof: utility_bill
- name_match: partial
Task: determine whether this should be approved or sent to manual review.
"""

response = agent.chat(
    f"""
You are a retail banking KYC verification assistant.
Use only the provided tools and the supplied case details.
Return one of: approve, reject, manual_review.
Include short rationale and cite the policy basis when possible.

Case:
{kyc_case}
"""
)

print(response)

4) Add structured extraction before decisioning

For real onboarding flows you usually need structured fields before you can verify them. Use an extractor step upstream of the agent so your checks are deterministic.

import json
from pydantic import BaseModel
from llama_index.core.program import LLMTextCompletionProgram

class KYCExtract(BaseModel):
    customer_name: str
    document_type: str
    issuing_country: str
    address_proof_present: bool

extract_program = LLMTextCompletionProgram.from_defaults(
    output_cls=KYCExtract,
    prompt_template_str="""
Extract these fields from the following onboarding text:
{text}
"""
)

parsed = extract_program(text=kyc_case)
print(parsed.model_dump())

doc_check = check_document_type(parsed.document_type)
print({"doc_check": doc_check})

Production Considerations

  • Keep data residency explicit

    • Route EU customer data to EU-hosted infrastructure only.
    • Do not send raw identity documents to unmanaged external services.
  • Log every decision path

    • Persist retrieved policy chunks, tool outputs, model version, and final outcome.
    • This is what your auditors will ask for when a case is challenged.
  • Use human-in-the-loop thresholds

    • Auto-approve only low-risk cases with high-confidence field matches.
    • Send partial matches, expired documents, or watchlist hits to manual review.
  • Redact sensitive fields before prompts

    • Mask account numbers, national IDs, and full addresses unless they are required.
    • Keep prompt content minimal to reduce exposure under privacy rules.

Common Pitfalls

  1. Letting the model decide compliance from memory

    • Avoid this by grounding every decision in indexed policy docs and deterministic tools.
    • If it cannot cite a rule source, it should escalate to manual review.
  2. Skipping structured extraction

    • Free-text onboarding notes are not enough for reliable KYC checks.
    • Extract fields first with a schema like KYCExtract, then validate them explicitly.
  3. Ignoring auditability

    • If you cannot replay the decision path, you do not have a bank-ready system.
    • Store prompts, retrieved nodes, tool outputs, timestamps, and model identifiers per case.
  4. Mixing production data across regions

    • Cross-border movement of identity data creates legal risk fast.
    • Enforce region-specific storage and retrieval boundaries at the application layer.

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