# Память AI-агента: sessions, long-term state и retrieval

> Как спроектировать память AI-агента без data swamp: session state, durable facts, retrieval, provenance, conflicts, privacy, deletion и evaluation.
> Author: Roman Belov · Published: 2026-08-21 · Source: https://futurecraft.pro/ru/blog/ai-agent-memory/

«Добавить агенту память» звучит как одна feature. В production это минимум четыре
разные системы данных:

```text
current run state
conversation or workflow checkpoint
long-term facts and preferences
retrieval over documents and prior experiences
```

Если смешать их, агент начнёт считать старый chat summary текущим account state,
приватную preference — organization policy, а неудачную попытку — проверенной
процедурой.

Memory — не увеличенный prompt и не vector database со всеми разговорами подряд. Это
управляемый путь **event → candidate → stored record → retrieval → context → correction
or deletion**.

Здесь разобран именно этот путь. Общий
[гайд по context engineering](/ru/blog/context-engineering-guide/) показывает, как
memory конкурирует с instructions, tools и retrieved documents внутри context window.
Для нескольких cooperating agents пригодится
[гайд по multi-agent architecture](/ru/blog/multi-agent-architecture/).

## Разделите четыре задачи состояния

| Слой | Scope | Пример | Storage shape |
| --- | --- | --- | --- |
| Working state | Один run или step | Текущий plan, intermediate IDs, retry count | Typed in-memory state |
| Thread state | Один conversation или workflow | Messages, approvals, checkpoint, pending tool call | Ordered log и checkpoints |
| Long-term memory | User, project, agent или organization | Preference, verified fact, reusable experience | Structured records с lifecycle |
| Knowledge retrieval | Corpus и access domain | Product docs, tickets, repository files | Source documents плюс index |

Границы важнее названий. OpenAI Agents SDK, например, использует `Session` для
conversation history одной session. Актуальный
[гайд по state management](https://openai.github.io/openai-agents-python/running_agents/)
разделяет client-managed sessions и server-managed conversations и предупреждает: если
смешать обе стратегии persistence в одном run, context может задублироваться.

LangGraph проводит похожую границу: checkpoints сохраняют thread state, Store — данные
для recall между threads. В
[memory overview](https://docs.langchain.com/oss/python/concepts/memory) они называются
short-term и long-term memory. Framework можно сменить; scopes смешивать не стоит.

## Храните records, а не свободный prose

Единое поле `memory_text` быстро запускается и плохо эксплуатируется. Record должен
отвечать, кому он принадлежит, откуда взялся, действует ли сейчас и где может
использоваться:

```json
{
  "memory_id": "mem_01...",
  "subject_id": "usr_internal_42",
  "namespace": ["user", "travel_preferences"],
  "kind": "preference",
  "fact": {
    "field": "seat_preference",
    "value": "aisle"
  },
  "source": {
    "type": "explicit_user_statement",
    "event_id": "evt_01..."
  },
  "confidence": "confirmed",
  "sensitivity": "personal",
  "valid_from": "2026-08-21T10:00:00Z",
  "valid_until": null,
  "created_at": "2026-08-21T10:00:02Z",
  "supersedes": null
}
```

Embedding остаётся производным index от source record, а не source of truth. Тогда
correction, смена access и deletion не требуют восстанавливать смысл из вектора.

### Осознанно выбирайте memory type

Полезно разделять три long-term типа:

- **Semantic:** facts — язык пользователя или deployment region проекта.
- **Episodic:** предыдущая попытка, actions и verified outcome.
- **Procedural:** instructions по выполнению задачи.

Procedural memory требует самого строгого gate. Если агент может переписать свои общие
instructions, одна poisoned conversation закрепит вредное поведение. Organization
policy и high-impact procedures должны быть versioned, reviewed и read-only для
runtime. Агент может предложить изменение, но не тихо опубликовать его.

## Сначала спроектируйте write path

Большинство memory failures начинается с лишних записей. «Пользователь это упомянул» —
не retention policy.

Используйте три write paths.

### 1. Explicit и immediate

Пользователь говорит: «запомни, что я предпочитаю место у прохода». Проверьте, можно ли
хранить этот data class, при необходимости покажите будущую запись и сохраните
confirmed record.

### 2. Deterministic outcome

Application code фиксирует завершённое бронирование, approved decision или successful
tool result. Сохраните verified state или ссылку на system of record. Не просите модель
перефразировать identifier, чтобы затем доверять пересказу.

### 3. Inferred candidate

Модель выводит preference или lesson из нескольких событий. Сохраните candidate с
provenance, а не accepted fact. Background job может выполнить deduplication, policy
check, сравнение с текущими records и запросить user review.

Background consolidation не добавляет latency в основной ответ и видит несколько
events. Но появляются lag и races. Выдавайте candidate event ID, делайте writes
idempotent и не позволяйте старой job перезаписать новый confirmed record.

Текущая sandbox memory в OpenAI Agents SDK использует похожее разделение: conversation
extracts консолидируются в компактные memory files, а обычная `Session` остаётся
conversation history. В
[agent memory documentation](https://openai.github.io/openai-agents-python/sandbox/memory/)
сохранённая memory считается guidance, а при конфликте приоритет получает current
environment.

## Разрешайте conflicts, а не добавляйте бесконечно

Memory меняется: пользователь переехал, проект мигрировал, preference была временной,
либо extraction оказался неверным.

Задайте precedence policy в коде. Например:

```text
current system of record
> explicit current user statement
> approved organization or project record
> recent verified outcome
> model-inferred candidate
> old summary
```

Не склеивайте несовместимые values в prose. Храните versions или supersession link,
выбирайте active record детерминированно и показывайте conflict, если policy его не
разрешает. «Нашлись два billing contacts; какой актуален?» лучше, чем выбор ближайшего
embedding.

Для естественно устаревающих facts используйте validity intervals и TTL. Recency сама
по себе не является truth: более новая заметка не должна переписать approved policy.

## Сначала scope, потом similarity

Retrieval pipeline должен сначала сузить authority:

```text
verified principal
→ allowed namespace and tenant
→ memory kind and validity
→ task filters
→ lexical or semantic retrieval
→ reranking
→ context budget
```

Не ищите по глобальному index с последующей фильтрацией уже в model context. Identity и
tenant boundaries исполняются в storage query. Namespace выводится из verified runtime
context, а не из `user_id` в prompt.

Structured lookup нужен для точных facts:

- current timezone;
- approved language;
- active workflow ID;
- policy version;
- object ownership.

Semantic search нужен для fuzzy experiences и notes: похожих incidents, прошлых
подходов или preferences в разных формулировках. Добавляйте metadata filters и lexical
search, когда важны identifiers или exact phrases.

Возвращайте небольшой typed packet с provenance:

```json
{
  "fact": "Prefers aisle seats",
  "status": "confirmed",
  "source_date": "2026-08-21",
  "memory_id": "mem_01..."
}
```

У memory должен быть фиксированный token budget. Если помещаются десять records,
retrieval не должен возвращать пятьдесят в надежде, что модель отбросит сорок. Логируйте
candidates, selected records и rejection reasons для debugging.

## Summary — lossy index

Conversation compaction полезен, но summary не должен оставаться единственным record
approvals, tool results или user commitments.

Сохраняйте append-only event log или source messages согласно retention policy. У
summary фиксируйте:

- source range;
- prompt или summarizer version;
- creation timestamp;
- unresolved items;
- ссылки на важные source events.

После correction или deletion summary нужно пересобрать. Иначе исходный факт исчезнет,
а его paraphrase продолжит попадать в каждый будущий prompt.

## Возобновляйте workflow из checkpoint

Durable agent нужна точная state для side effects:

```text
workflow_id
current_step
completed_steps
pending_approval
tool_call_id and idempotency key
artifacts produced
last verified outcome
```

Это thread state, а не long-term memory. Сохраняйте её transactionally вокруг tool
effects и авторизуйте каждый resume. Model-generated summary «платёж, вероятно,
прошёл» не может решать, списывать ли деньги повторно.

[Persistence model LangGraph](https://docs.langchain.com/oss/python/langgraph/persistence)
пишет checkpoints per thread и использует отдельный Store для cross-thread memory. Это
хорошая architecture и без LangGraph.

## Privacy и deletion входят в schema

До хранения memory class решите:

- purpose и allowed readers;
- может ли model писать, читать или только предлагать;
- sensitivity и encryption requirements;
- default TTL и maximum retention;
- export, correction и deletion paths;
- может ли запись пересекать user, project или organization boundaries.

Не храните passwords, access tokens, recovery codes, payment data, raw government IDs
и secrets как conversational memory. Используйте подходящий system of record и отдавайте
агенту только минимально нужный факт.

Delete должен охватить source record, vector и lexical indexes, summaries, caches,
нужные checkpoints и asynchronous replicas. Используйте deletion job со status и
retry. Content-free tombstone не даст запоздавшему index event создать запись снова.
Проверяйте завершение через read path, а не только успешную постановку в queue.

## Оценивайте memory как write-and-retrieval system

Соберите fixed scenarios из реальных failure shapes:

| Метрика | Что проверяет scenario |
| --- | --- |
| Write precision | Сохранены только facts, достойные retention? |
| Write recall | Сохранён explicit permitted fact? |
| Useful retrieval | Task получил релевантный active record? |
| Noise | Irrelevant memories заняли context или изменили ответ? |
| Contradiction handling | Новые или более authoritative data победили? |
| Isolation | Может ли principal получить чужой record? |
| Staleness | Исключены expired и superseded records? |
| Deletion | Удалённый content исчез со всех read surfaces? |

Добавьте adversarial cases: indirect instructions в remembered note, prompt с попыткой
сменить namespace, poisoned shared procedure и race удаления с background consolidation.
Memory store одновременно является untrusted input для модели и sensitive data для
приложения.

## Production checklist

- [ ] Working state, thread checkpoints, long-term memory и knowledge retrieval разделены.
- [ ] У durable memory есть owner, scope, provenance, timestamps и sensitivity.
- [ ] Explicit facts и inferred candidates используют разные write paths.
- [ ] Conflicts и supersession разрешаются deterministic policy.
- [ ] Identity и tenant filters выполняются до semantic search.
- [ ] Retrieval имеет фиксированный context budget и возвращает provenance.
- [ ] Workflow resume использует checkpoints и idempotency, а не summaries.
- [ ] Shared procedures проходят review и versioning.
- [ ] Correction и deletion распространяются на indexes, summaries и caches.
- [ ] Fixed tests проверяют quality, isolation, staleness и deletion.

Хорошая memory избирательна и скучна. Агент находит нужный факт, показывает его
источник, забывает его по команде и не превращает вчерашний chat в сегодняшнюю
authority.
