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

# Storage

> Configure persistence for the belief state

# Storage

sxth-mind supports pluggable storage backends for persisting the **belief state**
— the cognitive model it owns (`UserMind`, `ProjectMind`, `Nudge`).

<Note>
  Storage persists *beliefs*, not raw bytes. Raw conversation turns and events
  live behind a separate [`EvidenceSource`](/guides/evidence) that sxth-mind reads
  but does not own — "own the beliefs, rent the bytes." If you're looking for where
  message history is kept, that's the evidence source, not storage.
</Note>

## Available Backends

### Memory (Default)

In-memory storage. Data is lost when the process exits. Good for development and testing.

```python theme={null}
from sxth_mind import Mind
from sxth_mind.adapters import SalesAdapter

# Memory storage is the default
mind = Mind(adapter=SalesAdapter())
```

### SQLite

Persistent storage using SQLite. Good for single-server deployments.

```bash theme={null}
pip install sxth-mind[sqlite]
```

```python theme={null}
from sxth_mind import Mind
from sxth_mind.storage import SQLiteStorage
from sxth_mind.adapters import SalesAdapter

mind = Mind(
    adapter=SalesAdapter(),
    storage=SQLiteStorage("mind.db"),
)
```

The SQLite storage automatically creates these tables:

* `user_minds` — User-level belief state
* `project_minds` — Project-specific belief state
* `nudges` — Proactive suggestions

## Custom Storage

Implement the `BaseStorage` interface for custom backends (Redis, PostgreSQL, MongoDB, etc.):

```python theme={null}
from sxth_mind.storage.base import BaseStorage
from sxth_mind.schemas import UserMind, ProjectMind, Nudge

class MyStorage(BaseStorage):
    async def initialize(self) -> None:
        """Initialize the storage (create tables, connections, etc.)."""
        pass

    async def close(self) -> None:
        """Clean up resources."""
        pass

    # UserMind operations
    async def get_user_mind(self, user_id: str) -> UserMind | None:
        ...

    async def save_user_mind(self, user_mind: UserMind) -> None:
        ...

    async def delete_user_mind(self, user_id: str) -> None:
        ...

    # ProjectMind operations
    async def get_project_mind(self, user_id: str, project_id: str) -> ProjectMind | None:
        ...

    async def save_project_mind(self, project_mind: ProjectMind) -> None:
        ...

    async def get_project_minds_for_user(self, user_id: str) -> list[ProjectMind]:
        ...

    async def delete_project_mind(self, user_id: str, project_id: str) -> None:
        ...

    # Nudge operations
    async def get_pending_nudges(self, user_id: str) -> list[Nudge]:
        ...

    async def save_nudge(self, nudge: Nudge) -> None:
        ...

    async def update_nudge_status(self, nudge_id: str, status: str) -> bool:
        ...
```

<Note>
  There are no memory/message methods on `BaseStorage` — raw history is the
  [`EvidenceSource`](/guides/evidence)'s job, not storage's.
</Note>

Then use it:

```python theme={null}
mind = Mind(adapter=SalesAdapter(), storage=MyStorage())
```

## Storage Lifecycle

When using the HTTP API, storage is initialized and closed automatically via FastAPI's lifespan:

```python theme={null}
from sxth_mind.api import create_app

app = create_app(
    adapter=SalesAdapter(),
    storage=SQLiteStorage("mind.db"),  # Initialized on startup, closed on shutdown
)
```

For direct usage, initialize manually if needed:

```python theme={null}
storage = SQLiteStorage("mind.db")
await storage.initialize()

mind = Mind(adapter=SalesAdapter(), storage=storage)

# ... use mind ...

await storage.close()
```

## Data Model

All storage backends persist these entities:

| Entity      | Description                   | Key                     |
| ----------- | ----------------------------- | ----------------------- |
| UserMind    | User-level belief state       | `user_id`               |
| ProjectMind | Project-specific belief state | `(user_id, project_id)` |
| Nudge       | Proactive suggestions         | `id`                    |

Raw message/event history is **not** a storage entity — it lives behind the
[`EvidenceSource`](/guides/evidence).

Data is serialized as JSON using Pydantic's `model_dump_json()` and deserialized with `model_validate_json()`.
