Ідея за 30 секунд
Memory Layer — це не просто сховище фактів, а контрольований шар відбору, запису і повернення пам'яті.
Агент не повинен передавати всю історію в кожен запит. Він читає з пам'яті лише те, що справді допомагає зробити наступний крок. Memory Layer не повинен бездумно накопичувати все підряд. Його задача — повертати мало, але влучно.
Коли потрібен: коли агент працює не один крок, а серією кроків або сесій, де важлива послідовність і персоналізація.
LLM може бачити лише те, що потрапило в поточний контекст. Memory Layer вирішує, що саме з минулого варто повернути назад.
Проблема
Без окремого шару пам'яті агент майже завжди працює "з нуля".
Це створює типові проблеми:
- агент повторно питає те, що вже знає;
- відповіді стають непослідовними між сесіями;
- у контекст потрапляє забагато зайвої історії;
- важливі факти губляться серед шуму;
- у пам'яті накопичуються дублікати або конфліктні версії одного факту;
- агент персоналізує відповіді на основі застарілих або слабко підтверджених даних.
У результаті зростають витрати, латентність і кількість помилок у відповідях.
Рішення
Додати Memory Layer як окремий шар для роботи з пам'яттю: що зберігати, що повертати в контекст і що видаляти.
Він відокремлює логіку "як пам'ятати" від логіки "як мислити", тому агент працює стабільніше.
Аналогія: як нотатки менеджера про клієнта.
Менеджер не тримає в голові весь архів листувань. Він дістає короткі релевантні нотатки: що важливо саме для цієї розмови.
Memory Layer так само повертає агенту тільки потрібну пам'ять у потрібний момент.
Як працює Memory Layer
Memory Layer — це керований шар між Agent Runtime і memory store, який вирішує, що читати, що записувати і що прибирати.
Опис повного флоу: Retrieve → Rank → Inject → Write → Compact
Retrieve
Runtime звертається до Memory Layer і просить факти для поточного кроку.
Rank
Layer відбирає найбільш релевантні записи: за темою, свіжістю та важливістю.
Inject
Відібрана пам'ять додається в контекст перед викликом LLM.
Write
Після кроку агента шар вирішує, чи варто зберігати новий факт, зважаючи на його корисність, стабільність, чутливість, джерело та TTL.
Compact
Старі або дубльовані записи стискаються, оновлюються або видаляються за правилами TTL/лімітів.
Цей цикл повторюється на кожному кроці й допомагає агенту зберігати послідовність між кроками та сесіями.
У коді це виглядає так
class MemoryLayer:
def __init__(self, store, max_items_per_user=200):
self.store = store
self.max_items_per_user = max_items_per_user
def retrieve(self, user_id: str, query: str, top_k: int = 4):
# Повертаємо лише релевантну пам'ять, а не всю історію.
items = self.store.search(
user_id=user_id,
query=query,
limit=top_k,
min_score=0.7,
exclude_expired=True,
)
return [item["text"] for item in items]
def write(
self,
user_id: str,
observation: str,
tags: list[str],
source: str = "user",
sensitivity: str = "low",
ttl_days: int = 30,
):
if not self._worth_storing(
observation=observation,
tags=tags,
source=source,
sensitivity=sensitivity,
ttl_days=ttl_days,
):
return
self.store.insert(
user_id=user_id,
text=observation,
tags=tags,
source=source,
sensitivity=sensitivity,
ttl_days=ttl_days,
)
self.store.enforce_limit(user_id=user_id, max_items=self.max_items_per_user)
def _worth_storing(
self,
observation: str,
tags: list[str],
source: str,
sensitivity: str,
ttl_days: int,
) -> bool:
text = observation.strip()
if len(text) < 20:
return False
# Не зберігаємо короткі службові фрази.
if text.lower() in {"ок", "дякую", "зроблено", "готово"}:
return False
# Не записуємо чутливі дані в стандартну пам'ять.
if sensitivity == "high":
return False
# Довіряємо лише визначеним джерелам.
if source not in {"user", "tool", "policy"}:
return False
# Пам'ять має бути стабільною і корисною, а не випадковим шумом.
stable_tags = {"preference", "constraint", "profile", "goal"}
if not any(tag in stable_tags for tag in tags):
return False
if ttl_days < 1 or ttl_days > 365:
return False
return True
Як це виглядає під час виконання
Запит: "Підготуй мені план харчування на тиждень"
Step 1
Agent Runtime: звертається до Memory Layer.retrieve(...)
Memory Layer: повертає релевантні факти -> ["алергія на арахіс", "вегетаріанський раціон"]
Agent Runtime: додає ці факти в Context
Agent Runtime: викликає LLM.decide(...)
Step 2
LLM: повертає -> final_answer (план без арахісу і м'яса)
Agent Runtime: передає нове спостереження в Memory Layer.write(...)
Memory Layer: зберігає факт -> "користувач хоче бюджет до $80/тиждень"
Memory Layer допомагає агенту не забувати важливе і не перевантажувати контекст зайвими деталями.
Коли підходить — і коли ні
Memory Layer корисний, коли агент має пам'ятати факти між кроками або сесіями. Для одноразових запитів він часто зайвий.
Підходить
| Ситуація | Чому Memory Layer підходить | |
|---|---|---|
| ✅ | Агент працює з користувачем у кількох сесіях | Пам'ять зберігає важливі факти і прибирає повторні уточнення. |
| ✅ | Потрібна персоналізація відповіді | Шар повертає вподобання і обмеження користувача перед кроком LLM. |
| ✅ | Агент виконує довгий multi-step workflow в межах одного запуску | Шар тримає проміжні висновки і важливі факти без постійного роздування контексту. |
| ✅ | Контекст швидко росте і має ліміти | Замість повної історії агент отримує лише top-k релевантних фактів. |
Не підходить
| Ситуація | Чому Memory Layer не підходить | |
|---|---|---|
| ❌ | One-shot запит без продовження діалогу | Окремий шар пам'яті додає складність без відчутної користі. |
| ❌ | Потрібні факти, що швидко змінюються: ціни, статуси, наявність, live-дані | Тут краще робити fresh retrieval або tool call, а не покладатися на пам'ять. |
| ❌ | Політика продукту забороняє зберігати дані між сесіями | Довготривала пам'ять порушить вимоги приватності та відповідності. |
У таких випадках часто достатньо одного виклику моделі:
response = llm(prompt)
Типові проблеми та відмови
| Проблема | Що відбувається | Як запобігти |
|---|---|---|
| Застаріла пам'ять | Агент використовує старий факт і дає хибну відповідь | TTL, версії записів і періодичне оновлення |
| Некоректна персоналізація | Агент занадто впевнено персоналізує відповідь на основі слабкої або застарілої пам'яті | Перевірка свіжості факту, confidence-поріг і уточнення в користувача перед персоналізацією |
| Шум у пам'яті | У контекст потрапляє багато слабко корисних записів | Правила запису, ранжування і обмеження top_k |
| Витік між користувачами | Агент читає пам'ять іншого користувача або tenant (окремого клієнта) | Ізоляція за user_id/tenant_id та перевірки доступу |
| Отруєна пам'ять | У пам'ять потрапляє небезпечний або хибний інструктаж | Санітизація, джерела з довірою, ручна перевірка критичних записів |
| Переповнення ліміту контексту | Обсяг пам'яті у контексті стає занадто великим для LLM | Стиснення, дедуплікація і короткі підсумки замість сирої історії |
Більшість проблем Memory Layer вирішуються через чіткі правила запису, якісне ранжування і контроль доступу.
Як поєднується з іншими патернами
Memory Layer не керує всім агентом. Він відповідає лише за якісну роботу з пам'яттю в кожному кроці.
- Agent Runtime — Runtime вирішує, коли звернутися до пам'яті, а Memory Layer — що саме читати, записувати або видаляти.
- Tool Execution Layer — tool calls можуть читати або оновлювати пам'ять через контрольований шар виконання.
- Memory-Augmented Agent — цей патерн напряму спирається на Memory Layer.
- RAG Agent — RAG дістає зовнішні знання, а Memory Layer тримає внутрішній досвід конкретного агента/користувача.
Інакше кажучи:
- Agent Runtime визначає коли агент звертається до пам'яті
- Memory Layer визначає що саме зберігається і що повертається назад
Чим це відрізняється від Agent Runtime
| Agent Runtime | Memory Layer | |
|---|---|---|
| Що контролює | Увесь цикл агента | Запис, пошук і якість пам'яті |
| Коли працює | На кожному кроці циклу виконання | Під час читання/запису пам'яті |
| Що повертає | Наступний стан або фінальну відповідь | Релевантні факти для контексту |
| Головний ризик | Неправильний контроль циклу і лімітів | Застарілі, шумні або небезпечні записи |
Agent Runtime — це "диригент" усього процесу.
Memory Layer — це "пам'ять системи", яка підтримує послідовність відповіді.
Коротко
Memory Layer:
- зберігає важливі факти між кроками і сесіями
- повертає в контекст лише релевантні записи
- стискає або видаляє застарілу пам'ять за правилами
- захищає дані через ізоляцію доступу і правила запису
FAQ
Q: Чи не достатньо просто передавати всю історію в prompt?
A: Для коротких сценаріїв інколи достатньо. Але в довгих діалогах це дорого, повільно і шумно. Memory Layer дає коротку релевантну пам'ять замість повного логу.
Q: Чим короткострокова (short-term) пам'ять відрізняється від довгострокової (long-term)?
A: Короткострокова потрібна для поточного запуску або сесії. Довгострокова зберігає важливі факти між сесіями і використовується повторно.
Q: Чи можна записувати в пам'ять кожен крок агента?
A: Технічно можна, але це погана практика. Краще зберігати лише корисні факти за правилами запису, інакше пам'ять швидко перетвориться на шум.
Q: Чи замінює Memory Layer RAG або tool calls?
A: Ні. Memory Layer зберігає внутрішні факти та досвід агента/користувача. Для свіжих зовнішніх даних зазвичай потрібні retrieval або tool calls.
Що далі
Пам'ять корисна лише тоді, коли вона під контролем. Наступний крок — побачити, де пам'ять під'єднується до виконання і політик:
- Agent Runtime — як runtime підтягує пам'ять у кожній ітерації.
- Multi-Tenant — як не змішувати контекст і дані між клієнтами.
- Policy Boundaries — як обмежувати доступ до чутливої пам'яті.
- Production Stack — як поєднати memory-якість, аудит і операційний контроль.