Building AI Agents from Scratch

Long-Term Memory

Store and retrieve useful facts across sessions — and know when memory makes the agent worse.

Short-term memory dies when the process exits. Long-term memory is a file or table you wrote: facts you chose to keep, not a transcript dump.

Store less than you think

Save durable facts: “entrypoint is chat.py,” “demo URL is httpbin.” Do not save every tool payload. A JSONL or SQLite table with key, value, updated_at is enough.

import json
from pathlib import Path

MEM = Path("memory.json")


def load_memory() -> dict[str, str]:
    if not MEM.exists():
        return {}
    return json.loads(MEM.read_text(encoding="utf-8"))


def save_memory(data: dict[str, str]) -> None:
    MEM.write_text(json.dumps(data, indent=2), encoding="utf-8")


def remember(key: str, value: str) -> dict:
    data = load_memory()
    data[key.strip()] = value.strip()[:500]
    save_memory(data)
    return {"ok": True, "stored": key}


def recall(key: str) -> dict:
    data = load_memory()
    if key not in data:
        return {"ok": False, "error": "unknown key", "keys": list(data)[:20]}
    return {"ok": True, "key": key, "value": data[key]}

Expose remember and recall as tools, or inject the whole small map into the system prompt at startup if it stays under a page. Injection is simpler until the map grows.

When not to use memory

  • Secrets. A remembered token will leak into the next chat and the log.
  • Volatile state (“the build is red”) that will be wrong tomorrow.
  • Anything the filesystem or API can answer cheaply. Memory of a file is a stale copy.

Restart the process and ask “What did we decide the entrypoint was?” It should recall without listing the directory again. Next: plan before the first tool.