Supabase Memory
SupabaseMemoryAdapter
stores conversations in Supabase Postgres for applications already using Supabase.
Installation
- npm
- yarn
- pnpm
npm install @voltagent/supabase @supabase/supabase-js
yarn add @voltagent/supabase @supabase/supabase-js
pnpm add @voltagent/supabase @supabase/supabase-js
Database Setup
Run this SQL in your Supabase SQL Editor (adjusts table prefix if needed):
Schema SQL (click to expand)
-- Users table (for user-scoped working memory)
CREATE TABLE IF NOT EXISTS voltagent_memory_users (
id TEXT PRIMARY KEY,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT timezone('utc'::text, now()),
updated_at TIMESTAMPTZ NOT NULL DEFAULT timezone('utc'::text, now())
);
-- Conversations table
CREATE TABLE IF NOT EXISTS voltagent_memory_conversations (
id TEXT PRIMARY KEY,
resource_id TEXT NOT NULL,
user_id TEXT NOT NULL,
title TEXT NOT NULL,
metadata JSONB NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT timezone('utc'::text, now()),
updated_at TIMESTAMPTZ NOT NULL DEFAULT timezone('utc'::text, now())
);
-- Messages table (UIMessage format)
CREATE TABLE IF NOT EXISTS voltagent_memory_messages (
conversation_id TEXT NOT NULL REFERENCES voltagent_memory_conversations(id) ON DELETE CASCADE,
message_id TEXT NOT NULL,
user_id TEXT NOT NULL,
role TEXT NOT NULL,
parts JSONB,
metadata JSONB,
format_version INTEGER DEFAULT 2,
created_at TIMESTAMPTZ NOT NULL DEFAULT timezone('utc'::text, now()),
PRIMARY KEY (conversation_id, message_id)
);
-- Workflow states (for suspension/resume)
CREATE TABLE IF NOT EXISTS voltagent_memory_workflow_states (
id TEXT PRIMARY KEY,
workflow_id TEXT NOT NULL,
workflow_name TEXT NOT NULL,
status TEXT NOT NULL,
suspension JSONB,
user_id TEXT,
conversation_id TEXT,
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_voltagent_memory_conversations_user_id
ON voltagent_memory_conversations(user_id);
CREATE INDEX IF NOT EXISTS idx_voltagent_memory_conversations_resource_id
ON voltagent_memory_conversations(resource_id);
CREATE INDEX IF NOT EXISTS idx_voltagent_memory_messages_conversation_id
ON voltagent_memory_messages(conversation_id);
CREATE INDEX IF NOT EXISTS idx_voltagent_memory_messages_created_at
ON voltagent_memory_messages(created_at);
CREATE INDEX IF NOT EXISTS idx_voltagent_memory_workflow_states_workflow_id
ON voltagent_memory_workflow_states(workflow_id);
CREATE INDEX IF NOT EXISTS idx_voltagent_memory_workflow_states_status
ON voltagent_memory_workflow_states(status);
Credentials
Get your Supabase credentials:
- Go to Supabase Dashboard
- Open your project
- Go to Project Settings → API
- Copy Project URL and anon key
Store as environment variables: SUPABASE_URL
and SUPABASE_KEY
Configuration
import { Agent, Memory } from "@voltagent/core";
import { SupabaseMemoryAdapter } from "@voltagent/supabase";
import { openai } from "@ai-sdk/openai";
// Using URL and key
const memory = new Memory({
storage: new SupabaseMemoryAdapter({
supabaseUrl: process.env.SUPABASE_URL!,
supabaseKey: process.env.SUPABASE_KEY!,
}),
});
// Using existing Supabase client
import { createClient } from "@supabase/supabase-js";
const supabaseClient = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!);
const memory = new Memory({
storage: new SupabaseMemoryAdapter({
client: supabaseClient,
}),
});
const agent = new Agent({
name: "Assistant",
model: openai("gpt-4o-mini"),
memory,
});
Configuration Options
Option | Type | Description |
---|---|---|
supabaseUrl | string | Supabase project URL (required if not using client ) |
supabaseKey | string | Supabase anon key (required if not using client ) |
client | SupabaseClient | Existing Supabase client (alternative to URL/key) |
tableName | string | Table name prefix (default: voltagent_memory ) |
storageLimit | number | Max messages per conversation (default: 100 ) |
debug | boolean | Enable debug logging (default: false ) |
logger | Logger | Optional logger for structured logging |
Note: Table prefix must match the SQL schema. If you use a custom tableName
, update the SQL accordingly.
Features
- Messages stored per
userId
andconversationId
- Oldest messages pruned when
storageLimit
exceeded - Supports complex queries with filtering, pagination, and sorting
Working Memory
const memory = new Memory({
storage: new SupabaseMemoryAdapter({
supabaseUrl: process.env.SUPABASE_URL!,
supabaseKey: process.env.SUPABASE_KEY!,
}),
workingMemory: {
enabled: true,
scope: "conversation", // or "user"
},
});
See Working Memory.
Semantic Search
import { Memory, AiSdkEmbeddingAdapter, InMemoryVectorAdapter } from "@voltagent/core";
import { SupabaseMemoryAdapter } from "@voltagent/supabase";
import { openai } from "@ai-sdk/openai";
const memory = new Memory({
storage: new SupabaseMemoryAdapter({
supabaseUrl: process.env.SUPABASE_URL!,
supabaseKey: process.env.SUPABASE_KEY!,
}),
embedding: new AiSdkEmbeddingAdapter(openai.embedding("text-embedding-3-small")),
vector: new InMemoryVectorAdapter(), // or pgvector adapter
});
See Semantic Search.
Production Setup
import { Agent, Memory } from "@voltagent/core";
import { SupabaseMemoryAdapter } from "@voltagent/supabase";
import { createClient } from "@supabase/supabase-js";
import { openai } from "@ai-sdk/openai";
const supabaseClient = createClient(
process.env.SUPABASE_URL!,
process.env.SUPABASE_KEY! // or service_role key for backend
);
const memory = new Memory({
storage: new SupabaseMemoryAdapter({
client: supabaseClient,
storageLimit: 200,
}),
});
const agent = new Agent({
name: "Assistant",
model: openai("gpt-4o-mini"),
memory,
});
Security:
- Use
anon
key with Row Level Security (RLS) policies - Use
service_role
key only in secure backend environments - Store credentials in environment variables
Use cases:
- Applications already using Supabase
- Projects leveraging Supabase Auth, Realtime, or Storage
- Environments requiring RLS policies
For production-ready zero-setup hosting, see Managed Memory.
Learn More
- Managed Memory - Production-ready hosted memory with zero setup
- Working Memory - Maintain compact context
- Semantic Search - Vector search configuration