langgraph-checkpoint-redis


Namelanggraph-checkpoint-redis JSON
Version 0.1.1 PyPI version JSON
download
home_pagehttps://www.github.com/redis-developer/langgraph-redis
SummaryRedis implementation of the LangGraph agent checkpoint saver and store.
upload_time2025-08-15 22:33:31
maintainerNone
docs_urlNone
authorRedis Inc.
requires_python<3.14,>=3.9
licenseMIT
keywords ai redis redis-client vector-database agents langgraph langchain
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # LangGraph Redis

[![PyPI version](https://badge.fury.io/py/langgraph-checkpoint-redis.svg)](https://badge.fury.io/py/langgraph-checkpoint-redis)
[![Python versions](https://img.shields.io/pypi/pyversions/langgraph-checkpoint-redis.svg)](https://pypi.org/project/langgraph-checkpoint-redis/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Tests](https://github.com/redis-developer/langgraph-redis/actions/workflows/test.yml/badge.svg)](https://github.com/redis-developer/langgraph-redis/actions/workflows/test.yml)
[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/bsbodden/4b5aae70fef2c9606648bce5d010e129/raw/langgraph-redis-coverage.json)](https://github.com/redis-developer/langgraph-redis/actions/workflows/coverage-gist.yml)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
[![Checked with mypy](https://img.shields.io/badge/mypy-checked-blue)](http://mypy-lang.org/)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Downloads](https://static.pepy.tech/badge/langgraph-checkpoint-redis)](https://pepy.tech/project/langgraph-checkpoint-redis)
[![Redis](https://img.shields.io/badge/Redis-8.0%2B-DC382D?logo=redis&logoColor=white)](https://redis.io)

This repository contains Redis implementations for LangGraph, providing both Checkpoint Savers and Stores functionality.

## Overview

The project consists of two main components:

1. **Redis Checkpoint Savers**: Implementations for storing and managing checkpoints using Redis
2. **Redis Stores**: Redis-backed key-value stores with optional vector search capabilities

## Dependencies

### Python Dependencies

The project requires the following main Python dependencies:

- `redis>=5.2.1`
- `redisvl>=0.5.1`
- `langgraph-checkpoint>=2.0.24`

### Redis Modules Requirements

**IMPORTANT:** This library requires Redis with the following modules:

- **RedisJSON** - For storing and manipulating JSON data
- **RediSearch** - For search and indexing capabilities

#### Redis 8.0+

If you're using Redis 8.0 or higher, both RedisJSON and RediSearch modules are included by default as part of the core
Redis distribution. No additional installation is required.

#### Redis < 8.0

If you're using a Redis version lower than 8.0, you'll need to ensure these modules are installed:

- Use [Redis Stack](https://redis.io/docs/stack/), which bundles Redis with these modules
- Or install the modules separately in your Redis instance

Failure to have these modules available will result in errors during index creation and checkpoint operations.

### Azure Cache for Redis / Redis Enterprise Configuration

If you're using **Azure Cache for Redis** (especially Enterprise tier) or **Redis Enterprise**, there are important configuration considerations:

#### Client Configuration

Azure Cache for Redis and Redis Enterprise use a **proxy layer** that makes the cluster appear as a single endpoint. This requires using a **standard Redis client**, not a cluster-aware client:

```python
from redis import Redis
from langgraph.checkpoint.redis import RedisSaver

# ✅ CORRECT: Use standard Redis client for Azure/Enterprise
client = Redis(
    host="your-cache.redis.cache.windows.net",  # or your Redis Enterprise endpoint
    port=6379,  # or 10000 for Azure Enterprise with TLS
    password="your-access-key",
    ssl=True,  # Azure/Enterprise typically requires SSL
    ssl_cert_reqs="required",  # or "none" for self-signed certs
    decode_responses=False  # RedisSaver expects bytes
)

# Pass the configured client to RedisSaver
saver = RedisSaver(redis_client=client)
saver.setup()

# ❌ WRONG: Don't use RedisCluster client with Azure/Enterprise
# from redis.cluster import RedisCluster
# cluster_client = RedisCluster(...)  # This will fail with proxy-based deployments
```

#### Why This Matters

- **Proxy Architecture**: Azure Cache for Redis and Redis Enterprise use a proxy layer that handles cluster operations internally
- **Automatic Detection**: RedisSaver will correctly detect this as non-cluster mode when using the standard client
- **No Cross-Slot Errors**: The proxy handles key distribution, avoiding cross-slot errors

#### Azure Cache for Redis Specific Settings

For Azure Cache for Redis Enterprise tier:

- **Port**: Use port `10000` for Enterprise tier with TLS, or `6379` for standard
- **Modules**: Enterprise tier includes RediSearch and RedisJSON by default
- **SSL/TLS**: Always enabled, minimum TLS 1.2 for Enterprise

Example for Azure Cache for Redis Enterprise:

```python
client = Redis(
    host="your-cache.redisenterprise.cache.azure.net",
    port=10000,  # Enterprise TLS port
    password="your-access-key",
    ssl=True,
    ssl_cert_reqs="required",
    decode_responses=False
)
```

## Installation

Install the library using pip:

```bash
pip install langgraph-checkpoint-redis
```

## Redis Checkpoint Savers

### Important Notes

> [!IMPORTANT]
> When using Redis checkpointers for the first time, make sure to call `.setup()` method on them to create required
> indices. See examples below.

### Standard Implementation

```python
from langgraph.checkpoint.redis import RedisSaver

write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
read_config = {"configurable": {"thread_id": "1"}}

with RedisSaver.from_conn_string("redis://localhost:6379") as checkpointer:
    # Call setup to initialize indices
    checkpointer.setup()
    checkpoint = {
        "v": 1,
        "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, {}, {})

    # Retrieve checkpoint
    loaded_checkpoint = checkpointer.get(read_config)

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

### Async Implementation

```python
from langgraph.checkpoint.redis.aio import AsyncRedisSaver


async def main():
    write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
    read_config = {"configurable": {"thread_id": "1"}}

    async with AsyncRedisSaver.from_conn_string("redis://localhost:6379") as checkpointer:
        # Call setup to initialize indices
        await checkpointer.asetup()
        checkpoint = {
            "v": 1,
            "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
        await checkpointer.aput(write_config, checkpoint, {}, {})

        # Retrieve checkpoint
        loaded_checkpoint = await checkpointer.aget(read_config)

        # List all checkpoints
        checkpoints = [c async for c in checkpointer.alist(read_config)]


# Run the async main function
import asyncio

asyncio.run(main())
```

### Shallow Implementations

Shallow Redis checkpoint savers store only the latest checkpoint in Redis. These implementations are useful when
retaining a complete checkpoint history is unnecessary.

```python
from langgraph.checkpoint.redis.shallow import ShallowRedisSaver

# For async version: from langgraph.checkpoint.redis.ashallow import AsyncShallowRedisSaver

write_config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
read_config = {"configurable": {"thread_id": "1"}}

with ShallowRedisSaver.from_conn_string("redis://localhost:6379") as checkpointer:
    checkpointer.setup()
    # ... rest of the implementation follows similar pattern
```

## Redis Checkpoint TTL Support

Both Redis checkpoint savers and stores support Time-To-Live (TTL) functionality for automatic key expiration:

```python
# Configure TTL for checkpoint savers
ttl_config = {
    "default_ttl": 60,  # Default TTL in minutes
    "refresh_on_read": True,  # Refresh TTL when checkpoint is read
}

# Use with any checkpoint saver implementation
with RedisSaver.from_conn_string("redis://localhost:6379", ttl=ttl_config) as checkpointer:
    checkpointer.setup()
    # Use the checkpointer...
```

### Removing TTL (Pinning Threads)

You can make specific checkpoints persistent by removing their TTL. This is useful for "pinning" important threads that should never expire:

```python
from langgraph.checkpoint.redis import RedisSaver

# Create saver with default TTL
saver = RedisSaver.from_conn_string("redis://localhost:6379", ttl={"default_ttl": 60})
saver.setup()

# Save a checkpoint
config = {"configurable": {"thread_id": "important-thread", "checkpoint_ns": ""}}
saved_config = saver.put(config, checkpoint, metadata, {})

# Remove TTL from the checkpoint to make it persistent
checkpoint_id = saved_config["configurable"]["checkpoint_id"]
checkpoint_key = f"checkpoint:important-thread:__empty__:{checkpoint_id}"
saver._apply_ttl_to_keys(checkpoint_key, ttl_minutes=-1)

# The checkpoint is now persistent and won't expire
```

When no TTL configuration is provided, checkpoints are persistent by default (no expiration).

This makes it easy to manage storage and ensure ephemeral data is automatically cleaned up while keeping important data persistent.

## Redis Stores

Redis Stores provide a persistent key-value store with optional vector search capabilities.

### Synchronous Implementation

```python
from langgraph.store.redis import RedisStore

# Basic usage
with RedisStore.from_conn_string("redis://localhost:6379") as store:
    store.setup()
    # Use the store...

# With vector search configuration
index_config = {
    "dims": 1536,  # Vector dimensions
    "distance_type": "cosine",  # Distance metric
    "fields": ["text"],  # Fields to index
}

# With TTL configuration
ttl_config = {
    "default_ttl": 60,  # Default TTL in minutes
    "refresh_on_read": True,  # Refresh TTL when store entries are read
}

with RedisStore.from_conn_string(
        "redis://localhost:6379",
        index=index_config,
        ttl=ttl_config
) as store:
    store.setup()
    # Use the store with vector search and TTL capabilities...
```

### Async Implementation

```python
from langgraph.store.redis.aio import AsyncRedisStore


async def main():
    # TTL also works with async implementations
    ttl_config = {
        "default_ttl": 60,  # Default TTL in minutes
        "refresh_on_read": True,  # Refresh TTL when store entries are read
    }

    async with AsyncRedisStore.from_conn_string(
            "redis://localhost:6379",
            ttl=ttl_config
    ) as store:
        await store.setup()
        # Use the store asynchronously...


asyncio.run(main())
```

## Examples

The `examples` directory contains Jupyter notebooks demonstrating the usage of Redis with LangGraph:

- `persistence_redis.ipynb`: Demonstrates the usage of Redis checkpoint savers with LangGraph
- `create-react-agent-memory.ipynb`: Shows how to create an agent with persistent memory using Redis
- `cross-thread-persistence.ipynb`: Demonstrates cross-thread persistence capabilities
- `persistence-functional.ipynb`: Shows functional persistence patterns with Redis

### Running Example Notebooks

To run the example notebooks with Docker:

1. Navigate to the examples directory:

   ```bash
   cd examples
   ```

2. Start the Docker containers:

   ```bash
   docker compose up
   ```

3. Open the URL shown in the console (typically <http://127.0.0.1:8888/tree>) in your browser to access Jupyter.

4. When finished, stop the containers:

   ```bash
   docker compose down
   ```

## Implementation Details

### Redis Module Usage

This implementation relies on specific Redis modules:

- **RedisJSON**: Used for storing structured JSON data as native Redis objects
- **RediSearch**: Used for creating and querying indices on JSON data

### Indexing

The Redis implementation creates these main indices using RediSearch:

1. **Checkpoints Index**: Stores checkpoint metadata and versioning
2. **Channel Values Index**: Stores channel-specific data
3. **Writes Index**: Tracks pending writes and intermediate states

For Redis Stores with vector search:

1. **Store Index**: Main key-value store
2. **Vector Index**: Optional vector embeddings for similarity search

### TTL Implementation

Both Redis checkpoint savers and stores leverage Redis's native key expiration:

- **Native Redis TTL**: Uses Redis's built-in `EXPIRE` command for setting TTL
- **TTL Removal**: Uses Redis's `PERSIST` command to remove TTL (with `ttl_minutes=-1`)
- **Automatic Cleanup**: Redis automatically removes expired keys
- **Configurable Default TTL**: Set a default TTL for all keys in minutes
- **TTL Refresh on Read**: Optionally refresh TTL when keys are accessed
- **Applied to All Related Keys**: TTL is applied to all related keys (checkpoint, blobs, writes)
- **Persistent by Default**: When no TTL is configured, keys are persistent (no expiration)

## Contributing

We welcome contributions! Here's how you can help:

### Development Setup

1. Clone the repository:

   ```bash
   git clone https://github.com/redis-developer/langgraph-redis
   cd langgraph-redis
   ```

2. Install dependencies:

   ```bash
   `poetry install --all-extras`
   ```

### Available Commands

The project includes several make commands for development:

- **Testing**:

  ```bash
  make test           # Run all tests
  make test-all       # Run all tests including API tests
  ```

- **Linting and Formatting**:

  ```bash
  make format        # Format all files with Black and isort
  make lint          # Run formatting, type checking, and other linters
  make check-types   # Run mypy type checking
  ```

- **Code Quality**:

  ```bash
  make test-coverage    # Run tests with coverage reporting
  make coverage-report  # Generate coverage report without running tests
  make coverage-html    # Generate HTML coverage report (opens in htmlcov/)
  make find-dead-code   # Find unused code with vulture
  ```

- **Redis for Development/Testing**:

  ```bash
  make redis-start   # Start Redis Stack in Docker (includes RedisJSON and RediSearch modules)
  make redis-stop    # Stop Redis container
  ```

### Contribution Guidelines

1. Create a new branch for your changes
2. Write tests for new functionality
3. Ensure all tests pass: `make test`
4. Format your code: `make format`
5. Run linting checks: `make lint`
6. Submit a pull request with a clear description of your changes
7. Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for commit messages

## License

This project is licensed under the MIT License.

            

Raw data

            {
    "_id": null,
    "home_page": "https://www.github.com/redis-developer/langgraph-redis",
    "name": "langgraph-checkpoint-redis",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<3.14,>=3.9",
    "maintainer_email": null,
    "keywords": "ai, redis, redis-client, vector-database, agents, langgraph, langchain",
    "author": "Redis Inc.",
    "author_email": "applied.ai@redis.com",
    "download_url": "https://files.pythonhosted.org/packages/f4/c5/59797d833d0c270364d864a01094f9f4d07baeaa0e5954a66556820037ba/langgraph_checkpoint_redis-0.1.1.tar.gz",
    "platform": null,
    "description": "# LangGraph Redis\n\n[![PyPI version](https://badge.fury.io/py/langgraph-checkpoint-redis.svg)](https://badge.fury.io/py/langgraph-checkpoint-redis)\n[![Python versions](https://img.shields.io/pypi/pyversions/langgraph-checkpoint-redis.svg)](https://pypi.org/project/langgraph-checkpoint-redis/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Tests](https://github.com/redis-developer/langgraph-redis/actions/workflows/test.yml/badge.svg)](https://github.com/redis-developer/langgraph-redis/actions/workflows/test.yml)\n[![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/bsbodden/4b5aae70fef2c9606648bce5d010e129/raw/langgraph-redis-coverage.json)](https://github.com/redis-developer/langgraph-redis/actions/workflows/coverage-gist.yml)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)\n[![Checked with mypy](https://img.shields.io/badge/mypy-checked-blue)](http://mypy-lang.org/)\n[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n[![Downloads](https://static.pepy.tech/badge/langgraph-checkpoint-redis)](https://pepy.tech/project/langgraph-checkpoint-redis)\n[![Redis](https://img.shields.io/badge/Redis-8.0%2B-DC382D?logo=redis&logoColor=white)](https://redis.io)\n\nThis repository contains Redis implementations for LangGraph, providing both Checkpoint Savers and Stores functionality.\n\n## Overview\n\nThe project consists of two main components:\n\n1. **Redis Checkpoint Savers**: Implementations for storing and managing checkpoints using Redis\n2. **Redis Stores**: Redis-backed key-value stores with optional vector search capabilities\n\n## Dependencies\n\n### Python Dependencies\n\nThe project requires the following main Python dependencies:\n\n- `redis>=5.2.1`\n- `redisvl>=0.5.1`\n- `langgraph-checkpoint>=2.0.24`\n\n### Redis Modules Requirements\n\n**IMPORTANT:** This library requires Redis with the following modules:\n\n- **RedisJSON** - For storing and manipulating JSON data\n- **RediSearch** - For search and indexing capabilities\n\n#### Redis 8.0+\n\nIf you're using Redis 8.0 or higher, both RedisJSON and RediSearch modules are included by default as part of the core\nRedis distribution. No additional installation is required.\n\n#### Redis < 8.0\n\nIf you're using a Redis version lower than 8.0, you'll need to ensure these modules are installed:\n\n- Use [Redis Stack](https://redis.io/docs/stack/), which bundles Redis with these modules\n- Or install the modules separately in your Redis instance\n\nFailure to have these modules available will result in errors during index creation and checkpoint operations.\n\n### Azure Cache for Redis / Redis Enterprise Configuration\n\nIf you're using **Azure Cache for Redis** (especially Enterprise tier) or **Redis Enterprise**, there are important configuration considerations:\n\n#### Client Configuration\n\nAzure Cache for Redis and Redis Enterprise use a **proxy layer** that makes the cluster appear as a single endpoint. This requires using a **standard Redis client**, not a cluster-aware client:\n\n```python\nfrom redis import Redis\nfrom langgraph.checkpoint.redis import RedisSaver\n\n# \u2705 CORRECT: Use standard Redis client for Azure/Enterprise\nclient = Redis(\n    host=\"your-cache.redis.cache.windows.net\",  # or your Redis Enterprise endpoint\n    port=6379,  # or 10000 for Azure Enterprise with TLS\n    password=\"your-access-key\",\n    ssl=True,  # Azure/Enterprise typically requires SSL\n    ssl_cert_reqs=\"required\",  # or \"none\" for self-signed certs\n    decode_responses=False  # RedisSaver expects bytes\n)\n\n# Pass the configured client to RedisSaver\nsaver = RedisSaver(redis_client=client)\nsaver.setup()\n\n# \u274c WRONG: Don't use RedisCluster client with Azure/Enterprise\n# from redis.cluster import RedisCluster\n# cluster_client = RedisCluster(...)  # This will fail with proxy-based deployments\n```\n\n#### Why This Matters\n\n- **Proxy Architecture**: Azure Cache for Redis and Redis Enterprise use a proxy layer that handles cluster operations internally\n- **Automatic Detection**: RedisSaver will correctly detect this as non-cluster mode when using the standard client\n- **No Cross-Slot Errors**: The proxy handles key distribution, avoiding cross-slot errors\n\n#### Azure Cache for Redis Specific Settings\n\nFor Azure Cache for Redis Enterprise tier:\n\n- **Port**: Use port `10000` for Enterprise tier with TLS, or `6379` for standard\n- **Modules**: Enterprise tier includes RediSearch and RedisJSON by default\n- **SSL/TLS**: Always enabled, minimum TLS 1.2 for Enterprise\n\nExample for Azure Cache for Redis Enterprise:\n\n```python\nclient = Redis(\n    host=\"your-cache.redisenterprise.cache.azure.net\",\n    port=10000,  # Enterprise TLS port\n    password=\"your-access-key\",\n    ssl=True,\n    ssl_cert_reqs=\"required\",\n    decode_responses=False\n)\n```\n\n## Installation\n\nInstall the library using pip:\n\n```bash\npip install langgraph-checkpoint-redis\n```\n\n## Redis Checkpoint Savers\n\n### Important Notes\n\n> [!IMPORTANT]\n> When using Redis checkpointers for the first time, make sure to call `.setup()` method on them to create required\n> indices. See examples below.\n\n### Standard Implementation\n\n```python\nfrom langgraph.checkpoint.redis import RedisSaver\n\nwrite_config = {\"configurable\": {\"thread_id\": \"1\", \"checkpoint_ns\": \"\"}}\nread_config = {\"configurable\": {\"thread_id\": \"1\"}}\n\nwith RedisSaver.from_conn_string(\"redis://localhost:6379\") as checkpointer:\n    # Call setup to initialize indices\n    checkpointer.setup()\n    checkpoint = {\n        \"v\": 1,\n        \"ts\": \"2024-07-31T20:14:19.804150+00:00\",\n        \"id\": \"1ef4f797-8335-6428-8001-8a1503f9b875\",\n        \"channel_values\": {\n            \"my_key\": \"meow\",\n            \"node\": \"node\"\n        },\n        \"channel_versions\": {\n            \"__start__\": 2,\n            \"my_key\": 3,\n            \"start:node\": 3,\n            \"node\": 3\n        },\n        \"versions_seen\": {\n            \"__input__\": {},\n            \"__start__\": {\n                \"__start__\": 1\n            },\n            \"node\": {\n                \"start:node\": 2\n            }\n        },\n        \"pending_sends\": [],\n    }\n\n    # Store checkpoint\n    checkpointer.put(write_config, checkpoint, {}, {})\n\n    # Retrieve checkpoint\n    loaded_checkpoint = checkpointer.get(read_config)\n\n    # List all checkpoints\n    checkpoints = list(checkpointer.list(read_config))\n```\n\n### Async Implementation\n\n```python\nfrom langgraph.checkpoint.redis.aio import AsyncRedisSaver\n\n\nasync def main():\n    write_config = {\"configurable\": {\"thread_id\": \"1\", \"checkpoint_ns\": \"\"}}\n    read_config = {\"configurable\": {\"thread_id\": \"1\"}}\n\n    async with AsyncRedisSaver.from_conn_string(\"redis://localhost:6379\") as checkpointer:\n        # Call setup to initialize indices\n        await checkpointer.asetup()\n        checkpoint = {\n            \"v\": 1,\n            \"ts\": \"2024-07-31T20:14:19.804150+00:00\",\n            \"id\": \"1ef4f797-8335-6428-8001-8a1503f9b875\",\n            \"channel_values\": {\n                \"my_key\": \"meow\",\n                \"node\": \"node\"\n            },\n            \"channel_versions\": {\n                \"__start__\": 2,\n                \"my_key\": 3,\n                \"start:node\": 3,\n                \"node\": 3\n            },\n            \"versions_seen\": {\n                \"__input__\": {},\n                \"__start__\": {\n                    \"__start__\": 1\n                },\n                \"node\": {\n                    \"start:node\": 2\n                }\n            },\n            \"pending_sends\": [],\n        }\n\n        # Store checkpoint\n        await checkpointer.aput(write_config, checkpoint, {}, {})\n\n        # Retrieve checkpoint\n        loaded_checkpoint = await checkpointer.aget(read_config)\n\n        # List all checkpoints\n        checkpoints = [c async for c in checkpointer.alist(read_config)]\n\n\n# Run the async main function\nimport asyncio\n\nasyncio.run(main())\n```\n\n### Shallow Implementations\n\nShallow Redis checkpoint savers store only the latest checkpoint in Redis. These implementations are useful when\nretaining a complete checkpoint history is unnecessary.\n\n```python\nfrom langgraph.checkpoint.redis.shallow import ShallowRedisSaver\n\n# For async version: from langgraph.checkpoint.redis.ashallow import AsyncShallowRedisSaver\n\nwrite_config = {\"configurable\": {\"thread_id\": \"1\", \"checkpoint_ns\": \"\"}}\nread_config = {\"configurable\": {\"thread_id\": \"1\"}}\n\nwith ShallowRedisSaver.from_conn_string(\"redis://localhost:6379\") as checkpointer:\n    checkpointer.setup()\n    # ... rest of the implementation follows similar pattern\n```\n\n## Redis Checkpoint TTL Support\n\nBoth Redis checkpoint savers and stores support Time-To-Live (TTL) functionality for automatic key expiration:\n\n```python\n# Configure TTL for checkpoint savers\nttl_config = {\n    \"default_ttl\": 60,  # Default TTL in minutes\n    \"refresh_on_read\": True,  # Refresh TTL when checkpoint is read\n}\n\n# Use with any checkpoint saver implementation\nwith RedisSaver.from_conn_string(\"redis://localhost:6379\", ttl=ttl_config) as checkpointer:\n    checkpointer.setup()\n    # Use the checkpointer...\n```\n\n### Removing TTL (Pinning Threads)\n\nYou can make specific checkpoints persistent by removing their TTL. This is useful for \"pinning\" important threads that should never expire:\n\n```python\nfrom langgraph.checkpoint.redis import RedisSaver\n\n# Create saver with default TTL\nsaver = RedisSaver.from_conn_string(\"redis://localhost:6379\", ttl={\"default_ttl\": 60})\nsaver.setup()\n\n# Save a checkpoint\nconfig = {\"configurable\": {\"thread_id\": \"important-thread\", \"checkpoint_ns\": \"\"}}\nsaved_config = saver.put(config, checkpoint, metadata, {})\n\n# Remove TTL from the checkpoint to make it persistent\ncheckpoint_id = saved_config[\"configurable\"][\"checkpoint_id\"]\ncheckpoint_key = f\"checkpoint:important-thread:__empty__:{checkpoint_id}\"\nsaver._apply_ttl_to_keys(checkpoint_key, ttl_minutes=-1)\n\n# The checkpoint is now persistent and won't expire\n```\n\nWhen no TTL configuration is provided, checkpoints are persistent by default (no expiration).\n\nThis makes it easy to manage storage and ensure ephemeral data is automatically cleaned up while keeping important data persistent.\n\n## Redis Stores\n\nRedis Stores provide a persistent key-value store with optional vector search capabilities.\n\n### Synchronous Implementation\n\n```python\nfrom langgraph.store.redis import RedisStore\n\n# Basic usage\nwith RedisStore.from_conn_string(\"redis://localhost:6379\") as store:\n    store.setup()\n    # Use the store...\n\n# With vector search configuration\nindex_config = {\n    \"dims\": 1536,  # Vector dimensions\n    \"distance_type\": \"cosine\",  # Distance metric\n    \"fields\": [\"text\"],  # Fields to index\n}\n\n# With TTL configuration\nttl_config = {\n    \"default_ttl\": 60,  # Default TTL in minutes\n    \"refresh_on_read\": True,  # Refresh TTL when store entries are read\n}\n\nwith RedisStore.from_conn_string(\n        \"redis://localhost:6379\",\n        index=index_config,\n        ttl=ttl_config\n) as store:\n    store.setup()\n    # Use the store with vector search and TTL capabilities...\n```\n\n### Async Implementation\n\n```python\nfrom langgraph.store.redis.aio import AsyncRedisStore\n\n\nasync def main():\n    # TTL also works with async implementations\n    ttl_config = {\n        \"default_ttl\": 60,  # Default TTL in minutes\n        \"refresh_on_read\": True,  # Refresh TTL when store entries are read\n    }\n\n    async with AsyncRedisStore.from_conn_string(\n            \"redis://localhost:6379\",\n            ttl=ttl_config\n    ) as store:\n        await store.setup()\n        # Use the store asynchronously...\n\n\nasyncio.run(main())\n```\n\n## Examples\n\nThe `examples` directory contains Jupyter notebooks demonstrating the usage of Redis with LangGraph:\n\n- `persistence_redis.ipynb`: Demonstrates the usage of Redis checkpoint savers with LangGraph\n- `create-react-agent-memory.ipynb`: Shows how to create an agent with persistent memory using Redis\n- `cross-thread-persistence.ipynb`: Demonstrates cross-thread persistence capabilities\n- `persistence-functional.ipynb`: Shows functional persistence patterns with Redis\n\n### Running Example Notebooks\n\nTo run the example notebooks with Docker:\n\n1. Navigate to the examples directory:\n\n   ```bash\n   cd examples\n   ```\n\n2. Start the Docker containers:\n\n   ```bash\n   docker compose up\n   ```\n\n3. Open the URL shown in the console (typically <http://127.0.0.1:8888/tree>) in your browser to access Jupyter.\n\n4. When finished, stop the containers:\n\n   ```bash\n   docker compose down\n   ```\n\n## Implementation Details\n\n### Redis Module Usage\n\nThis implementation relies on specific Redis modules:\n\n- **RedisJSON**: Used for storing structured JSON data as native Redis objects\n- **RediSearch**: Used for creating and querying indices on JSON data\n\n### Indexing\n\nThe Redis implementation creates these main indices using RediSearch:\n\n1. **Checkpoints Index**: Stores checkpoint metadata and versioning\n2. **Channel Values Index**: Stores channel-specific data\n3. **Writes Index**: Tracks pending writes and intermediate states\n\nFor Redis Stores with vector search:\n\n1. **Store Index**: Main key-value store\n2. **Vector Index**: Optional vector embeddings for similarity search\n\n### TTL Implementation\n\nBoth Redis checkpoint savers and stores leverage Redis's native key expiration:\n\n- **Native Redis TTL**: Uses Redis's built-in `EXPIRE` command for setting TTL\n- **TTL Removal**: Uses Redis's `PERSIST` command to remove TTL (with `ttl_minutes=-1`)\n- **Automatic Cleanup**: Redis automatically removes expired keys\n- **Configurable Default TTL**: Set a default TTL for all keys in minutes\n- **TTL Refresh on Read**: Optionally refresh TTL when keys are accessed\n- **Applied to All Related Keys**: TTL is applied to all related keys (checkpoint, blobs, writes)\n- **Persistent by Default**: When no TTL is configured, keys are persistent (no expiration)\n\n## Contributing\n\nWe welcome contributions! Here's how you can help:\n\n### Development Setup\n\n1. Clone the repository:\n\n   ```bash\n   git clone https://github.com/redis-developer/langgraph-redis\n   cd langgraph-redis\n   ```\n\n2. Install dependencies:\n\n   ```bash\n   `poetry install --all-extras`\n   ```\n\n### Available Commands\n\nThe project includes several make commands for development:\n\n- **Testing**:\n\n  ```bash\n  make test           # Run all tests\n  make test-all       # Run all tests including API tests\n  ```\n\n- **Linting and Formatting**:\n\n  ```bash\n  make format        # Format all files with Black and isort\n  make lint          # Run formatting, type checking, and other linters\n  make check-types   # Run mypy type checking\n  ```\n\n- **Code Quality**:\n\n  ```bash\n  make test-coverage    # Run tests with coverage reporting\n  make coverage-report  # Generate coverage report without running tests\n  make coverage-html    # Generate HTML coverage report (opens in htmlcov/)\n  make find-dead-code   # Find unused code with vulture\n  ```\n\n- **Redis for Development/Testing**:\n\n  ```bash\n  make redis-start   # Start Redis Stack in Docker (includes RedisJSON and RediSearch modules)\n  make redis-stop    # Stop Redis container\n  ```\n\n### Contribution Guidelines\n\n1. Create a new branch for your changes\n2. Write tests for new functionality\n3. Ensure all tests pass: `make test`\n4. Format your code: `make format`\n5. Run linting checks: `make lint`\n6. Submit a pull request with a clear description of your changes\n7. Follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) for commit messages\n\n## License\n\nThis project is licensed under the MIT License.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Redis implementation of the LangGraph agent checkpoint saver and store.",
    "version": "0.1.1",
    "project_urls": {
        "Homepage": "https://www.github.com/redis-developer/langgraph-redis",
        "Repository": "https://www.github.com/redis-developer/langgraph-redis"
    },
    "split_keywords": [
        "ai",
        " redis",
        " redis-client",
        " vector-database",
        " agents",
        " langgraph",
        " langchain"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "6d5c78305f6c7f32397718316abd69496127902d94021769068e3e27a58d319b",
                "md5": "8dc4152f1fb3c98a899fc8a45120c959",
                "sha256": "ac59e28b949b308dc4c1a0d0c4e11affb3d9b495e46d152d593b89a8e55338b8"
            },
            "downloads": -1,
            "filename": "langgraph_checkpoint_redis-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "8dc4152f1fb3c98a899fc8a45120c959",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<3.14,>=3.9",
            "size": 86505,
            "upload_time": "2025-08-15T22:33:29",
            "upload_time_iso_8601": "2025-08-15T22:33:29.876096Z",
            "url": "https://files.pythonhosted.org/packages/6d/5c/78305f6c7f32397718316abd69496127902d94021769068e3e27a58d319b/langgraph_checkpoint_redis-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f4c559797d833d0c270364d864a01094f9f4d07baeaa0e5954a66556820037ba",
                "md5": "4c78d627f2b3fe22cdf7458a9636e7d0",
                "sha256": "2663a3c138c6aaeeafa28de76d78d4e693bf7722fdc99ff291525f6aa1c986f3"
            },
            "downloads": -1,
            "filename": "langgraph_checkpoint_redis-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "4c78d627f2b3fe22cdf7458a9636e7d0",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<3.14,>=3.9",
            "size": 81279,
            "upload_time": "2025-08-15T22:33:31",
            "upload_time_iso_8601": "2025-08-15T22:33:31.069211Z",
            "url": "https://files.pythonhosted.org/packages/f4/c5/59797d833d0c270364d864a01094f9f4d07baeaa0e5954a66556820037ba/langgraph_checkpoint_redis-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-15 22:33:31",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "redis-developer",
    "github_project": "langgraph-redis",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "langgraph-checkpoint-redis"
}
        
Elapsed time: 2.27637s