How to Integrate LlamaIndex for payments with Supabase for production AI

By Cyprian AaronsUpdated 2026-04-22
llamaindex-for-paymentssupabaseproduction-ai

Combining LlamaIndex for payments with Supabase gives you a clean path to build AI agents that can reason over payment data, persist state, and serve reliable responses in production. The pattern is simple: use LlamaIndex to orchestrate retrieval and agent logic, and use Supabase as the durable backend for transaction metadata, user state, and audit trails.

This is the setup you want when your agent needs to answer questions like “Did this invoice clear?”, “Show failed card attempts for this customer,” or “What’s the last successful payment for account X?” without hardcoding business logic into the model layer.

Prerequisites

  • Python 3.10+
  • A Supabase project with:
    • Project URL
    • Service role key or anon key
    • A table for payment records
  • A LlamaIndex installation with the packages you need for your agent workflow
  • Access to your payment system data source:
    • Stripe, Adyen, PayPal, or your internal ledger API
  • Environment variables configured:
    • SUPABASE_URL
    • SUPABASE_KEY
    • Any payment API keys you use
  • Basic familiarity with:
    • llama_index
    • supabase-py
    • Python async/sync HTTP calls

Integration Steps

  1. Install the dependencies and wire up clients.
pip install llama-index supabase python-dotenv
import os
from dotenv import load_dotenv
from supabase import create_client, Client

load_dotenv()

SUPABASE_URL = os.environ["SUPABASE_URL"]
SUPABASE_KEY = os.environ["SUPABASE_KEY"]

supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
print("Supabase client ready")
  1. Create a payments table in Supabase and store normalized records.

Use a schema that keeps the agent-facing fields simple. You want IDs, status, amount, currency, customer reference, and timestamps.

create table if not exists payments (
  id uuid primary key default gen_random_uuid(),
  payment_id text unique not null,
  customer_id text not null,
  amount numeric not null,
  currency text not null,
  status text not null,
  provider text not null,
  created_at timestamptz default now()
);

Now insert a record from Python after fetching it from your payment provider.

payment_row = {
    "payment_id": "pay_12345",
    "customer_id": "cust_9001",
    "amount": 149.99,
    "currency": "USD",
    "status": "succeeded",
    "provider": "stripe",
}

result = supabase.table("payments").insert(payment_row).execute()
print(result.data)
  1. Pull payment history from Supabase and expose it to LlamaIndex as context.

For production systems, don’t dump raw tables into prompts. Query only what the agent needs, then pass compact context into LlamaIndex tools or nodes.

from llama_index.core import Document

response = (
    supabase.table("payments")
    .select("payment_id, customer_id, amount, currency, status, provider, created_at")
    .eq("customer_id", "cust_9001")
    .order("created_at", desc=True)
    .limit(5)
    .execute()
)

docs = []
for row in response.data:
    text = (
        f"Payment {row['payment_id']} | "
        f"Customer {row['customer_id']} | "
        f"{row['amount']} {row['currency']} | "
        f"Status {row['status']} | "
        f"Provider {row['provider']} | "
        f"Created {row['created_at']}"
    )
    docs.append(Document(text=text))

print(f"Loaded {len(docs)} payment documents")
  1. Build a LlamaIndex query layer on top of those records.

A simple vector index works well when you want semantic lookup over payment notes, dispute reasons, or support annotations. For structured payment data alone, you can still use LlamaIndex as the orchestration layer while Supabase remains the source of truth.

from llama_index.core import VectorStoreIndex

index = VectorStoreIndex.from_documents(docs)
query_engine = index.as_query_engine()

answer = query_engine.query("What is the latest successful payment for cust_9001?")
print(str(answer))

If you need an agent that can decide when to query Supabase directly versus when to answer from indexed context, wrap both in tools.

from llama_index.core.tools import FunctionTool

def get_recent_payments(customer_id: str):
    res = (
        supabase.table("payments")
        .select("payment_id, amount, currency, status, created_at")
        .eq("customer_id", customer_id)
        .order("created_at", desc=True)
        .limit(3)
        .execute()
    )
    return res.data

payments_tool = FunctionTool.from_defaults(fn=get_recent_payments)
print(payments_tool.metadata.name)
  1. Add an agent workflow that can answer operational questions safely.

Keep write actions behind explicit functions. For production AI in payments, read-only queries should be the default; updates should require deterministic business rules.

from llama_index.core.agent.workflow import FunctionAgent

agent = FunctionAgent(
    tools=[payments_tool],
    system_prompt=(
        "You are a payments operations assistant. "
        "Use tools for factual queries. Do not invent transaction statuses."
    ),
)

result = agent.run("Show me the last three payments for customer cust_9001")
print(result)

Testing the Integration

Run a smoke test that inserts one record into Supabase and retrieves it through your query layer.

test_payment = {
    "payment_id": "pay_test_001",
    "customer_id": "cust_test_001",
    "amount": 25.00,
    "currency": "USD",
    "status": "succeeded",
    "provider": "stripe",
}

supabase.table("payments").upsert(test_payment).execute()

check = (
    supabase.table("payments")
    .select("payment_id, status")
    .eq("payment_id", "pay_test_001")
    .execute()
)

print(check.data)

# Optional LlamaIndex check
test_docs = [Document(text=f"Payment pay_test_001 status succeeded for cust_test_001")]
test_index = VectorStoreIndex.from_documents(test_docs)
print(test_index.as_query_engine().query("What is the status of pay_test_001?"))

Expected output:

[{'payment_id': 'pay_test_001', 'status': 'succeeded'}]
The status of pay_test_001 is succeeded.

Real-World Use Cases

  • Payment support agents that answer refund and chargeback questions using live Supabase records plus LlamaIndex retrieval.
  • Finance ops copilots that summarize failed transactions by customer segment and surface anomalies from recent payment activity.
  • Compliance assistants that generate audit-ready explanations of payment events while keeping Supabase as the system of record.

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