How to Integrate LlamaIndex for healthcare with Supabase for multi-agent systems

By Cyprian AaronsUpdated 2026-04-21
llamaindex-for-healthcaresupabasemulti-agent-systems

Why this integration matters

If you’re building healthcare agents, you need two things working together: domain-aware retrieval and durable shared state. LlamaIndex for healthcare gives your agents a way to query clinical knowledge, while Supabase gives you Postgres-backed persistence, auth, and realtime coordination for multi-agent workflows.

That combination is useful when one agent extracts patient context, another retrieves relevant clinical guidance, and a third stores decisions, audit trails, or task handoffs. You get an architecture that is easier to debug than a pile of in-memory prompts.

Prerequisites

  • Python 3.10+
  • A Supabase project with:
    • SUPABASE_URL
    • SUPABASE_SERVICE_ROLE_KEY or anon key for local testing
  • A PostgreSQL schema in Supabase for agent state
  • LlamaIndex installed with healthcare-related packages you plan to use
  • Access to a healthcare knowledge source:
    • clinical documents
    • guidelines
    • de-identified patient notes
  • Environment variables configured in .env

Install the core dependencies:

pip install supabase python-dotenv llama-index

If you’re using a healthcare-specific LlamaIndex package or integration layer in your stack, install that too.

Integration Steps

1) Configure Supabase and load environment variables

Start by wiring your app to Supabase. Keep credentials out of code and use a service role key only on the server side.

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_SERVICE_ROLE_KEY"]

supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)

Create a table for agent memory and handoffs:

create table if not exists agent_state (
  id uuid primary key default gen_random_uuid(),
  conversation_id text not null,
  agent_name text not null,
  payload jsonb not null,
  created_at timestamptz default now()
);

2) Build a healthcare index with LlamaIndex

Use LlamaIndex to ingest your healthcare documents. In production, keep the source data de-identified and versioned.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

docs = SimpleDirectoryReader("./healthcare_docs").load_data()
index = VectorStoreIndex.from_documents(docs)

query_engine = index.as_query_engine()
response = query_engine.query("What are the contraindications for metformin?")
print(response)

If you’re using structured medical content, keep your chunks small and preserve metadata like specialty, guideline version, and source date.

3) Persist agent outputs into Supabase

Now store the response so other agents can pick it up later. This is the part that turns retrieval into a multi-agent system instead of a single-turn chatbot.

import json

conversation_id = "case-123"
agent_name = "clinical_retrieval_agent"

result = {
    "question": "What are the contraindications for metformin?",
    "answer": str(response),
    "source": "llamaindex_healthcare_index"
}

supabase.table("agent_state").insert({
    "conversation_id": conversation_id,
    "agent_name": agent_name,
    "payload": result,
}).execute()

A second agent can read that record and continue the workflow:

handoff = (
    supabase.table("agent_state")
    .select("*")
    .eq("conversation_id", conversation_id)
    .eq("agent_name", "clinical_retrieval_agent")
    .order("created_at", desc=True)
    .limit(1)
    .execute()
)

print(handoff.data[0]["payload"])

4) Wire retrieval + persistence into one agent loop

This pattern is what you want in production: retrieve from LlamaIndex, store in Supabase, then let another agent consume the state.

def clinical_agent(question: str, conversation_id: str):
    answer = query_engine.query(question)

    supabase.table("agent_state").insert({
        "conversation_id": conversation_id,
        "agent_name": "clinical_retrieval_agent",
        "payload": {
            "question": question,
            "answer": str(answer),
        },
    }).execute()

    return str(answer)

def care_coordination_agent(conversation_id: str):
    rows = (
        supabase.table("agent_state")
        .select("*")
        .eq("conversation_id", conversation_id)
        .eq("agent_name", "clinical_retrieval_agent")
        .order("created_at", desc=True)
        .limit(1)
        .execute()
    )

    latest = rows.data[0]["payload"]
    return f"Next action based on retrieval: {latest['answer']}"

5) Add realtime coordination for multi-agent systems

Supabase Realtime lets agents react when new state lands. That’s useful for orchestration patterns like triage → retrieval → summarization → escalation.

from supabase import create_client

channel = supabase.channel("agent-state-updates")

def handle_insert(payload):
    print("New agent state:", payload)

channel.on_postgres_changes(
    event="INSERT",
    schema="public",
    table="agent_state",
    callback=handle_insert,
)

channel.subscribe()

In practice, one worker writes to Supabase and another worker listens for inserts. That keeps your agents loosely coupled and easy to scale.

Testing the Integration

Run an end-to-end smoke test: ask a question, store the result, then fetch it back from Supabase.

test_conversation_id = "test-case-001"

answer = clinical_agent(
    "What monitoring is recommended after starting warfarin?",
    test_conversation_id,
)

stored = (
    supabase.table("agent_state")
    .select("*")
    .eq("conversation_id", test_conversation_id)
    .eq("agent_name", "clinical_retrieval_agent")
    .limit(1)
    .execute()
)

print("Answer:", answer)
print("Stored payload:", stored.data[0]["payload"])

Expected output:

Answer: [LlamaIndex-generated answer about warfarin monitoring]
Stored payload: {
  'question': 'What monitoring is recommended after starting warfarin?',
  'answer': '[same answer]',
}

If that round-trip works, your retrieval layer and shared state layer are connected correctly.

Real-World Use Cases

  • Clinical triage assistant

    • One agent collects symptoms.
    • Another retrieves guideline-based recommendations from LlamaIndex.
    • Supabase stores every step for auditability and escalation.
  • Prior authorization workflow

    • An intake agent extracts diagnosis and treatment details.
    • A retrieval agent pulls payer policy snippets.
    • A coordinator agent writes final packets into Supabase for review.
  • Care coordination copilot

    • One agent summarizes discharge notes.
    • Another searches internal protocols.
    • Supabase keeps task status, handoffs, and timestamps across the whole chain.

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