A MemoryStore is the storage backend for Memory. Definable provides three built-in implementations, from ephemeral in-memory stores for testing to file-based and SQLite backends for persistence.
Available Backends
| Backend | Import | Dependency | Best For |
|---|
InMemoryStore | definable.memory | None | Testing, ephemeral sessions |
SQLiteStore | definable.memory | aiosqlite (core) | Local dev, single-process |
FileStore | definable.memory | None | JSONL-based persistence, simple deployments |
Backend Examples
InMemoryStore
Ephemeral store for testing. Data is lost when the process exits.
from definable.memory import Memory, InMemoryStore
memory = Memory(store=InMemoryStore())
This is also what you get with memory=True on an Agent or when you omit the store parameter:
from definable.agent import Agent
from definable.model.openai import OpenAIChat
# Both of these use InMemoryStore:
agent = Agent(model=OpenAIChat(id="gpt-4o"), memory=True)
agent = Agent(model=OpenAIChat(id="gpt-4o"), memory=Memory())
SQLiteStore
The default choice for local development. Uses aiosqlite (included as a core dependency). Tables are auto-created on first use.
from definable.memory import Memory, SQLiteStore
memory = Memory(store=SQLiteStore("./memory.db"))
Path to the SQLite database file. Created automatically if it does not exist.
FileStore
JSONL-based file storage. Each session gets its own .jsonl file in the specified directory.
from definable.memory import Memory, FileStore
memory = Memory(store=FileStore("./memory_data"))
Directory where JSONL session files are stored. Created automatically if it does not exist.
MemoryStore Protocol
All backends implement the MemoryStore protocol. You can create custom stores by implementing these methods:
from definable.memory.store.base import MemoryStore
from definable.memory.types import MemoryEntry
class MyStore:
async def initialize(self) -> None:
"""Prepare the store (create tables, open connections)."""
...
async def close(self) -> None:
"""Release resources (close connections, flush buffers)."""
...
async def add(self, entry: MemoryEntry) -> None:
"""Add a conversation entry to the store."""
...
async def get_entries(
self,
session_id: str,
user_id: str = "default",
) -> list[MemoryEntry]:
"""Retrieve all entries for a session, ordered by created_at ascending."""
...
async def get_entry(self, memory_id: str) -> MemoryEntry | None:
"""Retrieve a single entry by its ID."""
...
async def update(self, entry: MemoryEntry) -> None:
"""Update an existing entry (matched by memory_id)."""
...
async def delete(self, memory_id: str) -> None:
"""Delete a single entry by ID."""
...
async def delete_session(
self,
session_id: str,
user_id: str = "default",
) -> None:
"""Delete all entries for a session."""
...
async def count(
self,
session_id: str,
user_id: str = "default",
) -> int:
"""Count entries in a session."""
...
Method Reference
| Method | Description |
|---|
initialize() | Prepare the store (create tables, open connections). Called automatically by Memory on first use. |
close() | Release resources. Called by Memory.close() or the agent’s shutdown. |
add(entry) | Add a MemoryEntry to the store. |
get_entries(session_id, user_id) | List entries for a session, ordered by creation time ascending. |
get_entry(memory_id) | Fetch a single entry by its UUID. Returns None if not found. |
update(entry) | Update an existing entry (matched by memory_id). |
delete(memory_id) | Delete a single entry. |
delete_session(session_id, user_id) | Delete all entries for a session. |
count(session_id, user_id) | Count the number of entries in a session. |
MemoryEntry Data Type
Every store works with MemoryEntry objects:
| Field | Type | Default | Description |
|---|
session_id | str | — | Session this entry belongs to |
memory_id | str | None | Auto-generated UUID | Unique identifier |
user_id | str | "default" | User this entry belongs to |
role | str | "user" | Message role ("user", "assistant", "summary") |
content | str | "" | The message content |
message_data | dict | None | None | Optional structured message data |
created_at | float | None | Auto-set | Unix timestamp |
updated_at | float | None | Auto-set | Unix timestamp |
from definable.memory.types import MemoryEntry
entry = MemoryEntry(
session_id="session-1",
user_id="alice",
role="user",
content="I prefer Python for backend work.",
)
Choosing a Backend
| Scenario | Recommended Store |
|---|
| Unit tests, quick prototyping | InMemoryStore |
| Local development, single-process apps | SQLiteStore |
| Simple deployments, human-readable logs | FileStore |
For most projects, start with SQLiteStore during development. The store is a constructor parameter, so swapping backends requires changing a single line:
# Development
memory = Memory(store=SQLiteStore("./memory.db"))
# File-based
memory = Memory(store=FileStore("./memory_data"))