---
title: "Supabase + pgvector for AI Agents: Memory, RAG, and Auth in One Backend (2026)"
description: "Supabase ships pgvector, RLS, and edge functions out of the box. Here's a working AI-agent memory layer with semantic recall, per-user RLS, and a match_documents RPC ready for LangChain."
canonical: https://callsphere.ai/blog/vw7h-supabase-pgvector-ai-agents-2026
category: "AI Engineering"
tags: ["Supabase", "pgvector", "AI Agents", "RAG", "Postgres"]
author: "CallSphere Team"
published: 2026-03-31T00:00:00.000Z
updated: 2026-05-07T22:22:41.766Z
---

# Supabase + pgvector for AI Agents: Memory, RAG, and Auth in One Backend (2026)

> Supabase ships pgvector, RLS, and edge functions out of the box. Here's a working AI-agent memory layer with semantic recall, per-user RLS, and a match_documents RPC ready for LangChain.

> **TL;DR** — Supabase = managed Postgres + pgvector + RLS + edge functions. For AI agent memory and RAG it's the lowest-friction stack in 2026 — five tables, one RPC, and your LangChain agent has long-term memory.

## What you'll build

A Supabase project with a `documents` table for RAG, an `agent_memories` table for per-user long-term memory, an RLS policy that scopes both to `auth.uid()`, and a `match_documents` RPC that LangChain.js calls directly.

## Schema

```sql
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id BIGSERIAL PRIMARY KEY,
  user_id UUID NOT NULL REFERENCES auth.users (id) ON DELETE CASCADE,
  content TEXT NOT NULL,
  metadata JSONB DEFAULT '{}',
  embedding vector(1536) NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE INDEX documents_hnsw_idx ON documents
  USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64);

ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

CREATE POLICY user_owns_documents ON documents
  USING (user_id = auth.uid())
  WITH CHECK (user_id = auth.uid());
```

## Architecture

```mermaid
flowchart LR
  USER[User in app] --> SB[Supabase Auth JWT]
  SB --> PG[(Postgres + pgvector)]
  PG --> RLS[RLS scopes to auth.uid]
  AGENT[LangChain agent] --> RPC[match_documents RPC]
  RPC --> PG
  PG --> RESULTS[Top-k user docs]
  RESULTS --> AGENT
```

## Step 1 — Create the match RPC

```sql
CREATE OR REPLACE FUNCTION match_documents(
  query_embedding vector(1536),
  match_count int DEFAULT 5,
  filter jsonb DEFAULT '{}'
)
RETURNS TABLE (id bigint, content text, metadata jsonb, similarity float)
LANGUAGE plpgsql STABLE
AS $$
BEGIN
  RETURN QUERY
  SELECT d.id, d.content, d.metadata,
         1 - (d.embedding  query_embedding) AS similarity
  FROM documents d
  WHERE d.user_id = auth.uid()
    AND d.metadata @> filter
  ORDER BY d.embedding  query_embedding
  LIMIT match_count;
END;
$$;
```

## Step 2 — Wire into LangChain.js

```ts
import { SupabaseVectorStore } from "@langchain/community/vectorstores/supabase";
import { OpenAIEmbeddings } from "@langchain/openai";
import { createClient } from "@supabase/supabase-js";

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!,
  { global: { headers: { Authorization: `Bearer ${userJwt}` } } },
);

const store = new SupabaseVectorStore(new OpenAIEmbeddings(), {
  client: supabase,
  tableName: "documents",
  queryName: "match_documents",
});

const docs = await store.similaritySearch("appointment policy", 5);
```

The user's JWT carries `auth.uid()` — RLS plus the RPC keeps results scoped automatically.

## Step 3 — Edge function for ingestion

```ts
// supabase/functions/ingest/index.ts
import { OpenAI } from "https://esm.sh/openai@4";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";

Deno.serve(async (req) => {
  const { content } = await req.json();
  const oai = new OpenAI({ apiKey: Deno.env.get("OPENAI_API_KEY") });
  const v = (await oai.embeddings.create({
    model: "text-embedding-3-small", input: content,
  })).data[0].embedding;

  const sb = createClient(
    Deno.env.get("SUPABASE_URL")!,
    Deno.env.get("SUPABASE_SERVICE_ROLE_KEY")!,
  );
  const userId = (await sb.auth.getUser(req.headers.get("Authorization"))).data.user!.id;
  await sb.from("documents").insert({ user_id: userId, content, embedding: v });
  return new Response("ok");
});
```

## Step 4 — Add agent memory

```sql
CREATE TABLE agent_memories (
  id BIGSERIAL PRIMARY KEY,
  user_id UUID NOT NULL,
  agent TEXT NOT NULL,
  kind TEXT NOT NULL,  -- 'episodic' | 'semantic'
  content TEXT NOT NULL,
  embedding vector(1536) NOT NULL,
  created_at TIMESTAMPTZ DEFAULT now()
);
ALTER TABLE agent_memories ENABLE ROW LEVEL SECURITY;
CREATE POLICY uo ON agent_memories USING (user_id = auth.uid());
```

## Step 5 — Realtime updates

Supabase realtime auto-streams changes. Enable on `agent_memories` and clients see new memories live.

## Step 6 — Cost guard

Embedding API costs add up. Hash content before embedding to avoid duplicates:

```ts
import crypto from "node:crypto";
const hash = crypto.createHash("sha1").update(content).digest("hex");
// query documents WHERE metadata->>'hash' = hash before embedding
```

## Pitfalls

- **Service-role key in browser** — never. Use anon key + RLS.
- **`auth.uid()` returns null** — RPC was called with anon JWT. Pass the user's JWT in headers.
- **Index built on empty table** — fine, but rebuild after first 100k inserts for better recall.
- **Realtime row size** — Supabase realtime caps at 1MB per row.

## CallSphere production note

UrackIT — CallSphere's non-HIPAA support vertical — runs Supabase + ChromaDB for fast prototyping and per-user memory. Healthcare and Behavioral Health stay on dedicated Postgres with the `healthcare_voice` Prisma schema; OneRoof keeps RLS for landlord isolation. Across **115+ DB tables · 37 agents · 90+ tools · 6 verticals**, the same RRF + RLS pattern ports cleanly between hosts. Plans: $149/$499/$1,499 — 14-day trial, 22% affiliate.

## FAQ

**Q: Free tier limits?**
500 MB DB + 2 GB egress + 50k auth users. Fine for prototypes.

**Q: How big can pgvector grow on Supabase?**
Pro plan + dedicated compute scales to 100M+ rows.

**Q: Can I bring my own LLM?**
Yes — edge functions can call any provider; no Supabase lock-in.

**Q: What about data residency?**
Supabase supports US, EU, AP regions; pick at project create time.

**Q: Migrate off Supabase later?**
`pg_dump` + restore to any Postgres. No proprietary surfaces beyond auth + storage.

## Sources

- [Supabase docs — pgvector](https://supabase.com/docs/guides/database/extensions/pgvector)
- [Supabase docs — AI & Vectors](https://supabase.com/docs/guides/ai)
- [DEV — Persistent memory with pgvector + Supabase](https://dev.to/moneylab_ai/building-persistent-memory-for-ai-agents-a-pgvector-supabase-architecture-558n)
- [DEV — LangChain + Supabase Vector Store](https://dev.to/gautam_kumar_d3daad738680/langchain-supabase-vector-store-pgvector-a-beginner-friendly-guide-5h33)

---

Source: https://callsphere.ai/blog/vw7h-supabase-pgvector-ai-agents-2026
