КЛАСТЕР 02 · АГЕНТЫ КОНТЕКСТ ~16 МИНУТ
День 07 · из 35

Сохранение
контекста

В Дне 1 ты узнал, что LLM stateless. В Дне 6 — что агент работает циклом. Сегодня — как эти две идеи живут вместе. И почему «контекст» — это не туманная концепция, а конкретный массив, который ты собираешь руками каждую итерацию.

Суть урока

Память агента — это не свойство модели. Это массив messages, который твой код пересобирает перед каждой итерацией: туда кладутся все предыдущие шаги (мысли модели, вызовы инструментов, их результаты), и весь массив отправляется в LLM целиком. Модель смотрит на эту «фотографию текущего состояния» и решает, что делать дальше. Понимание этой механики — ключ к управлению агентом.

Парадокс stateless-агента

В Дне 1 был главный инсайт: модель ничего не помнит между запросами. В Дне 6 ты увидел: агент работает в цикле и явно опирается на предыдущие шаги. Как одно совместимо с другим?

Очень просто. Модель — по-прежнему stateless. Память — у твоего кода вокруг неё. Каждую итерацию цикла твой код пересобирает массив сообщений: туда кладётся вся история ходов агента до этого момента. Этот собранный массив целиком отправляется в LLM как новый запрос. Модель видит «фотографию» — и отвечает.

Память агента — это не способность модели. Это массив messages, который твой код пересобирает заново перед каждым шагом.

Из этого следует, что у тебя есть полный контроль над тем, что модель «помнит». Что ты положишь в массив — то она и увидит. Не положишь — не увидит. Положишь криво — увидит криво.

Анатомия контекста агента

В каждой итерации цикла массив сообщений выглядит примерно так:

Массив messages на 3-й итерации агента
system
Ты — агент-помощник. Доступные инструменты: web_search, fetch_url, send_email. Используй их аккуратно, сначала думай.
user
Найди новости о компании X, составь сводку, пришли на почту.
assistant · итерация 1
Думаю: сначала нужно найти новости. Вызываю web_search("компания X новости")
tool result
[10 ссылок с заголовками и snippet'ами]
assistant · итерация 2
Думаю: возьму первую ссылку, прочитаю. Вызываю fetch_url(...)
tool result
[текст статьи на 2000 слов]
assistant · итерация 3 (пишется сейчас)
...

Главные наблюдения:

  • system один, в начале. В нём описаны инструкции и инструменты агента — он стабилен на всю задачу.
  • user тоже один, изначальный. Это запрос пользователя, который запустил агента.
  • assistant и tool чередуются по итерациям. Каждая итерация добавляет ровно две новые записи: что модель решила сделать и что инструмент вернул.
  • Каждая итерация отправляет в LLM ВЕСЬ массив целиком. Это и есть «контекст». На третьей итерации модель видит и user, и предыдущие два цикла. На пятидесятой — все 50 циклов.

Кликни по табу — увидишь подробнее, что и зачем кладётся в каждую роль:

system — конституция агента

Это политика на всю задачу. Сюда идёт описание роли агента, перечень инструментов с их назначением, ограничения («не вызывай send_email больше одного раза», «не более 10 запросов»), формат внутренних размышлений.

system пишется один раз перед запуском агента и не меняется на протяжении всего цикла. Это стабильная часть контекста, по которой модель ориентируется, кто она и что ей можно.

Что важно: чем длиннее system — тем больше токенов уходит на каждую итерацию. Это плата за «правила игры». Поэтому system должен быть точным, без воды.

user — исходная задача

Запрос пользователя, который запустил агента. Кладётся один раз, в начале. В большинстве архитектур больше user-сообщений за время работы агента не появляется — только если ты делаешь интерактивного агента, который может уточнить что-то у пользователя посреди работы.

Тонкость: в продвинутых системах user-запрос предобрабатывается до того, как попасть в агента — обогащается контекстом из памяти, RAG-документами, метаданными. Об этом будет в следующих кластерах.

assistant — что модель решила на каждом шаге

На каждой итерации модель добавляет одно assistant-сообщение. В нём — её рассуждения (внутренний монолог: «нужно сделать X, потому что Y») и вызов инструмента (или финальный ответ, если задача решена).

Это история «мыслей агента». Когда на 7-й итерации модель смотрит назад, она видит, как она сама рассуждала на шагах 1-6 — и это помогает ей не повторять одни и те же ошибки и не возвращаться к уже отброшенным гипотезам.

Концептуально важное: модель видит свои прошлые ходы и должна вести себя последовательно. Если на шаге 3 она решила «попробуем подход А», на шаге 7 она не должна вдруг сказать «попробуем подход А» снова. Хороший system prompt явно про это напоминает.

tool — что вернули инструменты

После каждого вызова инструмента в массив идёт сообщение с ролью tool (или function, зависит от провайдера) — содержащее результат выполнения. Текст веб-страницы, JSON от API, содержимое файла.

На следующей итерации модель видит эти результаты как «то, что я узнала на шагах 1-N» — и принимает следующее решение на их основе.

Самая большая опасность: tool-результаты — это та часть контекста, которая растёт быстрее всего и непредсказуемо. Один fetch_url может вернуть 50 000 токенов. И это повторится на каждой следующей итерации, потому что весь массив отправляется заново. Об этом — следующий раздел.

Как контекст растёт

Самое неочевидное и самое дорогое свойство агента — контекст растёт квадратично относительно числа итераций. Не линейно. Это критически важно понять.

Почему квадратично

Представь, что каждая итерация добавляет в массив новый блок длиной N токенов (мысль модели + результат инструмента). Тогда:

  • Итерация 1: отправляется N токенов
  • Итерация 2: отправляется 2N (предыдущий шаг + новый)
  • Итерация 3: отправляется 3N
  • ...
  • Итерация 10: отправляется 10N

За 10 итераций суммарно ты отправил: N + 2N + 3N + ... + 10N = 55N токенов. Не 10N (как было бы при линейном росте), а 55N. На 20 итерациях это уже 210N. На 50 — 1275N.

!
Финансовая реальность
Если агент работает 30 итераций, и каждая добавляет в среднем 1500 токенов — на 30-й итерации ты отправляешь ~45K токенов в одном запросе. Суммарно за всю задачу — около 700K input-токенов. На gpt-4o это $1.75 за один запуск агента. На большой модели Tier 3 — $10-20. На тысячу запусков — серьёзные деньги.

Что становится критичным

Из-за квадратичного роста сразу несколько вещей становятся важными:

Бюджет

Цена

Запуск агента в 5-10 раз дороже одного обычного запроса, иногда — на порядок. Это нужно закладывать в архитектуру с самого начала.

UX

Скорость

Каждая итерация = ожидание модели. Агент с 10 итерациями работает не 1 секунду, а 20-60. Пользователю нужно показывать прогресс.

Стена

Окно контекста

Даже при 200K-токенном окне можно его исчерпать на длинной задаче. Когда упрёшься — нужны стратегии сжатия (День 9).

Качество

Lost in the middle

Чем длиннее контекст, тем хуже модель помнит то, что в его середине. На 30-й итерации модель может «забыть» важное из шага 5.

Поэтому AI-инженер, работающий с агентами, обязан думать о контексте как о ресурсе. Это не «деталь оптимизации» — это основной навык. Дни 8-10 как раз об этом.

Решения AI-инженера

Развилка 1. Хранить ли scratchpad модели

Часто на каждой итерации модель пишет внутренние рассуждения — длинные, на 300-500 токенов: «думаю, нужно сделать X, потому что Y...». Эти рассуждения помогают модели на текущем шаге, но раздувают контекст на следующих.

Решение: отделить «мысли» от «действий». В контекст на следующую итерацию класть только реально принятые решения и результаты инструментов — а длинные рассуждения сжимать или вообще обрезать. Многие фреймворки делают это автоматически.

Развилка 2. Когда обрезать «хвост»

Когда контекст приближается к окну модели — нужно что-то выбрасывать. Самое простое — выбрасывать самое старое (первые итерации). Но именно там часто лежит критически важная информация: исходный запрос, ранние находки.

Правильнее — выбрасывать наименее релевантное на данный момент: подробные тексты статей, которые уже прочитаны и из которых уже извлечены факты; промежуточные ошибочные шаги, от которых модель отказалась; повторяющиеся вызовы. Об этом подробно — в Дне 9.

Концептуальные грабли

«Модель помнит, что мы делали на шаге 3». Нет — модель видит запись о шаге 3 в массиве сообщений, который ты ей подал на 7-й итерации. Перестанешь подавать — она перестанет «помнить». Это твой массив, твоя ответственность.

Эта мысленная модель меняет всё: ты не уговариваешь модель «не забывать», ты решаешь, что в её контексте на этом шаге будет.

«Раз инструмент вернул — пусть модель видит». В итоге контекст забит сырыми данными: HTML-разметка, JSON-ответы API, длинные тексты. Модель не успевает их обрабатывать, выбирает нерелевантное, запутывается.

Привычка: результат инструмента — это сырой материал, который твой код должен обработать перед тем, как класть в контекст. Извлеки главное, отбрось мусор, ужми. Это не «фича оптимизации», это часть архитектуры агента.

Агент работает, отвечает пользователю — а ты видишь только финальный ответ. Когда он «не сработал» или сделал не то — у тебя нет данных, чтобы разобраться где именно модель свернула не туда.

Лечится привычкой: логировать каждую итерацию агента полностью — что было в reason, какой инструмент вызван, что вернулось. Это твой единственный способ отладки. Без логов агент — чёрный ящик.

Практика

Эксперимент 01 · Подсмотреть контекст агента

Открой режим разработчика в Claude / ChatGPT

В современных ассистентах есть режимы, где можно увидеть «технические детали» работы агента. В Claude — раздел «thinking» в развёрнутом виде; в ChatGPT — «Show tools». Сделай запрос, требующий нескольких шагов («найди три цены на ноутбуки и сравни»). Посмотри, как разворачивается цепочка: рассуждение → инструмент → результат → новое рассуждение → новый инструмент → ... Это и есть массив messages в действии.

Эксперимент 02 · Посчитать квадратичный рост

Прикинь стоимость на бумажке

Возьми гипотетического агента с 20 итерациями. Каждая итерация добавляет 1000 токенов (думаю + результат). На 20-й итерации в LLM улетает 20 000 input-токенов. Суммарно за всю задачу — 210 000 input-токенов. Цена на gpt-4o ~$0.50, на gpt-5 ~$2-5. Это одна задача. Прикинь, что будет на тысяче задач в день. Это даст тебе ощущение, почему в Кластере 02 столько внимания контексту.

Эксперимент 03 · «Подмени» контекст

Сделай свою «фальшивую историю»

В плейграунде вручную собери массив сообщений с несколькими assistant-сообщениями (как будто это был многоходовой диалог). Подмени один из ассистент-ответов на фальшивый — например, скажи «я уже выяснила, что ответ — 42». Запусти следующий ход. Увидишь, как модель опирается на «свои» прошлые слова, даже если они на самом деле никогда не были произнесены. Это и есть демонстрация того, что массив messages — это конструкция твоего кода, не реальная история.

Что в Дне 08
Контекст — это не абстракция. Это токены, которые превращаются в деньги, latency и качество. В Дне 8 пойдём глубже в саму единицу измерения: что такое токен, как его считать, и почему «300 слов» на разных языках — это разное число токенов.