How to Build a loan approval Agent Using LlamaIndex in Python for retail banking
A loan approval agent helps a retail bank collect applicant data, retrieve policy and credit criteria, reason over the case, and produce a decision recommendation with an audit trail. It matters because loan ops teams need faster turnaround without losing control over compliance, explainability, and policy enforcement.
Architecture
- •
Applicant intake layer
- •Collects structured inputs like income, employment type, requested amount, existing obligations, and jurisdiction.
- •Normalizes fields before they hit the agent.
- •
Policy and underwriting knowledge base
- •Stores lending policy, product rules, exception handling, and regulatory notes.
- •Backed by
VectorStoreIndexso the agent can retrieve the right policy passages.
- •
Decisioning agent
- •Uses LlamaIndex
ReActAgentorFunctionCallingAgentWorkerto reason over retrieved context. - •Produces one of: approve, refer for manual review, or decline.
- •Uses LlamaIndex
- •
Risk scoring tools
- •Wraps deterministic checks such as debt-to-income ratio, minimum income thresholds, and affordability rules.
- •Keeps hard rules outside the LLM so decisions are consistent.
- •
Audit and evidence store
- •Persists inputs, retrieved chunks, tool calls, and final rationale.
- •Required for model governance, complaints handling, and internal audit.
- •
Guardrail layer
- •Blocks unsupported advice, PII leakage, and decisions that violate jurisdictional rules.
- •Enforces data residency and access constraints.
Implementation
- •Load lending policy into a retrievable index
Use SimpleDirectoryReader to load policy documents and build a VectorStoreIndex. In production, these documents should be the approved version of your lending policy, not ad hoc PDFs from a shared drive.
from llama_index.core import SimpleDirectoryReader, VectorStoreIndex
docs = SimpleDirectoryReader("./policy_docs").load_data()
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine(similarity_top_k=3)
response = query_engine.query(
"What is the maximum debt-to-income ratio for unsecured personal loans?"
)
print(response)
This gives the agent a controlled retrieval path into underwriting policy. For retail banking, keep this corpus versioned so every decision can be tied back to a specific policy release.
- •Add deterministic risk tools
Do not let the LLM calculate financial ratios from scratch if you can avoid it. Put those checks in Python functions and expose them through LlamaIndex tools.
from llama_index.core.tools import FunctionTool
def debt_to_income_ratio(monthly_debt_payments: float,
gross_monthly_income: float) -> float:
if gross_monthly_income <= 0:
raise ValueError("gross_monthly_income must be positive")
return round(monthly_debt_payments / gross_monthly_income, 4)
def affordability_flag(dti: float) -> str:
return "PASS" if dti <= 0.43 else "REVIEW"
dti_tool = FunctionTool.from_defaults(fn=debt_to_income_ratio)
affordability_tool = FunctionTool.from_defaults(fn=affordability_flag)
This pattern keeps hard underwriting logic auditable. If your bank changes the threshold from 43% to 40%, you update code or config instead of retraining anything.
- •Build an agent that retrieves policy and calls tools
Use ReActAgent when you want explicit tool use and traceable reasoning steps. Pair it with a system prompt that constrains behavior to recommendation only; final approval should still go through a business rule or human review gate.
from llama_index.core.agent import ReActAgent
from llama_index.core import Settings
Settings.chunk_size = 512
agent = ReActAgent.from_tools(
tools=[dti_tool, affordability_tool],
llm=Settings.llm,
verbose=True,
system_prompt=(
"You are a retail banking loan assessment assistant. "
"Use retrieved policy only. Do not invent rules. "
"Return a recommendation: APPROVE, REVIEW, or DECLINE."
),
)
case_summary = """
Applicant: salaried employee
Gross monthly income: 5000
Monthly debt payments: 1800
Requested amount: 12000
Jurisdiction: UK
"""
result = agent.chat(
f"{case_summary}\n"
f"Compute DTI using the tool if needed. "
f"Check whether this case meets policy."
)
print(result)
The important part is that the agent is not making free-form decisions in isolation. It is combining retrieved policy with deterministic checks so your audit team can reconstruct why it recommended a path.
- •Persist outputs for audit
For retail banking you need more than the final answer. Store the input payload, retrieved chunks, tool outputs, timestamp, model version, and policy version in your case management system or event store.
A practical pattern is to serialize:
- •applicant fields after masking sensitive values
- •top-k retrieved passages from
query_engine - •agent response text
- •tool call inputs/outputs
- •reviewer override if one occurs
That record becomes your evidence pack for complaints handling and model risk reviews.
Production Considerations
- •
Enforce compliance boundaries
- •Restrict the knowledge base to approved lending policies and jurisdiction-specific regulations.
- •Separate UK, EU, and US rule sets if product criteria differ by region.
- •
Keep PII out of prompts where possible
- •Mask account numbers, national IDs, and full addresses before sending data to the model.
- •Use tokenized customer identifiers so logs remain useful without exposing raw personal data.
- •
Control data residency
- •Host embeddings, vector stores, and inference in-region when regulation requires it.
- •Do not let retrieval cross borders unless legal review explicitly allows it.
- •
Monitor decision drift
- •Track approval rate by segment: income band, employment type, geography.
- •Alert on sudden shifts in REVIEW or DECLINE outcomes after prompt or policy changes.
Common Pitfalls
- •
Letting the model decide hard underwriting rules
- •Mistake: asking the LLM to infer thresholds from prose.
- •Fix: implement threshold checks as Python functions and expose them through
FunctionTool.
- •
Using unversioned policy documents
- •Mistake: indexing whatever PDF someone uploaded last week.
- •Fix: store approved policies with semantic versioning and attach that version to every decision record.
- •
Ignoring audit requirements
- •Mistake: keeping only the final recommendation.
- •Fix: persist retrieval context, tool calls, model version, prompt template hash, and human override status.
- •
Mixing jurisdictions in one prompt set
- •Mistake: one global prompt for all markets.
- •Fix: route cases by country or product line before retrieval so local regulation stays explicit.
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