ИИ-агент без памяти каждый раз начинает разговор почти с нуля. Он может выполнить один запрос, но плохо держит контекст: забывает, что пользователь уже уточнил, какие данные дал, какие ограничения важны и что было сделано на предыдущем шаге. Память решает эту проблему, но ее нельзя включать “все сохранять навсегда”: так быстро появляются ошибки, лишние персональные данные и дорогой перегруженный контекст.
Короткая версия: разделите память на краткосрочную историю диалога и долгосрочные факты, храните их отдельно, добавьте правила записи, очистки и удаления, а перед ответом отдавайте модели только релевантные воспоминания.
Что мы соберем
Соберем понятную схему памяти для ИИ-агента. Она подойдет для агента поддержки, консультанта по базе знаний, ассистента в CRM, no-code агента в Flowise или кодового агента на LangGraph.
- Краткосрочная память хранит ход текущего диалога.
- Долгосрочная память хранит устойчивые факты: предпочтения, настройки, роль пользователя, важные ограничения.
- Checkpoint помогает восстановить состояние workflow или продолжить диалог.
- Правила записи не дают агенту сохранять случайные фразы как постоянную истину.
- Правила удаления нужны для приватности и исправления ошибок.
Шаг 1. Разделите типы памяти
Сначала решите, какая память вам действительно нужна. Не все нужно хранить в одном месте. История текущего чата, профиль пользователя, результат выполнения tool и RAG-контекст - это разные сущности.
- История диалога: последние сообщения в одном thread.
- Рабочая память: промежуточные данные задачи, например выбранный тариф или номер заявки.
- Долгосрочная память: устойчивые факты о пользователе или проекте.
- База знаний: документы и инструкции, которые лучше хранить через RAG, а не как “память пользователя”.
- Audit log: технический журнал действий агента, не часть промпта.
Шаг 2. Опишите, что можно сохранять
Самая частая ошибка - сохранять все подряд. Агент может неверно понять шутку, временное предпочтение или устаревшее ограничение, а потом будет повторять это в следующих сессиях. Поэтому нужна политика памяти.
- Сохранять можно: язык общения, роль пользователя, формат ответа, подтвержденные предпочтения, выбранные интеграции, постоянные ограничения.
- Не сохранять без явного разрешения: персональные данные, медицинские и финансовые детали, пароли, токены, секреты, одноразовые задачи.
- Не сохранять как факт: догадки модели, неподтвержденные выводы, результаты неудачных tool-вызовов.
- Для спорных фактов добавляйте статус: confirmed, inferred, stale, deleted.
Шаг 3. Сделайте краткосрочную память
Краткосрочная память нужна, чтобы агент понимал текущий диалог: “сделай второй вариант”, “возьми предыдущую таблицу”, “а теперь добавь это в CRM”. В LangGraph для этого используют thread-level persistence через checkpointer.
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph
checkpointer = InMemorySaver()
builder = StateGraph(...)
graph = builder.compile(checkpointer=checkpointer)
graph.invoke(
{"messages": [{"role": "user", "content": "Привет, я делаю агента поддержки"}]},
{"configurable": {"thread_id": "support-demo-1"}},
)
Для прототипа подойдет InMemorySaver. Для production используйте постоянное хранилище: Postgres, Redis, MongoDB или другое решение, которое поддерживает ваша агентная платформа.
Шаг 4. Не отправляйте всю историю в модель
Длинная история разговора быстро съедает контекстное окно и ухудшает ответы. Модель начинает видеть слишком много старого шума и хуже держит текущую задачу. Поэтому историю нужно сжимать, обрезать или выбирать по смыслу.
- Оставляйте последние N сообщений, если диалог короткий.
- Делайте summary старой части диалога, если обсуждение длинное.
- Удаляйте сообщения с секретами и временными кодами.
- Храните tool outputs отдельно и передавайте только нужные результаты.
- Считайте токены и задайте лимит на историю до вызова модели.
Шаг 5. Добавьте долгосрочную память
Долгосрочная память нужна, если агент должен помнить что-то между разными сессиями: язык пользователя, его продукт, роль, настройки, предпочитаемый формат отчета. В LangGraph для этого используют store, где данные лежат по namespace и key.
from dataclasses import dataclass
from langgraph.graph import StateGraph, MessagesState, START
from langgraph.store.memory import InMemoryStore
@dataclass
class Context:
user_id: str
store = InMemoryStore()
builder = StateGraph(MessagesState, context_schema=Context)
graph = builder.compile(store=store)
Смысл namespace простой: память одного пользователя не должна смешиваться с памятью другого. Например, namespace может выглядеть как ("user-42", "preferences") или ("company-7", "support-rules").
Шаг 6. Давайте агенту только релевантные воспоминания
Долгосрочную память не нужно целиком вставлять в каждый промпт. Перед ответом агент должен найти только те записи, которые относятся к текущему вопросу. Иначе память превращается в еще один шумный документ.
async def call_model(state: MessagesState, runtime):
user_id = runtime.context.user_id
namespace = (user_id, "memories")
memories = await runtime.store.asearch(
namespace,
query=state["messages"][-1].content,
limit=3,
)
memory_text = "\n".join(item.value["data"] for item in memories)
system_message = f"Учитывай эти подтвержденные факты о пользователе:\n{memory_text}"
# Дальше system_message передается в вызов модели вместе с текущими сообщениями.
Если память маленькая, можно начать без semantic search. Но как только записей становится много, лучше искать по смыслу и ограничивать количество воспоминаний.
Шаг 7. Добавьте отдельный шаг записи памяти
Не позволяйте агенту автоматически записывать любой текст пользователя. Лучше сделать отдельный memory writer: он анализирует диалог и решает, есть ли новый устойчивый факт. В идеале запись требует явного сигнала: “запомни”, “в дальнейшем отвечай так”, “у нас всегда используется такая схема”.
def should_save_memory(message: str) -> bool:
markers = ["запомни", "в дальнейшем", "всегда используй", "мое предпочтение"]
return any(marker in message.lower() for marker in markers)
Для production одной проверки по словам мало. Лучше использовать отдельный LLM-классификатор или строгую форму настроек, где пользователь сам подтверждает, что именно сохранить.
Шаг 8. Храните память структурно
Память в виде длинной строки быстро становится неудобной. Лучше сохранять JSON-объекты с типом, значением, датой, источником и уровнем уверенности. Тогда память можно обновлять, удалять, фильтровать и показывать пользователю.
{
"type": "preference",
"key": "answer_style",
"value": "кратко, по шагам, на русском",
"source": "user_confirmed",
"confidence": 1.0,
"created_at": "2026-05-22",
"expires_at": null
}
Если факт временный, добавьте expires_at. Например, “сегодня работаем с проектом X” не должен жить в памяти годами.
Шаг 9. Добавьте обновление и удаление памяти
Память должна быть редактируемой. Пользователь может изменить предпочтение, компания может сменить регламент, старый проект может стать неактуальным. Если память нельзя исправить, агент будет уверенно повторять прошлую ошибку.
- Команда “забудь это” должна удалять или помечать запись как deleted.
- Новая подтвержденная запись должна заменять старую по тому же key.
- У каждой записи должна быть дата обновления.
- В интерфейсе полезно показывать, что агент помнит о пользователе.
- Для чувствительных данных нужно отдельное подтверждение и политика хранения.
Шаг 10. Отделите память от RAG
RAG и память часто путают. RAG отвечает по документам: инструкции, база знаний, правила, статьи, договоры. Память отвечает по контексту пользователя или текущей задачи. Если положить документы в пользовательскую память, система станет хаотичной.
- RAG: “какие правила возврата товара действуют сейчас?”
- Память: “этот пользователь предпочитает краткие ответы”.
- RAG: “как настроить интеграцию с Bitrix24?”
- Память: “в этом проекте используется Bitrix24, а не amoCRM”.
Шаг 11. Проверьте память тестами
Память нужно тестировать отдельно от качества модели. Хороший тест проверяет не только “помнит ли агент”, но и “не запомнил ли лишнего”.
- Агент помнит подтвержденное предпочтение в новом thread.
- Агент не сохраняет секреты, токены и одноразовые коды.
- Агент забывает запись после команды пользователя.
- Агент не использует память одного пользователя для другого.
- Старое предпочтение заменяется новым.
- Длинный диалог не переполняет контекстное окно.
Шаг 12. Минимальная production-схема
Для рабочего проекта лучше сразу развести хранилища. Это не обязательно сложная архитектура, но роли должны быть понятны.
- Conversation store: история сообщений и checkpoints по thread_id.
- Memory store: долгосрочные факты по user_id, company_id или project_id.
- Vector store: база знаний и RAG-документы.
- Audit log: журнал tool-вызовов, ошибок, решений и human approval.
- Admin UI: просмотр, исправление и удаление памяти.
Мини-чеклист запуска
- Понятно, какие типы памяти есть у агента.
- Есть правила, что можно и нельзя сохранять.
- Краткосрочная история ограничена по токенам.
- Долгосрочная память хранится по namespace.
- Агент достает только релевантные воспоминания.
- Пользователь может попросить забыть запись.
- Секреты и персональные данные не попадают в память автоматически.
- RAG-документы не смешиваются с памятью пользователя.
- Есть тесты на утечки между пользователями.
Частые вопросы
Чем память отличается от контекстного окна?
Контекстное окно - это то, что модель видит прямо сейчас в одном запросе. Память - это данные, которые система хранит между запросами и при необходимости добавляет в контекст. Большое контекстное окно не заменяет управляемую память.
Нужно ли сохранять всю историю диалога?
Нет. Обычно достаточно последних сообщений, summary старой части и отдельных подтвержденных фактов. Полная история полезна для аудита, но не обязана каждый раз попадать в промпт модели.
Можно ли хранить память в векторной базе?
Можно, если нужно искать воспоминания по смыслу. Но для структурных предпочтений удобнее обычная база с ключами, датами, статусами и правами доступа. Часто используют комбинацию: JSON-хранилище плюс semantic search по длинным заметкам.
Что опаснее всего в памяти агента?
Самое опасное - сохранять неподтвержденные выводы как постоянные факты. Например, агент один раз неверно решил, что пользователь работает в определенной компании, сохранил это и начал подстраивать все ответы под ошибочный контекст.
Когда память лучше вообще не включать?
Если агент работает с одноразовыми анонимными запросами, чувствительными данными или задачей, где каждое обращение должно быть независимым. В таких случаях лучше использовать только краткосрочный session context и не сохранять долгосрочные факты.