Суть
- Context window — то, что в промпте прямо сейчас (см. Context Window); быстро, но ограничено.
- Conversation history — прошлые ходы текущей сессии; обрезаются при переполнении.
- Long-term — факты/предпочтения в vector DB (Qdrant, Pinecone, pgvector); переживает сессию.
- Episodic — логи прошлых успехов/провалов как справочник для будущих задач.
Зачем это нужно
Без памяти агент тащит весь контекст на каждом шаге → взрывной рост токенов. Кейс из материала: наивный агент-химик (IBM Materials) съел 20 млн токенов против 1234 у агента с указателями — разница ~16 000×.
Как работает
- Memory pointers: большие данные хранятся вне контекстного окна, агент работает с ними через короткие идентификаторы-указатели, подтягивая по запросу (а не пересылая целиком). Управление контекстом = управление стоимостью (см. Agent CostControl).
- Долгая память реализуется через retrieval — это и есть RAG поверх vector DB; выбор хранилища — Vector Databases, а сохранение/перенос индекса памяти между машинами — Vector Store Persistence.
- В multi-agent состояние шарится (общий invocation_state), в single-agent — локальный state.
- Персистентность состояния для долгоживущих агентов: статус задач пишется на диск (например, SQLite
agent_state.db), чтобы агент пережил рестарт и продолжил с чекпоинта (см. Task DAG в Agent Architecture). В LangGraph это встроенный checkpointer (SQLite/Postgres/Redis) с восстановлением сессии поthread_id— см. LangGraph Checkpointers. - Bi-temporal memory (двухвременная память): хранить не только факт, но и историю смены убеждений — поле
invalidated_reasonотвечает на вопрос «почему агент передумал» (выбрал SQLite вместо PostgreSQL). Даёт долгосрочную связность (coherence) и аудируемость.
Альтернативный взгляд
Память подаётся не как «4 хранилища», а как backend-сервис со своим SLA: latency, ошибки, таймауты, стоимость. Два следствия: (1) не модель решает идти в память — это делает оркестрация по явным правилам (policy); (2) принципиально различаются read (чтение по ключу, детерминированно: «положили — достали ровно то») и retrieve (всегда вопрос вероятности — поиск по смыслу). Операции памяти явные: memory.read / update / write / retrieve. Такой взгляд делает память тестируемой и предсказуемой, в отличие от «модель сама вспомнит».
Пример
Bi-temporal память: факт не удаляется, а помечается неактуальным (valid_to + invalidated_reason). В контекст модели идёт только query_valid(), но полная история (почему агент «передумал») остаётся для аудита.
class BiTemporalMemory:
def __init__(self): self.records = []
def store(self, fact, kind="observation"):
rec = {"id": uuid.uuid4().hex[:8], "fact": fact, "kind": kind,
"valid_to": None, "invalidated_reason": None} # valid_to=None -> актуально
self.records.append(rec); return rec["id"]
def invalidate(self, fact_id, reason): # «агент передумал»
for r in self.records:
if r["id"] == fact_id and r["valid_to"] is None:
r["valid_to"] = datetime.now().isoformat()
r["invalidated_reason"] = reason # почему отменили — для аудита
def query_valid(self, kind=None): # в контекст идёт только актуальное
return [r for r in self.records
if r["valid_to"] is None and (kind is None or r["kind"] == kind)]
Связано с
- Agent Anatomy — память как один из 4 компонентов
- Context Window — самый «горячий» вид памяти
- RAG — механизм долгосрочной памяти
- Vector Databases · Vector Store Persistence — где живёт и как переносится long-term память
- Agent CostControl — память напрямую влияет на бюджет
- LangGraph Checkpointers — персистентность сессионного состояния по
thread_id
Открытые вопросы
- когда хватает summary истории, а когда нужны pointers
- как устроить episodic memory практически