Дизайн conversation state
Что хранить, когда compact, как восстановить после crash, multi-session continuity. Границы сессии.
Спроектируй conversation state для {{agent_name}} ({{session_type}}). Чтобы агент выдерживал длинные диалоги, переживал crash и помнил контекст между сессиями.
Шаг 1 · Что вообще считать "состоянием"
Три слоя — путать нельзя:
- Working memory — текущий turn. Сообщения в активном window'е, tool_use results, текущий план. Volatile.
- Session memory — границы одной "встречи" (chat session, task execution). Сохраняется до завершения задачи или закрытия чата.
- Long-term memory — между сессиями. Профиль пользователя, история проектов, выученные предпочтения. Persistent storage.
Решение "что куда" — главный архитектурный выбор.
Шаг 2 · Что хранить в session state
| Поле | Зачем | Размер |
|---|---|---|
session_id | Уникальный ID для логирования и восстановления | UUID |
turn_count | Триггер для compaction | int |
messages | Полная или compacted история | bounded |
summary | Сжатая история старых turns (после compact) | ≤ 2K токенов |
pinned_facts | Критичные факты, которые НЕЛЬЗЯ потерять (user intent, decisions, IDs) | ≤ 500 токенов |
active_tools | Список tools в этой сессии (если динамический) | small |
last_checkpoint_at | Когда последний раз сохранили на диск | timestamp |
Pinned facts — самый недооценённый паттерн. Когда compact срезает history, эти факты выживают.
Шаг 3 · Когда compact (стратегии)
Compaction = заменить старые messages summary'ем, чтобы влезть в контекст.
Триггеры:
- Token budget: входной context > 70% от лимита модели → compact.
- Turn count: каждые 20 turns → compact самые старые 10.
- Semantic: новая тема → отметить boundary, старую тему compact в summary.
- Cost-based: input cost за сессию > $X → compact агрессивнее.
Двухслойный summary работает лучше плоского:
SUMMARY:
- Тема сессии: ...
- Ключевые решения: [...]
- Открытые вопросы: [...]
- Pinned facts: [...]
RECENT (последние 10 turns full text):
[user] ...
[assistant] ...
Шаг 4 · Crash recovery
Агенты падают: rate limits, network, OOM, deploy в середине запроса. Без persistence это потеря всей сессии.
Pattern: checkpoint every N turns.
async def handle_turn(session_id, user_msg):
state = await store.load(session_id)
state.messages.append(user_msg)
response = await llm.respond(state.messages)
state.messages.append(response)
state.turn_count += 1
if state.turn_count % 5 == 0:
await store.checkpoint(session_id, state)
return response
Pattern: write-ahead log для tool calls. Перед вызовом долгого tool пиши intent в БД. После crash восстанавливаешь: "ты собирался вызвать X с args Y". Иначе агент думает что tool отработал и идёт дальше — а БД не обновилась.
Шаг 5 · Multi-session continuity
Пользователь возвращается через день. Нужно ли помнить?
Зависит от типа продукта:
- Stateless chatbot (поддержка): не помнить, начать чисто. Privacy + simplicity.
- Personal assistant: помнить профиль, предпочтения, открытые задачи. Хранить в long-term memory с TTL (например, 90 дней).
- Long task (research agent, code project): обязательно. Резюме предыдущих сессий + state файлы артефактов.
Long-term memory schema:
user_profile: {preferences, communication_style, timezone}
project_context: {goals, decisions_log, glossary}
recent_sessions: [{date, summary, outcome}] // last 10
Грузить selectively, не пихать всё в каждый промпт.
Шаг 6 · Session boundary — где провести черту
Признаки конца сессии:
- Explicit: user закрыл чат / нажал "new conversation".
- Idle timeout: > N часов без активности → закрыть сессию, создать summary.
- Topic shift: classifier обнаружил смену темы > X семантической дистанции → soft boundary (summary, но та же session).
- Task completion: агент задеклалировал done.
Anti-patterns
- ❌ Хранить полную историю всех сессий в каждом промпте → context blow, cost ракетой.
- ❌ Compact без pinned facts → агент "забывает" критичные ID, решения, intent.
- ❌ Checkpoint только в конце сессии → crash посреди → потеря всего.
- ❌ Один глобальный state без session_id → multi-user agents путают контексты.
- ❌ Loading вся long-term memory в каждый промпт → дорого + privacy concerns.
- ❌ No TTL на long-term memory → 2 года назад user спрашивал про X, теперь модель упоминает X невпопад.
- ❌ Полагаться на контекст модели как на storage → 200K окно не вечно, после compact всё исчезает.
Output
Документ "State Architecture":
- Schema трёх слоёв (working / session / long-term) с конкретными полями.
- Compaction triggers и формат summary.
- Crash recovery flow с примерами кода.
- Session boundary rules.
- Privacy/retention policy для long-term memory (TTL, что хранить, что нет).
Autosave: спецификация UX
Когда сохранять (debounce / blur / interval), как индицировать (saved / saving / error), conflict resolution. Без «иногда теряется, мы исследуем».
Декомпозиция задачи на агентов
Разбить большую задачу на параллельных независимых агентов с чёткими интерфейсами.
Последовательный пайплайн агентов
Когда параллель не подходит: цепочка агентов с явными контрактами между шагами.