Supabase Database
PostgreSQL with REST API and real-time subscriptions for AI agents
Supabase provides PostgreSQL with a built-in REST API, authentication, and real-time features, perfect for rapid AI agent development.
import os
from praisonaiagents import Agent, MemoryConfig
agent = Agent(
name="assistant",
instructions="You are helpful with persistent memory.",
memory=MemoryConfig(
db={
"database_url": os.environ["SUPABASE_URL"],
"supabase_key": os.environ["SUPABASE_KEY"],
},
))
agent.start("Remember that I am building a chatbot")The user stores facts; Supabase-backed db config persists memory across sessions.
How It Works
Quick Start
- Choose Connection Mode
Supabase offers two connection methods:
REST API (Recommended)
python import os from praisonaiagents import Agent, MemoryConfig agent = Agent( name="Supabase Agent", instructions="You are a helpful assistant with persistent memory.", memory=MemoryConfig( db={ "database_url": os.environ["SUPABASE_URL"], "supabase_key": os.environ["SUPABASE_KEY"], }, ))Direct PostgreSQL
python from praisonaiagents import Agent, MemoryConfig agent = Agent( name="Supabase Direct Agent", instructions="You are a helpful assistant with SQL persistence.", memory=MemoryConfig( db={"database_url": "postgresql://postgres:pass@db.xxx.supabase.com:5432/postgres"}, )) - Set Environment Variables
bash # For REST API mode export SUPABASE_URL="https://your-project.supabase.co" export SUPABASE_KEY="your-anon-or-service-role-key" # Or for direct PostgreSQL mode export SUPABASE_DATABASE_URL="postgresql://postgres:pass@db.xxx.supabase.com:5432/postgres" - Test Conversation
python # Start conversation result = agent.start("I'm working on a chatbot project using Supabase") print(result) # Later session - memory persists result = agent.start("What project was I working on?") print(result) # "You were working on a chatbot project using Supabase"
Installation
REST API Mode
# Install Supabase client
pip install supabaseDirect PostgreSQL Mode
# Install PostgreSQL driver
pip install "praisonai[neon]"Connection Modes
REST API Mode
Uses Supabase’s REST API with automatic schema generation:
from praisonaiagents import Agent, MemoryConfig
agent = Agent(
name="REST Agent",
instructions="You use Supabase REST API for persistence.",
memory=MemoryConfig(
db={
"database_url": "https://xxx.supabase.co",
"supabase_key": os.environ["SUPABASE_KEY"],
},
))
# Tables are created automatically via REST API
result = agent.start("Hello from Supabase REST!")Required Tables (auto-created):
-- Create in Supabase SQL Editor if not using auto-creation
CREATE TABLE praison_sessions (
session_id TEXT PRIMARY KEY,
user_id TEXT,
agent_id TEXT,
name TEXT,
state JSONB,
metadata JSONB,
created_at DOUBLE PRECISION,
updated_at DOUBLE PRECISION
);
CREATE TABLE praison_messages (
id TEXT PRIMARY KEY,
session_id TEXT REFERENCES praison_sessions(session_id),
role TEXT NOT NULL,
content TEXT,
tool_calls JSONB,
metadata JSONB,
created_at DOUBLE PRECISION
);Direct PostgreSQL Mode
Uses standard PostgreSQL connection through Supabase’s pooler:
from praisonaiagents import Agent, MemoryConfig
agent = Agent(
name="Direct Agent",
instructions="You use direct PostgreSQL for persistence.",
memory=MemoryConfig(
db={"database_url": "postgresql://postgres:pass@db.xxx.supabase.com:6543/postgres"},
))
# Standard PostgreSQL tables with auto-retry for paused projects
result = agent.start("Hello from Supabase PostgreSQL!")Configuration Options
| Option | REST Mode | Direct Mode | Description |
|---|---|---|---|
database_url | https://xxx.supabase.co | postgresql://... | Supabase URL |
supabase_key | β Required | β | API key (anon or service_role) |
max_retries | 3 | 3 | Retries for paused project recovery |
retry_delay | 2.0 | 0.5 | Base delay between retries |
auto_create_tables | True | True | Create tables automatically |
Usage Patterns
Environment-Based Setup
import os
from praisonaiagents import Agent, MemoryConfig
# REST API mode - auto-detects from environment
agent = Agent(
name="Auto Agent",
instructions="You auto-configure from environment.",
memory=MemoryConfig(
db=True, # Uses SUPABASE_URL + SUPABASE_KEY
))Manual REST Configuration
from praisonai.persistence.conversation.supabase import SupabaseConversationStore
from praisonaiagents import Agent, MemoryConfig
store = SupabaseConversationStore(
url="https://your-project.supabase.co",
key=os.environ["SUPABASE_KEY"],
max_retries=5, # Extra retries for paused projects
retry_delay=3.0 # 3 second delays
)
agent = Agent(name="Manual Agent", memory={"db": store})Full Lifecycle Example
import os
from praisonai import ManagedAgent, LocalManagedConfig
from praisonaiagents import Agent, MemoryConfig
# Phase 1: Create agent with Supabase REST
managed = ManagedAgent(
provider="local",
db={
"database_url": os.environ["SUPABASE_URL"],
"supabase_key": os.environ["SUPABASE_KEY"]
},
config=LocalManagedConfig(
model="gpt-4o-mini",
name="Supabase Demo",
system="You are a helpful assistant with Supabase persistence."
)
)
agent = Agent(name="User", backend=managed)
# Store conversation data
result1 = agent.run("I'm building a real-time chat app with Supabase")
print(f"Agent: {result1}")
result2 = agent.run("The app needs user auth and database subscriptions")
print(f"Agent: {result2}")
# Phase 2: Save and simulate project pause (free tier)
session_data = managed.save_ids()
del agent, managed # Simulate pause
# Phase 3: Resume after project wake-up
managed2 = ManagedAgent(
provider="local",
db={
"database_url": os.environ["SUPABASE_URL"],
"supabase_key": os.environ["SUPABASE_KEY"]
}
)
managed2.resume_session(session_data["session_id"])
agent2 = Agent(name="User", backend=managed2)
result3 = agent2.run("What kind of app am I building?")
print(f"Resumed Agent: {result3}")
# Should recall: real-time chat app with auth and subscriptionsSupabase-Specific Features
Paused Project Recovery
Free tier projects auto-pause after 1 week of inactivity. PraisonAI handles wake-up automatically:
from praisonai.persistence.conversation.supabase import SupabaseConversationStore
store = SupabaseConversationStore(
url="https://paused-project.supabase.co",
key=os.environ["SUPABASE_KEY"],
max_retries=5, # Extra retries for wake-up
retry_delay=3.0 # Longer delays for project start
)
# First request may take 30-60 seconds if project was paused
# Subsequent requests are fastRow Level Security (RLS)
Enable RLS in Supabase for multi-tenant agents:
-- Enable RLS on tables
ALTER TABLE praison_sessions ENABLE ROW LEVEL SECURITY;
ALTER TABLE praison_messages ENABLE ROW LEVEL SECURITY;
-- Policy: Users can only access their own sessions
CREATE POLICY "Users can access own sessions" ON praison_sessions
FOR ALL USING (user_id = auth.uid()::text);
-- Policy: Users can access messages from their sessions
CREATE POLICY "Users can access own messages" ON praison_messages
FOR ALL USING (
session_id IN (
SELECT session_id FROM praison_sessions WHERE user_id = auth.uid()::text
)
);# Use service_role key for admin access, or implement user auth
agent = Agent(
name="Multi-Tenant Agent",
memory=MemoryConfig(
db={
"database_url": "https://xxx.supabase.co",
"supabase_key": os.environ["SUPABASE_SERVICE_KEY"] # service_role key bypasses RLS
},
))Real-time Subscriptions
Listen to conversation changes in real-time:
import asyncio
from supabase import create_client
async def listen_to_conversations():
supabase = create_client(
"https://your-project.supabase.co",
os.environ["SUPABASE_KEY"],
)
def on_message(payload):
print(f"New message: {payload}")
# Subscribe to new messages
supabase.table("praison_messages").on("INSERT", on_message).subscribe()
# Keep listening
await asyncio.sleep(3600) # Listen for 1 hour
# Run in background
asyncio.create_task(listen_to_conversations())Best Practices
Choose the Right Mode
- REST API: Best for rapid prototyping, automatic pausing recovery, built-in auth
- Direct PostgreSQL: Better performance, lower latency, standard SQL features
# REST: Easy setup, handles paused projects
rest_agent = Agent(memory={"db": {"database_url": "https://xxx.supabase.co", "supabase_key": "..."}})
# Direct: Better for production, lower latency
direct_agent = Agent(memory={"db": {"database_url": "postgresql://postgres:pass@db.xxx.supabase.com:6543/postgres"}})Handle Project Pausing
Free tier projects pause after 1 week. Design for graceful wake-up:
from praisonai.persistence.conversation.supabase import SupabaseConversationStore
# Optimize for paused project recovery
store = SupabaseConversationStore(
url="https://project.supabase.co",
key=os.environ["SUPABASE_KEY"],
max_retries=10, # More retries for wake-up
retry_delay=5.0 # Longer delays
)Use Service Role Keys Carefully
Service role keys bypass Row Level Security. Use them only for admin operations:
# Anon key (limited permissions)
public_agent = Agent(memory={"db": {"supabase_key": os.environ["SUPABASE_KEY"]}})
# Service role (full access) β use carefully
admin_agent = Agent(memory={"db": {"supabase_key": os.environ["SUPABASE_SERVICE_KEY"]}})Monitor Usage
Track your Supabase usage:
- Database size: Conversation history grows over time
- API requests: REST calls count toward monthly limits
- Bandwidth: File uploads/downloads if using storage
Set up usage alerts in the Supabase dashboard.
Environment Variables
| Variable | Mode | Format | Example |
|---|---|---|---|
SUPABASE_URL | REST | https://xxx.supabase.co | https://abcdefgh.supabase.co |
SUPABASE_KEY | REST | JWT token | From Supabase dashboard β Settings β API |
SUPABASE_DATABASE_URL | Direct | postgresql://... | postgresql://postgres:pass@db.xxx.supabase.com:5432/postgres |
OPENAI_API_KEY | Both | API key | Set in environment for LLM calls |
Troubleshooting
Project Paused Error
If you get “project is paused” errors:
# Wait 30-60 seconds for project to wake up, or upgrade to Pro plan
store = SupabaseConversationStore(max_retries=10, retry_delay=10.0)API Key Permissions
Ensure your API key has the right permissions:
# Check key type in Supabase dashboard
# anon key: Limited to RLS policies
# service_role key: Full database accessSSL Connection Issues
For direct PostgreSQL mode, ensure SSL:
# Add SSL to connection string
db_url = "postgresql://postgres:pass@db.xxx.supabase.com:6543/postgres?sslmode=require"