How to Integrate LlamaIndex for retail banking with Supabase for production AI
Retail banking agents need two things that usually live in separate systems: a retrieval layer that can reason over policy, product, and customer context, and a durable data store for conversation state, audit trails, and operational metadata. LlamaIndex gives you the retrieval and orchestration layer; Supabase gives you Postgres-backed persistence with auth and simple APIs. Combined, they let you build production AI assistants that answer banking questions, route cases, and keep a traceable record of every interaction.
Prerequisites
- •Python 3.10+
- •A Supabase project with:
- •
SUPABASE_URL - •
SUPABASE_SERVICE_ROLE_KEYfor server-side writes
- •
- •A LlamaIndex environment set up with:
- •
OPENAI_API_KEYor another supported LLM embedding/LLM provider
- •
- •Installed packages:
- •
llama-index - •
supabase - •
python-dotenv
- •
- •A Postgres table in Supabase for chat/session storage
- •Retail banking documents ready to index:
- •product FAQs
- •fee schedules
- •KYC/AML policy docs
- •dispute handling playbooks
Install dependencies:
pip install llama-index supabase python-dotenv
Integration Steps
- •Create the Supabase client
Use Supabase as the system of record for session state, retrieved answers, and audit events. In production, keep the service role key on the backend only.
import os
from dotenv import load_dotenv
from supabase import create_client, Client
load_dotenv()
SUPABASE_URL = os.getenv("SUPABASE_URL")
SUPABASE_SERVICE_ROLE_KEY = os.getenv("SUPABASE_SERVICE_ROLE_KEY")
supabase: Client = create_client(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY)
# quick sanity check
print(supabase.table("banking_sessions").select("*").limit(1).execute())
- •Load retail banking documents into LlamaIndex
For banking use cases, your documents are usually policy PDFs, internal knowledge base pages, or approved customer-facing scripts. LlamaIndex can ingest them into a vector index for retrieval.
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
# Example: local folder containing approved retail banking docs
documents = SimpleDirectoryReader("./banking_docs").load_data()
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine(similarity_top_k=3)
response = query_engine.query(
"What is the process for disputing an unauthorized debit card transaction?"
)
print(response)
If your retail banking content changes often, rebuild or incrementally update the index on a schedule. Don’t treat policy docs like static code.
- •Persist user sessions and agent traces in Supabase
Store each user turn so your agent has continuity across requests. This is where Supabase fits cleanly: it handles durable state while LlamaIndex handles retrieval and response generation.
from datetime import datetime
def save_turn(session_id: str, user_message: str, assistant_message: str):
payload = {
"session_id": session_id,
"user_message": user_message,
"assistant_message": assistant_message,
"created_at": datetime.utcnow().isoformat()
}
result = supabase.table("banking_sessions").insert(payload).execute()
return result
session_id = "sess_001"
user_message = "Can I reverse a wire transfer?"
assistant_message = str(query_engine.query(user_message))
result = save_turn(session_id, user_message, assistant_message)
print(result)
A simple table schema works fine:
create table banking_sessions (
id bigserial primary key,
session_id text not null,
user_message text not null,
assistant_message text not null,
created_at timestamptz default now()
);
- •Combine retrieval with stored context
In production AI systems, you rarely answer from one prompt alone. Pull recent history from Supabase, prepend it to the current question, then query LlamaIndex with that context.
def get_recent_turns(session_id: str):
result = (
supabase.table("banking_sessions")
.select("user_message,assistant_message")
.eq("session_id", session_id)
.order("created_at", desc=True)
.limit(5)
.execute()
)
return result.data[::-1]
def build_context(session_id: str) -> str:
turns = get_recent_turns(session_id)
context_lines = []
for turn in turns:
context_lines.append(f"User: {turn['user_message']}")
context_lines.append(f"Assistant: {turn['assistant_message']}")
return "\n".join(context_lines)
session_context = build_context(session_id)
prompt = f"""
Conversation history:
{session_context}
Current question:
What documents are required to open a joint savings account?
"""
answer = query_engine.query(prompt)
print(answer)
This pattern keeps the agent grounded in both policy knowledge and conversation state.
- •Write retrieval results back to Supabase for auditability
Banking teams care about traceability. Store the final answer plus metadata like source snippets or confidence signals so compliance teams can review outputs later.
def save_audit_event(session_id: str, question: str, answer: str):
payload = {
"session_id": session_id,
"question": question,
"answer": answer,
}
return supabase.table("banking_audit_log").insert(payload).execute()
question = "How do I escalate a suspicious account takeover case?"
answer_text = str(query_engine.query(question))
audit_result = save_audit_event(session_id, question, answer_text)
print(audit_result)
For stricter controls, add columns for document_sources, model_name, retrieval_score, and review_status.
Testing the Integration
Run a basic end-to-end test that queries LlamaIndex and persists the result to Supabase.
test_session_id = "test_session_123"
test_question = "What is the overdraft fee policy for retail checking accounts?"
test_answer = str(query_engine.query(test_question))
save_result = save_turn(test_session_id, test_question, test_answer)
print("ANSWER:", test_answer)
print("SAVED:", save_result.data[0]["session_id"])
Expected output:
ANSWER: [A concise answer based on your indexed retail banking documents]
SAVED: test_session_123
If this fails:
- •verify your
.envvalues are loaded correctly - •confirm your Supabase table names match the code
- •check that your banking docs are actually being loaded into the index
Real-World Use Cases
- •
Customer support agent
Answer questions about fees, card replacement, transfer limits, branch requirements, and dispute workflows using indexed bank policy docs. - •
Compliance-aware case assistant
Retrieve KYC/AML procedures from LlamaIndex and store every interaction in Supabase for audit review and escalation tracking. - •
Branch operations copilot
Help staff resolve account-opening issues by combining current session context from Supabase with approved internal SOPs indexed in LlamaIndex.
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