How to Build a compliance checking Agent Using LlamaIndex in Python for lending
A compliance checking agent for lending reviews loan applications, supporting documents, and policy text to flag potential violations before a human underwriter makes a decision. It matters because lending teams need fast decisions without losing control over fair lending rules, adverse action requirements, data residency, and auditability.
Architecture
- •
Document ingestion layer
- •Pulls in policy PDFs, lending playbooks, underwriting guidelines, and regulatory references.
- •Uses
SimpleDirectoryReaderor a custom loader for controlled sources only.
- •
Index layer
- •Builds a searchable knowledge base from approved compliance documents.
- •Uses
VectorStoreIndexwith embeddings for semantic retrieval.
- •
Compliance reasoning layer
- •Answers questions like “Does this loan file violate DTI limits?” or “Is an adverse action reason required?”
- •Uses
QueryEngineplus a structured prompt that forces citations from source docs.
- •
Decision orchestration layer
- •Wraps retrieval, rule checks, and output formatting into one agent workflow.
- •Can be built with
QueryEngineTooland an agent runner if you need multi-step reasoning.
- •
Audit logging layer
- •Stores the question, retrieved chunks, model answer, and source document IDs.
- •Critical for examiner review and internal model governance.
- •
Security and residency controls
- •Keeps PII inside approved regions and enforces access controls on indexed data.
- •Important for lending data subject to privacy and jurisdictional constraints.
Implementation
1) Load only approved compliance documents
Start with a controlled document set: lending policy manuals, state-specific overlays, ECOA/FCRA guidance, and internal underwriting rules. Do not dump raw customer files into the index without redaction and access controls.
from llama_index.core import SimpleDirectoryReader
docs = SimpleDirectoryReader(
input_dir="./compliance_docs",
required_exts=[".pdf", ".txt", ".md"],
recursive=True
).load_data()
print(f"Loaded {len(docs)} documents")
2) Build a vector index for policy retrieval
Use VectorStoreIndex so the agent can retrieve the exact policy passages that support its answer. For lending compliance, this is better than relying on generation alone because you need traceable citations.
from llama_index.core import VectorStoreIndex
index = VectorStoreIndex.from_documents(
docs,
show_progress=True
)
query_engine = index.as_query_engine(
similarity_top_k=4,
response_mode="compact"
)
3) Ask compliance questions with source-backed answers
The key pattern is: retrieve first, then answer with citations. In production, your prompt should force the model to say whether it found enough evidence in the policy corpus and to avoid guessing when the rule is unclear.
question = """
For a mortgage application with DTI of 48% and no compensating factors,
does our policy allow approval? Cite the relevant policy language.
"""
response = query_engine.query(question)
print("ANSWER:")
print(response.response)
print("\nSOURCES:")
for source in response.source_nodes:
print("-" * 80)
print(source.node.metadata)
print(source.node.get_content()[:500])
This pattern gives you three things lenders care about:
- •A direct answer
- •The exact policy text used
- •Metadata you can log for audit trails
If you want a more explicit tool-based workflow, wrap the query engine as a tool and place it behind an agent. That is useful when the agent must check multiple policies or route between state overlays and product-specific guidelines.
from llama_index.core.tools import QueryEngineTool, ToolMetadata
from llama_index.core.agent import ReActAgent
compliance_tool = QueryEngineTool(
query_engine=query_engine,
metadata=ToolMetadata(
name="lending_compliance_search",
description="Search approved lending compliance documents for underwriting and regulatory rules."
)
)
agent = ReActAgent.from_tools(
[compliance_tool],
verbose=True
)
result = agent.chat(
"Check whether approving this borrower with no adverse action notice would violate our process."
)
print(result)
4) Add structured output for downstream workflowing
For lending ops teams, free-form text is not enough. You usually want a machine-readable result that says whether there is a violation, what rule applies, and whether human review is required. Use your own post-processing layer to normalize the answer into JSON before sending it to case management.
Production Considerations
- •
Keep policy sources versioned
- •Store every indexed document with effective date, jurisdiction, product type, and version ID.
- •When regulators ask why a decision was made, you need to show the exact policy version in force at that time.
- •
Log every retrieval step
- •Persist user question, retrieved node IDs, scores, final answer, model version, and timestamp.
- •This is non-negotiable for auditability in lending workflows.
- •
Put guardrails around PII
- •Redact SSNs, bank account numbers, tax IDs, and other sensitive fields before indexing.
- •If customer data must be processed, keep it in-region and behind strict role-based access controls.
- •
Fail closed on uncertainty
- •If the model cannot find supporting policy text, return “needs human review” instead of inventing an answer.
- •That reduces fair lending risk and prevents overconfident bad decisions.
Common Pitfalls
- •
Indexing raw borrower files without redaction
- •This creates privacy exposure and can violate internal data handling rules.
- •Fix it by preprocessing documents to remove or tokenize PII before calling
load_data().
- •
Using the LLM as if it knows your policies
- •General model knowledge is not enough for lender-specific rules like debt-to-income thresholds or state overlays.
- •Fix it by grounding every answer in retrieved policy text from
VectorStoreIndex.
- •
Skipping audit metadata
- •If you do not store source document IDs and timestamps, your compliance team cannot reconstruct why an answer was produced.
- •Fix it by persisting
response.source_nodes, document metadata fields, and model configuration for every decision.
- •
Letting the agent decide outside its scope
- •A compliance checker should flag issues, not approve loans on its own.
- •Fix it by constraining outputs to “pass,” “flag,” or “needs review,” then route final decisions to an underwriter or rules engine.
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