Metadata-Version: 2.4
Name: langgraph-checkpoint-supabase
Version: 0.1.0
Summary: LangGraph checkpoint saver backed by Supabase (Postgres via PostgREST).
Project-URL: Homepage, https://github.com/Tghez/langgraph-checkpoint-supabase
Project-URL: Repository, https://github.com/Tghez/langgraph-checkpoint-supabase
Project-URL: Issues, https://github.com/Tghez/langgraph-checkpoint-supabase/issues
Author: Tal
License: MIT
License-File: LICENSE
Keywords: agents,checkpoint,langchain,langgraph,postgres,supabase
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: langchain-core>=0.3.0
Requires-Dist: langgraph-checkpoint>=2.0.0
Requires-Dist: supabase>=2.10.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.6.0; extra == 'dev'
Description-Content-Type: text/markdown

# langgraph-checkpoint-supabase

A [LangGraph](https://github.com/langchain-ai/langgraph) checkpoint saver
backed by [Supabase](https://supabase.com) — persist agent state to Postgres
through PostgREST, with no direct DB connection required.

There's an official-feel checkpointer for nearly every backend LangGraph
users reach for (Postgres, SQLite, Redis, MongoDB, MySQL, DynamoDB,
Firestore, S3, Django...) but, as of this writing, no Python package for
Supabase specifically — only a [JS/TS
implementation](https://www.npmjs.com/package/@skroyc/langgraph-supabase-checkpointer).
This fills that gap for Python agents.

## Why a dedicated Supabase saver, and not just `langgraph-checkpoint-postgres`?

Supabase *is* Postgres, so if you have direct DB access, the official
Postgres checkpointer works fine and is the more battle-tested choice.

This package is for the common Supabase deployment shape where you *don't*
have a direct `psycopg` connection available or convenient — serverless /
edge functions, connection-pooler-constrained environments, or apps that
already authenticate through Supabase's client libraries and RLS policies
rather than raw SQL. It talks to Postgres exclusively over PostgREST, so it
works anywhere `supabase-py` does.

## Install

```bash
pip install langgraph-checkpoint-supabase
```

## Setup

Run [`sql/schema.sql`](./sql/schema.sql) once against your Supabase project
(SQL editor, or as a migration) to create the two tables this saver uses.

## Usage

### Sync

```python
from langgraph_checkpoint_supabase import SupabaseSaver

checkpointer = SupabaseSaver.from_conn_info(
    url="https://<project>.supabase.co",
    key="<service-role-key>",  # or an RLS-scoped key — see below
)

graph = builder.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "1"}}
graph.invoke(inputs, config)
```

### Async

```python
from langgraph_checkpoint_supabase.aio import AsyncSupabaseSaver

checkpointer = await AsyncSupabaseSaver.from_conn_info(
    url="https://<project>.supabase.co",
    key="<service-role-key>",
)

graph = builder.compile(checkpointer=checkpointer)
config = {"configurable": {"thread_id": "1"}}
await graph.ainvoke(inputs, config)
```

## Multi-tenant apps / Row Level Security

`sql/schema.sql` ships with commented-out RLS policies that scope rows to
`auth.uid()`. Uncomment and adapt them if you're passing a user-scoped
(anon/authenticated) key instead of the service-role key — this keeps one
user's threads invisible to another's queries at the database level, not
just in application code.

## What's implemented

- `put`, `put_writes`, `get_tuple`, `list`, `delete_thread`, `copy_thread`,
  `delete_for_runs` (+ async equivalents) — the full set required for a
  working checkpointer, plus thread duplication and run-scoped cleanup.
- `list(..., filter=...)` uses Postgres jsonb containment (`@>`) against the
  `metadata` column.
- `delete_for_runs` matches checkpoints via `metadata->>run_id`, so it only
  finds checkpoints whose `CheckpointMetadata` includes a `run_id` (set by
  LangGraph on checkpoints written during a run).
- `copy_thread` duplicates every checkpoint and write row for a thread under
  a new `thread_id`, across all `checkpoint_ns` values — i.e. the complete
  parent chain, not just the latest checkpoint.
- Special write channels (errors, interrupts, scheduled tasks, resume
  values) are upsertable; regular writes are insert-once, matching the
  semantics of the official checkpointers.

## What's not (yet) implemented

- `prune` — a newer optional `BaseCheckpointSaver` method not required for
  normal graph execution. Contributions welcome.
- Large-blob offload to Supabase Storage (the JS package's approach for very
  large states). The current schema stores the full checkpoint as jsonb,
  which is simpler and fine for typical agent state sizes, but isn't ideal
  for huge payloads.
- `DeltaChannel` reconstruction (a newer, Postgres-checkpointer-specific
  optimization) — out of scope for an initial version.

## Testing

```bash
pip install -e ".[dev]"
pytest tests/test_shared.py -v          # no network required

# optional: full read/write test against a real project
export SUPABASE_TEST_URL="https://<project>.supabase.co"
export SUPABASE_TEST_KEY="<service-role-key>"
pytest tests/test_live_integration.py -v
```

## License

MIT
