How to Integrate LlamaIndex for wealth management with Supabase for production AI
Why this integration matters
Wealth management agents need two things to be useful in production: grounded financial context and durable state. LlamaIndex gives you retrieval over portfolio notes, policy docs, research, and client records; Supabase gives you Postgres-backed storage, auth, and a clean way to persist chat history, embeddings metadata, and audit trails.
Put them together and you can build an AI agent that answers advisor questions with the right documents, remembers client context across sessions, and stores every interaction in a database you can query and govern.
Prerequisites
- •Python 3.10+
- •A Supabase project with:
- •
SUPABASE_URL - •
SUPABASE_SERVICE_ROLE_KEY
- •
- •A Postgres table for chat/session state
- •OpenAI or another LLM provider configured for LlamaIndex
- •LlamaIndex installed with the core packages you need:
- •
llama-index - •
llama-index-embeddings-openai - •
llama-index-llms-openai
- •
- •Supabase Python client:
- •
supabase-py
- •
- •Your wealth management documents ready as PDFs, markdown, or text
- •Optional but recommended:
- •pgvector enabled in Supabase if you want vector search inside Postgres
Integration Steps
- •Set up Supabase as your persistence layer.
Start by creating a client and a simple table for conversations or agent runs. In production, I keep this separate from vector storage so I can lock down access patterns cleanly.
import os
from supabase import create_client, Client
SUPABASE_URL = os.environ["SUPABASE_URL"]
SUPABASE_SERVICE_ROLE_KEY = os.environ["SUPABASE_SERVICE_ROLE_KEY"]
supabase: Client = create_client(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY)
# Example: store conversation metadata
response = supabase.table("wealth_agent_sessions").insert({
"session_id": "client_123",
"advisor_id": "advisor_42",
"status": "active"
}).execute()
print(response.data)
- •Configure LlamaIndex for wealth management retrieval.
Use LlamaIndex to load your client policy docs, investment memos, or product sheets. For wealth management use cases, keep the source set narrow and well-tagged so responses stay grounded.
import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
Settings.llm = OpenAI(model="gpt-4o-mini", api_key=os.environ["OPENAI_API_KEY"])
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small", api_key=os.environ["OPENAI_API_KEY"])
docs = SimpleDirectoryReader("./wealth_docs").load_data()
index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine(similarity_top_k=3)
result = query_engine.query("What is our risk tolerance policy for high-net-worth clients?")
print(result)
- •Persist agent outputs and citations in Supabase.
The key production pattern is to store both the answer and the source references. That gives you auditability when an advisor asks why the agent recommended a specific allocation or compliance note.
query_text = "Summarize the client's portfolio concentration risk."
response = query_engine.query(query_text)
citations = []
for node in getattr(response, "source_nodes", []):
citations.append({
"file_name": node.node.metadata.get("file_name"),
"score": float(node.score) if node.score is not None else None,
})
supabase.table("wealth_agent_answers").insert({
"session_id": "client_123",
"question": query_text,
"answer": str(response),
"citations": citations
}).execute()
- •Use Supabase to fetch client context before querying LlamaIndex.
This is where the integration becomes useful in an agent loop. Pull structured client data from Postgres first, then pass it into your retrieval prompt so the answer reflects current account state.
client_ctx = supabase.table("client_profiles") \
.select("client_id,name,risk_profile,aum,target_allocation") \
.eq("client_id", "client_123") \
.single() \
.execute()
profile = client_ctx.data
prompt = f"""
Client name: {profile['name']}
Risk profile: {profile['risk_profile']}
AUM: {profile['aum']}
Target allocation: {profile['target_allocation']}
Question: Should we rebalance based on current concentration risk?
"""
rebalance_answer = query_engine.query(prompt)
print(rebalance_answer)
- •Add a lightweight service layer for production requests.
Don’t wire your app directly from UI to database to index. Put a small Python service in front so you can validate inputs, enforce auth rules, log latency, and handle retries cleanly.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class WealthQuery(BaseModel):
session_id: str
question: str
@app.post("/agent/query")
def agent_query(payload: WealthQuery):
ctx = supabase.table("client_profiles") \
.select("*") \
.eq("client_id", payload.session_id) \
.single() \
.execute().data
enriched_prompt = f"""
Client context:
{ctx}
Question:
{payload.question}
"""
answer = query_engine.query(enriched_prompt)
supabase.table("wealth_agent_answers").insert({
"session_id": payload.session_id,
"question": payload.question,
"answer": str(answer)
}).execute()
return {"answer": str(answer)}
Testing the Integration
Run one end-to-end check: fetch context from Supabase, query LlamaIndex, then write the result back to Postgres.
test_session_id = "client_123"
ctx = supabase.table("client_profiles") \
.select("*") \
.eq("client_id", test_session_id) \
.single() \
.execute().data
test_question = f"Given this profile {ctx}, what are the key portfolio risks?"
test_answer = query_engine.query(test_question)
write_result = supabase.table("wealth_agent_answers").insert({
"session_id": test_session_id,
"question": test_question,
"answer": str(test_answer)
}).execute()
print("Context loaded:", ctx["name"])
print("Answer snippet:", str(test_answer)[:200])
print("Rows written:", len(write_result.data))
Expected output:
Context loaded: Jane Doe
Answer snippet: The main portfolio risks are concentration in tech equities...
Rows written: 1
Real-World Use Cases
- •Advisor copilot that answers questions like “What changed in this client’s risk profile since last review?” using LlamaIndex retrieval plus Supabase-stored profile data.
- •Compliance assistant that checks recommendations against policy docs and stores every response with citations for audit.
- •Client servicing bot that remembers prior interactions per household and pulls current holdings before generating a response.
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