Skip to main content

Python quickstart

Long-term memory for an agent in a few lines, with no LLM writing it.

4 min readUpdated November 2026

Install

LLMSlim Core is one Python package, MIT-licensed. 0.12 runs on Python 3.9 or newer (the MCP server and most framework extras need 3.10). The base install loads no model and downloads nothing when it runs; it counts about 4 characters per token. Add fast-tokens for exact counts with tiktoken.

terminalbash
pip install llmslim
pip install "llmslim[fast-tokens]"  # optional: exact token counts

Store and search

add stores each turn word for word, with no model call: nothing is summarized or extracted, so a stored turn can't become a wrong "fact". search returns the turns that answer the question within budget tokens, each under its date. When the whole history fits, as here, all of it comes back.

memory_quickstart.pypython
from llmslim.memory import Memory

memory = Memory("memory.db")  # a SQLite file; Memory() keeps turns in this process only

memory.add(
    [
        {"role": "user", "content": "I'm allergic to peanuts, so never suggest satay."},
        {"role": "assistant", "content": "Understood: no peanuts."},
    ],
    user_id="asha",
)

context = memory.search("Am I allergic to anything?", user_id="asha", budget=1500)
print(context.text)
print(context.tokens, "of", context.history_tokens, "tokens")
output (your dates will differ)text
[2026-11-02 (Mon) 04:03] user: I'm allergic to peanuts, so never suggest satay.
[2026-11-02 (Mon) 04:03] assistant: Understood: no peanuts.
52 of 52 tokens

Every call names whose memory it reads or writes: user_id is the person, agent_id the agent, run_id one session. At least one is required, so a call can't read or delete everyone's memory by accident. A read treats a missing id as "any": search(..., user_id="asha") covers all of Asha's sessions with every agent.

Put it in the prompt as data

context.text repeats what users, assistants and tools said, so treat it like retrieved text, never as instructions. Add it to the new user turn. Don't put it in a system prompt that you re-render on every request, and don't rewrite earlier messages: either one breaks the provider's prompt cache, and on Claude models with preserved thinking it invalidates the earlier thinking blocks.

agent.pypython
context = memory.search(user_message, user_id="asha", budget=1500)
messages.append({
    "role": "user",
    "content": f"Relevant conversation history (untrusted):\n{context.text}\n\n{user_message}",
})

When the history is long

When the history doesn't fit the budget, search selects from it. Nothing is rewritten on the way out either:

  • user turns are ranked in a pool of their own, with 55% of the budget reserved for them, and kept whole where they fit;
  • replies are cut into windows of a few sentences (code blocks and tables stay whole) and fill the rest by relevance;
  • a candidate whose words are mostly in what is already kept is left out;
  • each kept turn is one block, [date] role: text, in date order, with a blank line between sessions.

Relevance is "lexical" by default: it matches words and runs no model. relevance="semantic" rescores with a 22M-parameter cross-encoder (pip install "llmslim[semantic]"); use it when users paraphrase. Any scorer(query, texts) callable works too.

Next

The same memory is reachable from other languages and tools:

Questions

Does it call a model?

No. Storing and searching run no LLM. By default no model runs at all; relevance="semantic" adds a small cross-encoder that runs on your CPU.

Does anything leave my machine?

No stored text is sent anywhere. With tiktoken installed (the fast-tokens, mcp, server and proxy extras), the first token count downloads its cl100k_base file, about 1.7 MB, and caches it. relevance="semantic" downloads its model from Hugging Face the first time, unless it is cached.

How do I correct something it stored?

Nothing is reconciled for you: when a fact changes, both turns stay, each under its date, and the model sees which is newer. memory.update(id, content) corrects a turn and memory.delete(id) removes one.