Содержание, 6 разделов
В истории моего агента есть коммит, который я помню лучше других. Сжатие контекста работало так: старые сообщения отдавались модели на пересказ, и для результатов инструментов пересказчик видел первые пятьсот символов. Однажды он прочитал начало 32-килобайтного вывода, не нашёл там нужного маркера и записал в сводку: «маркер отсутствует». Маркер стоял в последней строке. Ложный факт пережил сообщения, из которых родился, а через несколько ходов агент уже объяснял его вызовом grep, которого никогда не было.
Это самая неприятная часть агента: что делать, когда переписка больше не помещается в модель.
Единственная память
Языковая модель не имеет состояния. Всё, что она знает о текущей задаче, лежит в переписке, которая отправляется целиком на каждом шаге. Дальше простая арифметика. Каждый прочитанный файл, каждый вывод команды, каждый ответ инструмента остаётся в контексте до конца сессии. Агент, который за час прочитал сорок файлов и двадцать раз запустил тесты, тащит всё это с собой на каждый следующий вызов.
Окна контекста при этом растут: 128 тысяч токенов стали нормой, у части моделей заявлен миллион. Возникает соблазн решить, что проблема исчезнет сама. Она не исчезает, и причины измерены.
Почему большое окно не спасает
В июле 2023 года Нельсон Лю с коллегами из Стэнфорда опубликовали работу с говорящим названием «Lost in the Middle». Они проверяли, как модели используют длинный контекст, и нашли устойчивый эффект: качество выше всего, когда нужная информация стоит в начале или в конце входа, и заметно падает, когда она оказывается в середине. Даже у моделей, специально заявленных как длинноконтекстные. Модель не читает контекст равномерно. У неё есть края, которые она видит хорошо, и середина, которая расплывается.
Два года спустя команда Chroma проверила это шире. В отчёте «Context Rot» от июля 2025 года они прогнали восемнадцать моделей, семейства Claude, GPT, Gemini и Qwen, через задачи, где менялась только длина входа. Качество деградирует с ростом длины у всех восемнадцати, даже когда окно далеко от заполнения и задача элементарна. Один отвлекающий фрагмент, похожий на нужный, уже снижает точность, четыре снижают сильнее. И самое неожиданное: на перемешанных текстах модели работали лучше, чем на логически связных. Структура, удобная человеку, модели мешает.
Anthropic в сентябре 2025 года собрала это в инженерную рамку. У модели есть бюджет внимания: каждый токен в окне его расходует, и по мере роста контекста способность точно вспомнить что-то из него падает. Отсюда принцип, который я считаю главным в этой области: контекст должен быть наименьшим набором токенов с высоким сигналом, который даёт нужный результат. Большое окно даёт место. Оно не даёт внимания.
Для агента это значит, что сжимать контекст надо задолго до переполнения и сжимать умно. Каждый лишний результат инструмента в середине переписки делает модель хуже здесь и сейчас.
Как это устроено у меня
Компакция живёт внутри того же цикла и проверяется перед каждым запросом к модели. Порог это 75% от входного бюджета, где бюджет это окно минус резерв под ответ модели. Когда порог перейдён, старая часть переписки уходит отдельным запросом на пересказ, и на её место встаёт сводка.
Сводка структурирована жёстко: цель, ограничения и предпочтения пользователя, прогресс с разделением на сделанное, текущее и заблокированное, решения с обоснованием, следующие шаги, критический контекст. Пересказчику запрещено продолжать разговор или отвечать на вопросы из него, и от него требуется сохранять дословно пути к файлам, имена функций и тексты ошибок, потому что именно это агент потом будет искать. Если компакция не первая, пересказчик получает предыдущую сводку и обновляет её на месте, перенося пункты из «в работе» в «сделано». Так сводка накапливает всю историю сессии, включая то, что было сжато в предыдущие разы.
Хвост переписки остаётся нетронутым: последние сообщения агент видит как есть. Размер хвоста считается от бюджета, около пятой части, и с потолком этого хвоста связана вторая история, которую я запомнил. Потолок был константой в 20 тысяч токенов, написанной под окно в 128 тысяч, где это шестая часть. На модели с окном в миллион та же константа означала другое: компакция срабатывала на 726 тысячах токенов и оставляла около 28, сводку и хвост. Один шаг выбрасывал 96% контекста. Теперь потолок считается как доля бюджета, с нижней границей в те же 20 тысяч и верхней в 100.
Разрез между сводкой и хвостом проходит только по границе хода, по сообщению пользователя, с которого ход начался. Причина техническая и жёсткая: результат инструмента валиден только сразу после сообщения ассистента с соответствующим вызовом, и если разрез ляжет между ними, провайдер отклонит весь запрос. Хуже того, картинка, прочитанная инструментом, приходит в переписку под видом сообщения пользователя, потому что в протоколе нет слота для изображения в результате инструмента. Такое сообщение выглядит как граница хода, не являясь ею. Разрез после него ронял сессию той же ошибкой.
И одно правило про отказы. Если пересказ не удался, сеть, провайдер, что угодно, переписка остаётся нетронутой. Раньше агент в этом случае откатывался на простое отбрасывание старых сообщений, и пользователь не мог отличить настоящую сводку от молча потерянной истории. Переполненный контекст лучше потерянного: следующий ход просто попробует сжать ещё раз.
Где компакция врёт
Сводка это генерация модели, со всеми её свойствами. Она может выдумать. И её выдумка, в отличие от обычной, переживает источник: сообщения, по которым её можно было бы проверить, уже удалены.
Случай с маркером в последней строке привёл к двум изменениям. Пересказчик теперь видит начало и конец каждого результата инструмента, с явной пометкой посередине: столько-то символов вырезано, не считай пропуск отсутствием. Конец результата обычно самое ценное, список ошибок компилятора, итог тестов, хвост файла, и раньше терялась именно эта половина. А в промпт пересказчика добавилась строка: никогда не выдумывай, как факт был установлен; записывай только то, что переписка показывает, и пиши «не проверено», где неясно.
Были и другие. Сводка сама переросла бюджет и стала раздувать контекст, который должна была сжимать. У неё появился потолок. Компакция на пустой сводке отбрасывала историю и ничего не оставляла взамен. Пустая сводка теперь отменяет компакцию. Список файлов, изменённых за сессию, попадал в сводку дважды и разъезжался. Теперь он идёт отдельным сообщением-напоминанием после сводки и в пересказ не попадает. И стоимость самого пересказа, а это реальный запрос к модели, раньше просто терялась, занижая счётчик расходов сессии на каждой компакции.
Общий вывод из этих багов: компакция это самая опасная операция в агенте, потому что она единственная уничтожает данные, и делает это руками той же модели, которую потом просят на эти данные опираться.
Не ждать переполнения
Всё описанное выше это реакция на кризис: контекст почти полон, надо срочно резать. Со временем я пришёл к тому, что ждать кризиса не нужно.
Сейчас агент отмечает пороги по мере роста контекста, для окна в 200 тысяч это 20, 40, 60 и 80%, и на каждом запускает отдельного субагента-писаря. Тот получает переписку и обновляет два файла на диске. Первый это чекпоинт сессии: что делаем, какой следующий шаг, дословная цитата пользователя о задаче, если она есть. Второй это память проекта: знание, которое переживает сессию, и для каждого пункта обязательны две строки, почему это так и как это применять. Писарю запрещено трогать код и отвечать пользователю. Он пишет файлы и останавливается.
Разделение принципиальное. Чекпоинт про эту сессию, он нужен, чтобы после компакции или перезапуска агент не начинал с нуля. Память про проект, она нужна, чтобы следующая сессия не открывала заново то, что уже стоило часа работы. Anthropic описывает похожий подход в той же статье: агент ведёт заметки вне окна контекста и подтягивает их при необходимости, а Claude Code после компакции сохраняет пять последних открытых файлов.
Смысл в том, чтобы вынести устойчивое знание наружу, пока оно ещё в контексте целиком. Вытаскивать его потом из середины, которую модель уже плохо видит, поздно.
Что из этого следует
Контекст конечен, и растущие окна этого не меняют: у модели есть бюджет внимания, и он расходуется на каждый токен. Значит, агент рано или поздно что-то забудет, и единственный вопрос: кто и как решит, что именно.
Если ничего не делать, решать будет переполнение: провайдер вернёт ошибку, и потеряется всё. Если резать механически, решать будет константа, написанная под другое окно. Если пересказывать моделью, решать будет она, со своими галлюцинациями, которые переживут источник. Я в итоге пришёл к комбинации: структурированная сводка с жёсткими правилами, нетронутый хвост, чекпоинты до кризиса и память вне контекста. Это не гарантия. Это набор мест, где решение о том, что агент забудет, принимаю я.