# Supabase Session Manager for Strands AI

A session manager for [Strands Agents](https://strandsagents.com/) that uses Supabase (PostgreSQL) for persistent storage. Enables AI agents to maintain conversation history and state across sessions.

## Features

- **Persistent Sessions**: Store agent conversations and state in Supabase
- **Distributed Ready**: Share sessions across multiple application instances
- **JSONB Storage**: Native JSON support for complex data structures
- **Referential Integrity**: CASCADE deletes ensure data consistency

## Installation

```bash
pip install supabase-strands
```

Or with uv:

```bash
uv add supabase-strands
```

## Quick Start

Choose the setup that fits your workflow:

- **Option A** — [Local (Supabase CLI)](#option-a-local-supabase-cli) — best for development and testing
- **Option B** — [Hosted (Supabase Cloud)](#option-b-hosted-supabase-cloud) — best for production and shared environments

---

### Option A: Local (Supabase CLI)

#### 1. Start Supabase locally

```bash
# Install the CLI (macOS)
brew install supabase/tap/supabase

# Initialize and start
supabase init
supabase start
```

After `supabase start`, the CLI prints a summary of local URLs and keys. Note the **Project URL** and the **Publishable** (anon) key — you'll need both in step 3.

#### 2. Run the migrations

```bash
mkdir -p supabase/migrations
cp migrations/001_create_session_tables.sql supabase/migrations/
supabase db reset
```

> **Tip:** Skip `migrations/002_enable_rls.sql` for local dev — RLS adds complexity you don't need while iterating. When you're ready to test auth policies, copy that file into `supabase/migrations/` and run `supabase db reset` again.

#### 3. Configure credentials

```bash
export SUPABASE_URL="<Project URL from supabase start>"
export SUPABASE_KEY="<Publishable key from supabase start>"
```

Or create a `.env` file:

```
SUPABASE_URL=<Project URL from supabase start>
SUPABASE_KEY=<Publishable key from supabase start>
```

> You can re-print these values anytime with `supabase status`.

#### 4. Run the example

```bash
uv sync --extra dev
uv run python examples/basic_usage.py
```

See [`examples/basic_usage.py`](examples/basic_usage.py) for the full source.

#### 5. Verify session storage

Open Supabase Studio at `http://127.0.0.1:54323` and browse the `sessions`, `agents`, and `messages` tables in the Table Editor to confirm the data was persisted.

---

### Option B: Hosted (Supabase Cloud)

#### 1. Set up your Supabase project

Create a project at [supabase.com](https://supabase.com) and run `migrations/001_create_session_tables.sql` in the SQL Editor.

For production, also run `migrations/002_enable_rls.sql` and customize the RLS policies for your auth strategy (see [Row-Level Security](#row-level-security)).

#### 2. Configure credentials

```bash
export SUPABASE_URL="https://your-project.supabase.co"
export SUPABASE_KEY="your-anon-key"
```

#### 3. Run the example

```bash
uv sync --extra dev
uv run python examples/basic_usage.py
```

See [`examples/basic_usage.py`](examples/basic_usage.py) for the full source.

#### 4. Verify session storage

Open your project's [Table Editor](https://supabase.com/dashboard) in the Supabase dashboard and browse the `sessions`, `agents`, and `messages` tables to confirm the data was persisted.

## Configuration

Credentials are read from `SUPABASE_URL` and `SUPABASE_KEY` environment variables by default. You can also pass them explicitly:

```python
manager = SupabaseSessionManager(
    session_id="user-123",
    supabase_url="https://your-project.supabase.co",
    supabase_key="your-anon-key"
)
```

## Database Schema

```
sessions (session_id PK, session_type, created_at, updated_at)
    └── agents (session_id FK, agent_id, state JSONB, conversation_manager_state JSONB)
        └── messages (session_id FK, agent_id, message_id, message JSONB, redact_message JSONB)
```

Foreign keys use `ON DELETE CASCADE` for referential integrity.

## Row-Level Security

**IMPORTANT**: The basic schema migration (`001_create_session_tables.sql`) does not include Row-Level Security (RLS). For production deployments, enable RLS using `migrations/002_enable_rls.sql`.

The provided RLS policies assume Supabase Auth with `auth.uid()::text = session_id`. Customize the policies based on your authentication strategy:

- **Supabase Auth**: Use `auth.uid()` to get the current user's ID
- **Custom Auth**: Add a `user_id` column and filter on that
- **Service Account Pattern**: Use the service role key in backend, anon key with RLS in frontend
- **Team/Org Isolation**: Join to a teams table to implement org-level access control

## Development

### Setup

```bash
uv sync --extra dev
```

### Running Tests

```bash
# Unit tests (no Supabase required)
uv run pytest tests/test_unit.py -v

# Integration tests (requires Supabase)
export SUPABASE_URL="your-test-url"
export SUPABASE_KEY="your-test-key"
uv run pytest tests/test_integration.py -v

# All tests with coverage
uv run pytest --cov=src/supabase_strands --cov-report=html
```

## Requirements

- Python 3.10+
- Supabase — either [local via CLI](https://supabase.com/docs/guides/local-development) or a [hosted project](https://supabase.com) (free tier works)
- strands-agents >= 1.0.0

## License

MIT License - see LICENSE for details.

## Contributing

Contributions welcome! Please open an issue or submit a pull request.

## Related Projects

- [Strands Agents SDK](https://strandsagents.com/)
- [PostgreSQL Session Manager](https://github.com/macuartin/strands-postgresql-session-manager)
- [Supabase](https://supabase.com/)
