> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Async State Store

> Non-blocking key-value state persistence with the AsyncStateStore protocol

Async state stores provide non-blocking key-value and hash persistence so native-async backends never block the event loop.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    name="Assistant",
    instructions="Remember the user's preferences across turns.",
)
agent.start("What's my preferred language?")
```

The user asks a follow-up; an async state store fetches cached preferences without blocking other agents on the same loop.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Async State Flow"
        A[🤖 Agent] --> B[🔄 PraisonAIDB]
        B --> C{📊 instanceof?}
        C -->|AsyncStateStore| D[⚡ await store.get]
        C -->|StateStore| E[🔄 run_sync]
        D --> F[💾 Backend]
        E --> F
    end

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef tool fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class A agent
    class B,C,D,E tool
    class F result
```

## Quick Start

**1. Subclass AsyncStateStore**

Implement a native-async backend by inheriting from `AsyncStateStore`:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.persistence import AsyncStateStore
from typing import Any, Dict, List, Optional

class MyAsyncStateStore(AsyncStateStore):
    async def get(self, key: str) -> Optional[Any]:
        ...

    async def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None:
        ...

    async def delete(self, key: str) -> bool:
        ...

    async def exists(self, key: str) -> bool:
        ...

    async def keys(self, pattern: str = "*") -> List[str]:
        ...

    async def ttl(self, key: str) -> Optional[int]:
        ...

    async def expire(self, key: str, ttl: int) -> bool:
        ...

    async def hget(self, key: str, field: str) -> Optional[Any]:
        ...

    async def hset(self, key: str, field: str, value: Any) -> None:
        ...

    async def hgetall(self, key: str) -> Dict[str, Any]:
        ...

    async def hdel(self, key: str, *fields: str) -> int:
        ...

    async def close(self) -> None:
        ...
```

**2. Wire It Into an Agent**

Pass the store through the persistence config so the agent dispatches async calls natively:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

store = MyAsyncStateStore()

agent = Agent(
    name="Assistant",
    instructions="Remember the user's preferences across turns.",
    state_store=store,
)
agent.start("What's my preferred language?")
```

> [!NOTE]
>
> These ABCs give third-party native-async backends a formal interface to subclass. Shipped async backends (e.g. `AsyncMongoDBStateStore`) still subclass the sync `StateStore` and route through `run_sync` wrappers; they will migrate onto the async ABC in a follow-up PR. Dispatch via `PraisonAIDB._dispatch_async` continues to work for both styles.

***

## How It Works

A sync caller inside a running loop dispatches to the async store through `PraisonAIDB._dispatch_async`.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Caller
    participant PraisonAIDB
    participant AsyncStore as AsyncStateStore
    participant Backend

    Caller->>PraisonAIDB: get("prefs:lang")
    PraisonAIDB->>PraisonAIDB: isinstance(store, AsyncStateStore)?
    PraisonAIDB->>AsyncStore: await store.get("prefs:lang")
    AsyncStore->>Backend: fetch value
    Backend-->>AsyncStore: value
    AsyncStore-->>PraisonAIDB: Optional[Any]
    PraisonAIDB-->>Caller: value
```

| Component | Role |
| - | - |
| **Caller** | Agent or application requesting state |
| **PraisonAIDB** | Routes the call based on store type via `isinstance()` |
| **AsyncStateStore** | Handles native-async key-value / hash operations |
| **Backend** | Redis, MongoDB, or custom storage |

### Abstract Methods

| Method | Signature | Returns |
| - | - | - |
| `get` | `async def get(self, key: str)` | `Optional[Any]` |
| `set` | `async def set(self, key: str, value: Any, ttl: Optional[int] = None)` | `None` |
| `delete` | `async def delete(self, key: str)` | `bool` |
| `exists` | `async def exists(self, key: str)` | `bool` |
| `keys` | `async def keys(self, pattern: str = "*")` | `List[str]` |
| `ttl` | `async def ttl(self, key: str)` | `Optional[int]` |
| `expire` | `async def expire(self, key: str, ttl: int)` | `bool` |
| `hget` | `async def hget(self, key: str, field: str)` | `Optional[Any]` |
| `hset` | `async def hset(self, key: str, field: str, value: Any)` | `None` |
| `hgetall` | `async def hgetall(self, key: str)` | `Dict[str, Any]` |
| `hdel` | `async def hdel(self, key: str, *fields: str)` | `int` |
| `close` | `async def close(self)` | `None` |

Concrete helpers — `get_json(key)`, `set_json(key, value, ttl=None)`, `__aenter__`, `__aexit__` — ship on the ABC and need no override.

***

## Configuration Options

> **[Persistence API Reference](/docs/sdk/reference/praisonai/modules/persistence.md)**
>
> Complete method signatures for `AsyncStateStore` and sibling stores

***

## Common Patterns

### Custom Async Backend Inheritance

Subclass `AsyncStateStore` (not `StateStore`) when your backend is natively async:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonai.persistence import AsyncStateStore

class RedisAsyncStateStore(AsyncStateStore):
    def __init__(self, client):
        self._client = client

    async def get(self, key):
        return await self._client.get(key)

    async def set(self, key, value, ttl=None):
        await self._client.set(key, value, ex=ttl)

    async def close(self):
        await self._client.aclose()
    # ... implement the remaining abstract methods
```

### `async with` Context Manager

The ABC defines `__aenter__` / `__aexit__`, so `async with` closes the store automatically:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
async with MyAsyncStateStore() as store:
    await store.set("prefs:lang", "en", ttl=3600)
    lang = await store.get("prefs:lang")
```

### `get_json` / `set_json` Helpers

The concrete helpers serialize to JSON on write. On read, a stored `str` is parsed with `json.loads`; any non-`str` value is returned as-is:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
async with MyAsyncStateStore() as store:
    await store.set_json("prefs", {"lang": "en", "theme": "dark"})
    prefs = await store.get_json("prefs")  # {"lang": "en", "theme": "dark"}
```

***

## Best Practices

> **Subclass AsyncStateStore for Native-Async Backends**
>
> Inherit the async ABC so `isinstance()` dispatch awaits your methods directly:
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> # ✅ Good - native async dispatch
> class MyStore(AsyncStateStore):
>     async def get(self, key): ...
>
> # ❌ Bad - sync ABC forces run_sync shims
> class MyStore(StateStore):
>     def get(self, key): ...
> ```

> **Always Close the Store**
>
> Use `async with` or `await store.close()` to release connections:
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> # ✅ Good - automatic cleanup
> async with MyAsyncStateStore() as store:
>     await store.get("key")
>
> # ❌ Bad - leaked connections
> store = MyAsyncStateStore()
> await store.get("key")
> ```

> **Don't Mix Sync and Async Methods**
>
> Keep a single store async end-to-end:
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> # ✅ Good - pure async
> async with store:
>     await store.set("key", "value")
>
> # ❌ Bad - calling an async method without await
> store.set("key", "value")  # returns an un-awaited coroutine
> ```

***

## Related

> **[Async Conversation Store](/docs/features/async-conversation-store.md)**
>
> Sibling async pattern for conversation sessions

> **[Persistence Overview](/docs/persistence/overview.md)**
>
> Architecture and backend options


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.