Skip to content

Tutorial

Add memory to a Python agent

Take an agent that starts blank every run and give it what previous runs established, in about twenty lines.

about 15 minutesYou need: Python 3.10+, An API key, An agent loop you already have
  1. 01

    Install and configure

    The client reads the key from the argument or from the environment. Prefer the environment: a key in source is a key in your git history.

    pip install persistmemory
    export PERSISTMEMORY_API_KEY="pm_..."
  2. 02

    Recall before you reason

    Query for what earlier runs established and put it in the prompt. Recall returns a handful of memories rather than the whole history, so this stays the same size whether the agent has run twice or two thousand times.

    from persistmemory import PersistMemory
    
    client = PersistMemory()
    
    def recall(topic: str, limit: int = 5) -> str:
        found = client.search.query(query=topic, limit=limit)
        if not found.results:
            return "Nothing known about this yet."
        return "\n".join(f"- {r.memory.content}" for r in found.results)
  3. 03

    Write back what the run established

    Write the conclusion, not the transcript. A memory is something that will still be true and still be useful next month; the reasoning that produced it usually is not.

    def establish(finding: str) -> None:
        # Returns a job. Extraction runs afterwards and may produce one
        # memory, several, or none, so do not treat this as a write that
        # you can immediately read back.
        client.memories.remember(text=finding)

    Writing every intermediate thought is the common mistake. It fills recall with the agent's own noise, and next month's run is then reasoning about last month's reasoning rather than about what was true.

  4. 04

    Put it around the loop

    Two calls, one before and one after. That is the whole integration.

    def run(task: str) -> str:
        context = recall(task)
    
        answer = your_agent(
            task,
            system=f"What you already know:\n{context}"
        )
    
        if answer.confident:
            establish(answer.finding)
    
        return answer.text
  5. 05

    Keep runs apart with spaces

    If one agent serves several customers, pass a space so recall cannot cross between them. Access rules attached to a source are carried through and never widened, and a space is how you say which world a memory belongs to.

    client.search.query(query=task, space_ids=["spc_northwind"], limit=5)
    client.memories.remember(text=finding, space_ids=["spc_northwind"])

    Worth doing from the first day rather than retrofitting. Memories written without a space are not automatically placed in one later, so a multi-tenant agent that skipped this has a mixing problem to clean up rather than a setting to change.