Agent Memory in Python: What It Stores and Why (Full Example)

Learning runnable example that shows the difference between short-term and long-term agent memory.
On this page
  1. What This Example Demonstrates
  2. Project Structure
  3. How to Run
  4. What We Build in Code
  5. Code
  6. memory.py - short-term and long-term memory
  7. tools.py - data and report formatting
  8. agent.py - preference resolution logic
  9. main.py - comparison of two scenarios
  10. requirements.txt
  11. Example Output
  12. What You See in Practice
  13. What to Change in This Example
  14. Full Code on GitHub

This is the full learning implementation of the example from the article Agent Memory: What It Remembers and Why.

If you have not read the article yet, start there. Here the focus is only on code and the practical difference between short-term and long-term memory.


What This Example Demonstrates

  • How short-term memory can lose early instructions due to limited context
  • How long-term memory preserves settings across tasks
  • Why the same request can produce different results depending on memory type
  • How to build a simple memory-aware agent without unnecessary complexity

Project Structure

TEXT
foundations/
└── agent-memory/
    └── python/
        β”œβ”€β”€ main.py          # runs two scenarios and compares output
        β”œβ”€β”€ agent.py         # agent logic with short/long memory
        β”œβ”€β”€ memory.py        # short-term and long-term stores
        β”œβ”€β”€ tools.py         # simple data sources and report rendering
        └── requirements.txt

How to Run

1. Clone the repository and go to the folder:

BASH
git clone https://github.com/AgentPatterns-tech/agentpatterns.git
cd foundations/agent-memory/python

2. Install dependencies (this example has no external packages):

BASH
pip install -r requirements.txt

3. Run the demo:

BASH
python main.py

What We Build in Code

We build a minimal agent that creates a weekly report in two modes.

  • SCENARIO 1: short-term memory only (context is limited and can "forget" early prefs)
  • SCENARIO 2: short-term + long-term memory (prefs are preserved across tasks)

Key idea: task context and cross-task memory have different roles.


Code

memory.py - short-term and long-term memory

PYTHON
from dataclasses import dataclass, field
from typing import Any


@dataclass
class ShortMemory:
    max_items: int = 6
    items: list[dict[str, Any]] = field(default_factory=list)

    def add(self, role: str, content: str) -> None:
        self.items.append({"role": role, "content": content})
        if len(self.items) > self.max_items:
            self.items = self.items[-self.max_items :]

    def snapshot(self) -> list[dict[str, Any]]:
        return list(self.items)

    def clear(self) -> None:
        self.items.clear()


@dataclass
class LongMemoryStore:
    _prefs: dict[str, dict[str, str]] = field(default_factory=dict)

    def save_prefs(self, user_key: str, prefs: dict[str, str]) -> None:
        self._prefs[user_key] = dict(prefs)

    def load_prefs(self, user_key: str) -> dict[str, str]:
        return dict(self._prefs.get(user_key, {}))

tools.py - data and report formatting

PYTHON
def get_sales_total(user_id: int) -> float:
    _ = user_id
    return 12400.0


def get_orders_count(user_id: int) -> int:
    _ = user_id
    return 31


def render_report(*, total: float, orders: int, currency: str, report_format: str) -> str:
    if report_format == "short-bullets":
        return (
            f"- Total sales: {total:.2f} {currency}\n"
            f"- Orders: {orders}\n"
            "- Status: stable"
        )

    return (
        f"Sales report: total={total:.2f} {currency}, "
        f"orders={orders}, status=stable"
    )

agent.py - preference resolution logic

PYTHON
from memory import LongMemoryStore, ShortMemory
from tools import get_orders_count, get_sales_total, render_report

DEFAULT_PREFS = {
    "report_format": "default",
    "currency": "USD",
}


def save_user_preferences(
    *,
    user_key: str,
    prefs: dict[str, str],
    short_memory: ShortMemory,
    long_memory: LongMemoryStore,
) -> None:
    short_memory.add("user", f"Save prefs: {prefs}")
    long_memory.save_prefs(user_key, prefs)
    short_memory.add("assistant", "Preferences saved to long-term memory")


def parse_prefs_from_short_memory(short_memory: ShortMemory) -> dict[str, str]:
    # Simplified parser for learning: looks for lines like "pref:key=value".
    parsed: dict[str, str] = {}
    for item in short_memory.snapshot():
        content = item["content"]
        if "pref:" not in content:
            continue
        payload = content.split("pref:", 1)[1]
        if "=" not in payload:
            continue
        key, value = payload.split("=", 1)
        parsed[key.strip()] = value.strip()
    return parsed


def build_weekly_report(
    *,
    user_id: int,
    user_key: str,
    request: str,
    short_memory: ShortMemory,
    long_memory: LongMemoryStore,
    use_long_memory: bool,
) -> dict:
    trace: list[str] = []

    short_memory.add("user", request)
    trace.append(f"request={request}")

    short_prefs = parse_prefs_from_short_memory(short_memory)
    trace.append(f"short_prefs={short_prefs}")

    long_prefs = long_memory.load_prefs(user_key) if use_long_memory else {}
    trace.append(f"long_prefs={long_prefs}")

    prefs = {**DEFAULT_PREFS, **short_prefs, **long_prefs}
    trace.append(f"resolved_prefs={prefs}")

    total = get_sales_total(user_id)
    orders = get_orders_count(user_id)

    report = render_report(
        total=total,
        orders=orders,
        currency=prefs["currency"],
        report_format=prefs["report_format"],
    )

    short_memory.add("assistant", f"Report generated with prefs={prefs}")

    return {
        "prefs": prefs,
        "report": report,
        "trace": trace,
        "short_memory_snapshot": short_memory.snapshot(),
    }

main.py - comparison of two scenarios

PYTHON
from agent import build_weekly_report, save_user_preferences
from memory import LongMemoryStore, ShortMemory

USER_ID = 42
USER_KEY = "user:anna"


def print_result(title: str, result: dict) -> None:
    print(f"\n=== {title} ===")
    print("Resolved prefs:", result["prefs"])
    print("\nReport:")
    print(result["report"])
    print("\nTrace:")
    for line in result["trace"]:
        print(" ", line)


def main() -> None:
    long_memory = LongMemoryStore()

    # Scenario 1: only short-term memory, early instruction falls out of context.
    short_memory_1 = ShortMemory(max_items=4)
    short_memory_1.add("user", "pref:report_format=short-bullets")
    short_memory_1.add("user", "pref:currency=EUR")
    short_memory_1.add("assistant", "working...")
    short_memory_1.add("assistant", "still working...")
    short_memory_1.add("assistant", "collecting data...")  # pushes out old prefs

    result_short_only = build_weekly_report(
        user_id=USER_ID,
        user_key=USER_KEY,
        request="Build weekly sales report",
        short_memory=short_memory_1,
        long_memory=long_memory,
        use_long_memory=False,
    )
    print_result("SCENARIO 1: SHORT MEMORY ONLY", result_short_only)

    # Scenario 2: persist prefs in long-term memory, then start a new task.
    short_memory_2 = ShortMemory(max_items=4)
    save_user_preferences(
        user_key=USER_KEY,
        prefs={"report_format": "short-bullets", "currency": "EUR"},
        short_memory=short_memory_2,
        long_memory=long_memory,
    )
    short_memory_2.clear()  # new task, short memory resets

    result_with_long = build_weekly_report(
        user_id=USER_ID,
        user_key=USER_KEY,
        request="Build weekly sales report like last time",
        short_memory=short_memory_2,
        long_memory=long_memory,
        use_long_memory=True,
    )
    print_result("SCENARIO 2: WITH LONG MEMORY", result_with_long)


if __name__ == "__main__":
    main()

requirements.txt

TEXT
# No external dependencies for this learning example.

Example Output

TEXT
python main.py

=== SCENARIO 1: SHORT MEMORY ONLY ===
Resolved prefs: {'report_format': 'default', 'currency': 'USD'}

Report:
Sales report: total=12400.00 USD, orders=31, status=stable

Trace:
  request=Build weekly sales report
  short_prefs={}
  long_prefs={}
  resolved_prefs={'report_format': 'default', 'currency': 'USD'}

=== SCENARIO 2: WITH LONG MEMORY ===
Resolved prefs: {'report_format': 'short-bullets', 'currency': 'EUR'}

Report:
- Total sales: 12400.00 EUR
- Orders: 31
- Status: stable

Trace:
  request=Build weekly sales report like last time
  short_prefs={}
  long_prefs={'report_format': 'short-bullets', 'currency': 'EUR'}
  resolved_prefs={'report_format': 'short-bullets', 'currency': 'EUR'}

What You See in Practice

Short memory onlyShort + long memory
Keeps prefs across tasksβŒβœ…
Resilient to early-context lossβŒβœ…
Format/currency reproduced "like last time"βŒβœ…

What to Change in This Example

  • Reduce max_items to 2 and see how quickly prefs are lost in short memory
  • Add a third user preference (for example, timezone) and propagate it into the report
  • Save last_report_total in long memory and compare trend in the next task
  • Add a rule: do not allow empty prefs in save_user_preferences

Full Code on GitHub

The repository contains the full version of this demo: short-term/long-term memory, scenario comparison, and step trace.

View full code on GitHub β†—
⏱️ 5 min read β€’ Updated March 4, 2026Difficulty: β˜…β˜†β˜†
Integrated: production controlOnceOnly
Add guardrails to tool-calling agents
Ship this pattern with governance:
  • Budgets (steps / spend caps)
  • Tool permissions (allowlist / blocklist)
  • Kill switch & incident stop
  • Idempotency & dedupe
  • Audit logs & traceability
Integrated mention: OnceOnly is a control layer for production agent systems.

Author

Nick β€” engineer building infrastructure for production AI agents.

Focus: agent patterns, failure modes, runtime control, and system reliability.

πŸ”— GitHub: https://github.com/mykolademyanov


Editorial note

This documentation is AI-assisted, with human editorial responsibility for accuracy, clarity, and production relevance.

Content is grounded in real-world failures, post-mortems, and operational incidents in deployed AI agent systems.