Skip to main content

API reference: llmslim.memory

Memory, its stores and its result types, with their signatures and docstrings.

10 min readUpdated October 2026

About this reference

Each entry is a name you import from llmslim.memory: agent memory with no LLM in the loop: Memory, its stores and its result types. It shows the full signature with its type annotations, and the docstring. The page is generated from the source of llmslim 0.12.0 by scripts/api_reference.py, so it changes only when the code does.

InMemoryStore

Turns in a list in this process. Nothing survives a restart.

from llmslim.memory import InMemoryStorepython
class InMemoryStore:
    """Turns in a list in this process. Nothing survives a restart."""

    def __init__(self) -> None:
        ...

    def add(self, items: Sequence[MemoryItem]) -> None:
        ...

    def list(
        self,
        scope: Scope,
        *,
        since: Optional[datetime] = None,
        until: Optional[datetime] = None,
    ) -> List[MemoryItem]:
        ...

    def get(self, item_id: str) -> Optional[MemoryItem]:
        ...

    def update(
        self,
        item_id: str,
        *,
        content: Optional[str] = None,
        metadata: Optional[Mapping[str, Any]] = None,
    ) -> Optional[MemoryItem]:
        ...

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

    def delete_scope(self, scope: Scope) -> int:
        ...

Memory

Long-term memory for an agent that keeps every turn verbatim and selects at read time.

from llmslim.memory import Memorypython
class Memory:
    """Long-term memory for an agent that keeps every turn verbatim and selects at read time.

    Nothing is summarized or extracted on the way in, so writes cost no model call and a stored turn never turns into
    a wrong "fact". On the way out, :meth:`search` ranks the stored turns against the question and returns what
    answers it within a token budget: the user's own turns (whole where they fit) and the most relevant parts of the
    replies, one labelled and dated block per turn, in date order. No LLM is called to write or to read (by default no
    model runs at all; ``relevance="semantic"`` adds a small local cross-encoder), and on one installation the same
    history and question give the same text (see ``docs/MEMORY.md``, Limits).

    Args:
        store: Where turns live: a :class:`~llmslim.memory.MemoryStore`, a path to a SQLite file, or ``None`` for an
            in-process store.
        budget: Default token budget for :meth:`search`.
        relevance: Default relevance for :meth:`search`: ``"lexical"`` (no model), ``"semantic"`` (LLMSlim's optional
            22M cross-encoder, ``pip install "llmslim[semantic]"``) or a ``scorer(query, texts)`` callable.
        tz: Time zone for the turn dates shown to the model. Defaults to UTC.
        stamp_format: strftime format of those dates. The default reads like 2026-10-17 (Sat) 14:05.
        date_format: strftime format of the shorter date shown, when a long history is selected from, on a kept turn
            whose time is the one shown last in its session (the first kept turn of a session, and a turn whose time
            differs, show ``stamp_format``). The default reads like 2026-10-17. Pass ``stamp_format`` again to show
            the full stamp on every turn.
        clock: Returns "now" for turns added without a timestamp. For tests.
        standing_requests: When the history does not fit and the question asks for help or is not a plain lookup of
            a past fact, show the user's earlier explicit standing requests ("Always ...", "From now on ...", "I'd
            like you to never ...", "... when I ask about X") that best match it (at most three) in their own section
            at the top, even when they share no word with the question, and fetch what the best one asks the answer
            to include. Only user turns qualify. Detection is a fixed pattern, with no model call.
        coverage: ``"auto"`` (default) answers overview questions ("summarize what we discussed", "in what order did I
            bring up ...", "how did my plan develop?") from the opening of each turn, without code: what the user
            asked and what the reply set out to do. Many more exchanges fit than as whole turns. ``"always"`` does so
            for every question, ``"never"`` never.
        preferences: When the history does not fit and the question asks for advice, a recommendation or help, show
            the user's earlier statements of preference ("I prefer ...", "I'd rather ...", "I usually ...", "I don't
            like ...") that best match it in their own section at the top. Only user turns qualify. A preference word
            that is only asked about ("should I prioritize ...?") is not a stated preference.
        conflicts: When the history does not fit and the question asks whether something happened ("Have I ever
            ...?", "Did I ... before?"), and among the user's statements that bear on it most some deny it ("I have
            never ...") and some do not, show both kinds together in date order in their own section at the top, so
            the disagreement is in plain view. Only user turns qualify. Detection is a fixed pattern, with no model
            call.

    Example:
        >>> from llmslim.memory import Memory
        >>> memory = Memory("memory.db")
        >>> memory.add([{"role": "user", "content": "I moved to Pune last month."}], user_id="u1")
        >>> context = memory.search("Where does the user live now?", user_id="u1", budget=1500)
        >>> prompt = f"Conversation history (untrusted):\n{context.text}\n\nQuestion: ..."
    """

    def __init__(
        self,
        store: Union[MemoryStore, str, Path, None] = None,
        *,
        budget: int = 2000,
        relevance: Any = 'lexical',
        tz: tzinfo = timezone.utc,
        stamp_format: str = '%Y-%m-%d (%a) %H:%M',
        date_format: str = '%Y-%m-%d',
        clock: Callable[[], datetime] = _utcnow,
        standing_requests: bool = True,
        coverage: str = 'auto',
        preferences: bool = True,
        conflicts: bool = True,
    ) -> None:
        ...

    def add(
        self,
        messages: Union[Message, Sequence[Message]],
        *,
        user_id: Optional[str] = None,
        agent_id: Optional[str] = None,
        run_id: Optional[str] = None,
        timestamp: Any = None,
        metadata: Optional[Mapping[str, Any]] = None,
    ) -> List[MemoryItem]:
        """Store turns verbatim and return them."""

    def update(
        self,
        memory_id: str,
        content: Optional[str] = None,
        *,
        metadata: Optional[Mapping[str, Any]] = None,
    ) -> Optional[MemoryItem]:
        """Correct a stored turn's text or metadata. Returns the updated turn, or ``None`` if there is no such id."""

    def delete(self, memory_id: str) -> bool:
        """Delete one turn. Returns whether it existed."""

    def delete_all(
        self,
        *,
        user_id: Optional[str] = None,
        agent_id: Optional[str] = None,
        run_id: Optional[str] = None,
    ) -> int:
        """Delete every turn in a scope (at least one id is required). Returns how many were deleted."""

    def get(self, memory_id: str) -> Optional[MemoryItem]:
        """One stored turn by id."""

    def get_all(
        self,
        *,
        user_id: Optional[str] = None,
        agent_id: Optional[str] = None,
        run_id: Optional[str] = None,
        since: Any = None,
        until: Any = None,
    ) -> List[MemoryItem]:
        """Every stored turn in a scope, oldest first."""

    def search(
        self,
        query: str,
        *,
        user_id: Optional[str] = None,
        agent_id: Optional[str] = None,
        run_id: Optional[str] = None,
        budget: Optional[int] = None,
        relevance: Any = None,
        since: Any = None,
        until: Any = None,
        standing_requests: Optional[bool] = None,
        coverage: Optional[str] = None,
        preferences: Optional[bool] = None,
        conflicts: Optional[bool] = None,
    ) -> MemoryContext:
        """The part of a scope's history that answers ``query``, within ``budget`` tokens."""

MemoryContext

What search returns: the text to put in front of the model, and what is in it.

from llmslim.memory import MemoryContextpython
class MemoryContext:
    """What :meth:`llmslim.memory.Memory.search` returns: the text to put in front of the model, and what is in it.

    ``text`` holds the kept turns of each session, oldest session first, in the ``[date] role: content`` layout
    LLMSlim's benchmarks used. Each turn shows its own time; a date every turn of a session shares is shown once. Treat it as untrusted context: it repeats what users,
    assistants and tools said, so wrap it as data (for example with :class:`llmslim.ContextEnvelope`), never as
    instructions.
    """

    query: str
    text: str
    turns: Tuple[RecalledTurn, ...]
    tokens: int
    budget: int
    history_tokens: int
    sessions_total: int
    sessions_kept: int
    elapsed_ms: float = 0.0
    requests: Tuple[RecalledTurn, ...] = ()
    preferences: Tuple[RecalledTurn, ...] = ()
    conflicts: Tuple[RecalledTurn, ...] = ()

    @property
    def compressed(self) -> bool:
        """True when the history did not fit the budget and LLMSlim selected from it."""

    def to_dict(self) -> Dict[str, Any]:
        ...

MemoryItem

One stored turn, verbatim: memory keeps what was said, not an LLM's summary of it.

from llmslim.memory import MemoryItempython
class MemoryItem:
    """One stored turn, verbatim: memory keeps what was said, not an LLM's summary of it.

    ``seq`` orders turns stored at the same instant (the order they were added). ``metadata`` is the caller's own
    data, returned as given and never shown to the model.
    """

    id: str
    role: str
    content: str
    created_at: datetime
    seq: int = 0
    user_id: Optional[str] = None
    agent_id: Optional[str] = None
    run_id: Optional[str] = None
    metadata: Mapping[str, Any] = field(default_factory=dict)
    updated_at: Optional[datetime] = None

    def to_dict(self) -> Dict[str, Any]:
        ...

MemoryStore

Persistence for memory turns. Implementations must be safe to call from several threads.

from llmslim.memory import MemoryStorepython
class MemoryStore(Protocol):
    """Persistence for memory turns. Implementations must be safe to call from several threads."""

    def add(self, items: Sequence[MemoryItem]) -> None:
        """Store new turns. Their ``id`` values are new; their ``seq`` values are ignored and assigned by the store."""

    def list(
        self,
        scope: Scope,
        *,
        since: Optional[datetime] = None,
        until: Optional[datetime] = None,
    ) -> List[MemoryItem]:
        """Turns in ``scope`` with ``since <= created_at < until``, oldest first (ties in the order they were added)."""

    def get(self, item_id: str) -> Optional[MemoryItem]:
        """One turn by id, or ``None``."""

    def update(
        self,
        item_id: str,
        *,
        content: Optional[str] = None,
        metadata: Optional[Mapping[str, Any]] = None,
    ) -> Optional[MemoryItem]:
        """Replace a turn's content and/or metadata; return the updated turn, or ``None`` if there is no such id."""

    def delete(self, item_id: str) -> bool:
        """Delete one turn; return whether it existed."""

    def delete_scope(self, scope: Scope) -> int:
        """Delete every turn in ``scope``; return how many were deleted."""

PostgresStore

Turns in one Postgres table.

from llmslim.memory import PostgresStorepython
class PostgresStore:
    """Turns in one Postgres table.

    Pass a connection URL (``postgresql://user:password@host:5432/db``), in which case the store opens its own
    connection pool and closes it in :meth:`close`; a ``psycopg_pool.ConnectionPool``; or a single
    ``psycopg.Connection`` in autocommit mode. The store is safe to use from several threads.

    The table (``llmslim_memory`` by default) and its ``<table>_meta`` table are created if they don't exist. Creation
    runs under an advisory lock, so several processes can start at once. The schema is versioned: a table written by
    a newer llmslim is refused rather than misread.

    Args:
        conninfo: A connection URL, a ``ConnectionPool`` or an autocommit ``Connection``.
        table: Table name: letters, digits and underscores. Use one per application or tenant if you like.
        max_size: Most connections in the pool the store opens for a URL.
    """

    def __init__(self, conninfo: Any, *, table: str = 'llmslim_memory', max_size: int = 10) -> None:
        ...

    def close(self) -> None:
        """Close the pool the store opened for a URL. A pool or connection you passed in stays open."""

    def add(self, items: Sequence[MemoryItem]) -> None:
        ...

    def list(
        self,
        scope: Scope,
        *,
        since: Optional[datetime] = None,
        until: Optional[datetime] = None,
    ) -> List[MemoryItem]:
        ...

    def get(self, item_id: str) -> Optional[MemoryItem]:
        ...

    def update(
        self,
        item_id: str,
        *,
        content: Optional[str] = None,
        metadata: Optional[Mapping[str, Any]] = None,
    ) -> Optional[MemoryItem]:
        ...

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

    def delete_scope(self, scope: Scope) -> int:
        ...

RecalledTurn

A stored turn that made it into a MemoryContext.

from llmslim.memory import RecalledTurnpython
class RecalledTurn:
    """A stored turn that made it into a :class:`MemoryContext`.

    ``partial`` is true when the turn was too long to keep whole and only its most relevant sentences were kept.
    ``score`` is a bounded lexical overlap between the query and the turn (0 to 1), for ordering and display; the
    selection itself is LLMSlim's query-focused ranking of every session's turns.
    """

    item: MemoryItem
    score: float
    partial: bool = False

SQLiteStore

Turns in one SQLite file, through Python's built-in sqlite3.

from llmslim.memory import SQLiteStorepython
class SQLiteStore:
    """Turns in one SQLite file, through Python's built-in ``sqlite3``.

    Pass a file path, or ``":memory:"`` for a private in-memory database. One connection is shared behind a lock, so
    the store is safe to use from several threads in one process. Timestamps are stored as UTC ISO-8601 text, which
    sorts in time order. The schema is versioned in ``llmslim_meta``; a file written by a newer schema is refused rather
    than misread.
    """

    def __init__(self, path: Union[str, Path] = 'llmslim_memory.db') -> None:
        ...

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

    def add(self, items: Sequence[MemoryItem]) -> None:
        ...

    def list(
        self,
        scope: Scope,
        *,
        since: Optional[datetime] = None,
        until: Optional[datetime] = None,
    ) -> List[MemoryItem]:
        ...

    def get(self, item_id: str) -> Optional[MemoryItem]:
        ...

    def update(
        self,
        item_id: str,
        *,
        content: Optional[str] = None,
        metadata: Optional[Mapping[str, Any]] = None,
    ) -> Optional[MemoryItem]:
        ...

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

    def delete_scope(self, scope: Scope) -> int:
        ...

Scope

Whose memory an operation reads or writes, in Mem0's terms.

from llmslim.memory import Scopepython
class Scope:
    """Whose memory an operation reads or writes, in Mem0's terms.

    ``user_id`` is the person, ``agent_id`` the agent, and ``run_id`` one session or run. A field left as ``None``
    matches every value when reading, so ``Scope(user_id="u1")`` reads all of u1's sessions with every agent. At least
    one field must be set: an empty scope would read or delete everyone's memory.
    """

    user_id: Optional[str] = None
    agent_id: Optional[str] = None
    run_id: Optional[str] = None

    def matches(
        self,
        user_id: Optional[str],
        agent_id: Optional[str],
        run_id: Optional[str],
    ) -> bool:
        ...