Skip to main content

langgraph-checkpoint-cloudflare-d1

Installation

pip install -U langgraph-checkpoint-cloudflare-d1

Usage

This package provides both synchronous and asynchronous interfaces for saving and retrieving LangGraph checkpoints in Cloudflare D1.

Synchronous

from langgraph_checkpoint_cloudflare_d1 import CloudflareD1Saver

# Cloudflare credentials
account_id = "your-cloudflare-account-id"
database_id = "your-d1-database-id"
api_token = "your-cloudflare-api-token"

# Configuration for checkpoint operations
write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
read_config = {"configurable": {"thread_id": "1"}}

# Initialize the saver with proper credentials
with CloudflareD1Saver(
    account_id=account_id, database_id=database_id, api_token=api_token
) as checkpointer:
    # Setup the database tables (idempotent operation)
    checkpointer.setup()

    # Sample checkpoint data
    checkpoint = {
        "v": 2,
        "ts": "2024-07-31T20:14:19.804150+00:00",
        "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
        "channel_values": {"my_key": "meow", "node": "node"},
        "channel_versions": {"__start__": 2, "my_key": 3, "start:node": 3, "node": 3},
        "versions_seen": {
            "__input__": {},
            "__start__": {"__start__": 1},
            "node": {"start:node": 2},
        },
        "pending_sends": [],
    }

    # Store checkpoint
    checkpointer.put(write_config, checkpoint, {}, {})

    # Load checkpoint
    loaded_checkpoint = checkpointer.get_tuple(read_config)

    # List checkpoints
    checkpoints = list(checkpointer.list(read_config))

Async

from langgraph_checkpoint_cloudflare_d1 import AsyncCloudflareD1Saver
import asyncio


async def main():
    # Cloudflare credentials
    account_id = "your-cloudflare-account-id"
    database_id = "your-d1-database-id"
    api_token = "your-cloudflare-api-token"

    # Configuration for checkpoint operations
    write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
    read_config = {"configurable": {"thread_id": "1"}}

    # Initialize the async saver with proper credentials
    async with AsyncCloudflareD1Saver(
        account_id=account_id, database_id=database_id, api_token=api_token
    ) as checkpointer:
        # Sample checkpoint data
        checkpoint = {
            "v": 2,
            "ts": "2024-07-31T20:14:19.804150+00:00",
            "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
            "channel_values": {"my_key": "meow", "node": "node"},
            "channel_versions": {
                "__start__": 2,
                "my_key": 3,
                "start:node": 3,
                "node": 3,
            },
            "versions_seen": {
                "__input__": {},
                "__start__": {"__start__": 1},
                "node": {"start:node": 2},
            },
            "pending_sends": [],
        }

        # Setup happens automatically but can be called explicitly
        await checkpointer.setup()

        # Store checkpoint
        await checkpointer.put(write_config, checkpoint, {}, {})

        # Load checkpoint
        loaded_checkpoint = await checkpointer.get_tuple(read_config)

        # List checkpoints
        checkpoints = [cp async for cp in checkpointer.list(read_config)]


# For local execution
if __name__ == "__main__":
    asyncio.run(main())

Python Worker (D1 Binding)

Inside a Cloudflare Python Worker, WorkerCloudflareD1Saver talks to D1 directly through the Worker's env.DB binding instead of the REST API -- no network round-trip to the Cloudflare API and no API token required. It requires the optional worker extra:

pip install 'langgraph-checkpoint-cloudflare-d1[worker]'

Use it with graph.ainvoke(...) / graph.astream(...):

from workers import WorkerEntrypoint, Response
from langgraph.graph import StateGraph, START, END
from langgraph_checkpoint_cloudflare_d1.worker import WorkerCloudflareD1Saver


class Default(WorkerEntrypoint):
    async def fetch(self, request):
        # self.env.DB is the D1 binding configured in wrangler.jsonc
        checkpointer = WorkerCloudflareD1Saver(self.env.DB)

        builder = StateGraph(int)
        builder.add_node("add_one", lambda state: state + 1)
        builder.add_edge(START, "add_one")
        builder.add_edge("add_one", END)
        graph = builder.compile(checkpointer=checkpointer)

        config = {"configurable": {"thread_id": "1"}}
        result = await graph.ainvoke(3, config)
        return Response.json({"result": result})

The saver's synchronous methods (get_tuple, list, put, put_writes, delete_thread) also work, bridged to their async counterparts via pyodide.ffi.run_sync() -- the same mechanism sqlalchemy_cloudflare_d1.SyncWorkerConnection uses so SQLAlchemy's sync engine can run in a Worker without greenlet. Call them directly (checkpointer.put(...), checkpointer.get_tuple(...)) when you want synchronous code outside of a compiled graph.

This does not make graph.invoke() (sync) usable inside a Worker. LangGraph's synchronous Pregel loop submits checkpoint writes to a real concurrent.futures.ThreadPoolExecutor regardless of which checkpointer is attached, and Workers/Pyodide can't spawn real OS threads -- graph.invoke() fails with RuntimeError: can't start new thread with any checkpointer plugged in, this one included. graph.ainvoke(...) / graph.astream(...) are the only graph-level entry points that work inside a Worker.

See examples/workers/ for a complete, runnable Worker example and tests/worker_tests/ for the integration tests that exercise it.

Integration with LangGraph

To use this checkpoint saver with LangGraph, you can pass it when compiling your graph:

from langgraph.graph import StateGraph
from langgraph_checkpoint_cloudflare_d1 import CloudflareD1Saver

# Create a simple graph
builder = StateGraph(int)
builder.add_node("add_one", lambda x: x + 1)
builder.set_entry_point("add_one")
builder.set_finish_point("add_one")

# Create the checkpoint saver
checkpointer = CloudflareD1Saver(
    account_id="your-account-id",
    database_id="your-database-id",
    api_token="your-api-token",
)
checkpointer.setup()  # Create necessary tables

# Compile the graph with the checkpointer
graph = builder.compile(checkpointer=checkpointer)

# Use the graph with checkpointing
config = {"configurable": {"thread_id": "my-thread-1"}}
result = graph.invoke(3, config)

Release Notes

v0.1.6

  • Added WorkerCloudflareD1Saver for use inside Cloudflare Python Workers via the D1 binding (worker extra)

v0.1.2 (2025-05-11)

  • Added support for environmental variables

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langgraph_checkpoint_cloudflare_d1-0.1.6.tar.gz (219.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

File details

Details for the file langgraph_checkpoint_cloudflare_d1-0.1.6.tar.gz.

File metadata

File hashes

Hashes for langgraph_checkpoint_cloudflare_d1-0.1.6.tar.gz
Algorithm Hash digest
SHA256 46b129f4a27893a74b6fc8273b4575c826dc31f464b8d13a169f6769576c110b
MD5 8519156f865be3112fa2a3f424835a0d
BLAKE2b-256 fc41126ca90793f39f56024277bd826a0074ab941c2f03c5736a0b5305ca02c8

See more details on using hashes here.

File details

Details for the file langgraph_checkpoint_cloudflare_d1-0.1.6-py3-none-any.whl.

File metadata

File hashes

Hashes for langgraph_checkpoint_cloudflare_d1-0.1.6-py3-none-any.whl
Algorithm Hash digest
SHA256 378ad2a0ecfeafa55faee2cb7fc1c32781261aca94cc9dd9bf34c62e264539cd
MD5 c2044eb1f9458024d4b435df86a9ba30
BLAKE2b-256 0664100b755d49e4613ae4e562f9c749cc4b62e087c2a679e971a4f1524d8ff0

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.6 This release

2 files

0.1.5

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page