Памʼять агента у Python: що зберігається і навіщо (повний приклад)

Навчальний runnable приклад, який показує різницю між короткостроковою і довгостроковою пам'яттю агента.
На цій сторінці
  1. Що цей приклад демонструє
  2. Структура проєкту
  3. Як запустити
  4. Що ми будуємо в коді
  5. Код
  6. memory.py — short-term і long-term пам'ять
  7. tools.py — дані і форматування звіту
  8. agent.py — логіка вирішення prefs
  9. main.py — порівняння двох сценаріїв
  10. requirements.txt
  11. Приклад виводу
  12. Що видно на практиці
  13. Що змінити в цьому прикладі
  14. Повний код на GitHub

Це повна навчальна реалізація прикладу зі статті Пам'ять агента: що він пам'ятає і навіщо.

Якщо ти ще не читав статтю, почни з неї. Тут фокус лише на коді і практичній різниці між short-term та long-term memory.


Що цей приклад демонструє

  • Як короткострокова пам'ять може втратити ранні інструкції через обмежений контекст
  • Як довгострокова пам'ять зберігає налаштування між задачами
  • Чому один і той самий запит може дати різний результат залежно від типу пам'яті
  • Як будувати простий memory-aware агент без зайвої складності

Структура проєкту

TEXT
foundations/
└── agent-memory/
    └── python/
        ├── main.py          # запускає два сценарії і порівнює результат
        ├── agent.py         # логіка агента з short/long memory
        ├── memory.py        # short-term і long-term сховища
        ├── tools.py         # прості джерела даних і рендер звіту
        └── requirements.txt

Як запустити

1. Клонуй репозиторій і перейди в папку:

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

2. Встанови залежності (для цього прикладу зовнішніх пакетів немає):

BASH
pip install -r requirements.txt

3. Запусти демо:

BASH
python main.py

Що ми будуємо в коді

Ми будуємо мінімальний агент, який формує тижневий звіт у двох режимах.

  • SCENARIO 1: лише short-term memory (контекст обмежений і може "забути" ранні prefs)
  • SCENARIO 2: short-term + long-term memory (prefs збережені між задачами)

Ключова ідея: контекст задачі і пам'ять між задачами мають різні ролі.


Код

memory.py — short-term і long-term пам'ять

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 — дані і форматування звіту

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 — логіка вирішення prefs

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 — порівняння двох сценаріїв

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.

Приклад виводу

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'}

Що видно на практиці

Лише short memoryShort + long memory
Зберігає prefs між задачами
Стійкий до втрати раннього контексту
Формат/валюта відтворюються "як минулого разу"

Що змінити в цьому прикладі

  • Зменш max_items до 2 і подивись, як швидко губляться prefs у short memory
  • Додай третю user preference (наприклад, timezone) і протягни її у звіт
  • Збережи в long memory ще й last_report_total, а в новій задачі порівняй динаміку
  • Додай правило: не дозволяти порожні prefs у save_user_preferences

Повний код на GitHub

У репозиторії лежить повна версія цього демо: short-term/long-term memory, порівняння сценаріїв і trace кроків.

Переглянути повний код на GitHub ↗
⏱️ 5 хв читанняОновлено 3 березня 2026 р.Складність: ★☆☆
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.

Автор

Микола — інженер, який будує інфраструктуру для продакшн AI-агентів.

Фокус: патерни агентів, режими відмов, контроль рантайму та надійність систем.

🔗 GitHub: https://github.com/mykolademyanov


Редакційна примітка

Ця документація підготовлена з допомогою AI, із людською редакторською відповідальністю за точність, ясність і продакшн-релевантність.

Контент базується на реальних відмовах, постмортемах та операційних інцидентах у розгорнутих AI-агентних системах.