Если вы когда-нибудь зубрили материал перед экзаменом в последнюю ночь, то знакомы с этим чувством: чем больше учишь, тем быстрее забываются первые главы.
У агентов та же проблема. По мере выполнения длительных задач они накапливают все больше информации (инструкций, результатов работы инструментов, файлов и т. д.); в конечном итоге это становится слишком большим объемом данных, чтобы комфортно уместиться в контекстном окне модели. Чем больше истории, «шума» и вывода инструментов содержит модель, тем хуже становятся ее точность и способность к рассуждению.
В мире разработки агентов мы называем это «контекстным гниением». В этом блоге рассматриваются методы управления контекстным окном вашего агента, а также то, как обвязка Deep Agents использует концепцию промежуточного ПО (middleware) для внедрения этих методов в процесс работы агента.
Понимание методов проектирования контекста
Проще говоря, агент — это просто модель с «обвязкой» вокруг нее.
Методы проектирования контекста, доступные агенту для борьбы с «контекстным гниением», в основном делятся на две категории:
- Предотвращение попадания ненужной информации в контекстное окно
- Управление и фильтрация того, что уже находится в контекстном окне
Обвязка стратегически применяет эти методы, чтобы предоставить модели нужный контекст в нужное время для конкретной задачи.
Настроить обвязку, которая делает это эффективно, легче сказать, чем сделать, и это требует много работы (возможно, слишком много, если вы из тех, кто зубрит перед экзаменом в последнюю ночь).
Deep Agents — это open source обвязка от LangChain. Она дополняет выбранную вами модель методами, которые перемещают контекст из активного окна (в файлы, сводки или отдельному агенту), чтобы основной агент оперировал только тем, что ему нужно (и мог при необходимости восстановить исходные данные):
- Выгрузка (Offloading): результаты работы крупных инструментов и сообщения пользователей сохраняются в файловой системе, а модель видит только превью.
- Суммаризация: когда диалог приближается к лимиту контекста, старые сообщения сжимаются в краткое содержание.
- Навыки (Skills): ноу-хау для задач загружаются только тогда, когда модель решает, что это актуально.
- Субагенты: «шумная» работа выполняется в отдельном контекстном окне, а возвращается только результат.
- Долговременная память: то, что агент узнает, сохраняется в файл, который переносится в следующий диалог.
Применение проектирования контекста к типичным сценариям использования
Давайте посмотрим, как описанные выше методы можно применить в реальном сценарии: агент для конкурентного анализа. Каждый понедельник этот агент исследует пять конкурентов и пишет отчет по шаблону команды. Один цикл работы выглядит примерно так:
- Выгрузка данных о рынке для Компании А (десятки тысяч строк)
- Поиск новостей, чтение нескольких статей и создание заметок
- Повторение действий для Компаний от B до E
- Написание черновика отчета, его доработка на основе ваших отзывов и форматирование
К 4-му шагу агент пронес через каждый вызов модели пять необработанных выгрузок, десятки результатов поиска и два устаревших черновика. Большая часть этого не имеет отношения к форматированию финального отчета.
Методы поиска (RAG или поиск по файловой системе) помогают агенту извлекать только то, что нужно, но это решает проблему лишь наполовину. Даже точный агент накапливает ненужные сообщения, результаты инструментов и промежуточные наработки, поэтому обвязка также должна управлять тем, что уже находится внутри и вокруг контекстного окна.
Как реализовать эти методы: промежуточное ПО (middleware)
Агент работает в цикле: модель решает, что делать, вызывает инструмент, считывает результат и повторяет это до завершения задачи. Промежуточное ПО — это код, который подключается к определенным точкам этого цикла: например, перед запуском агента, вокруг каждого вызова модели или вокруг каждого вызова инструмента.
- В каждой такой точке он может прочитать контекст и изменить его перед выполнением следующего шага.
- Каждый метод проектирования контекста в этой статье — это фрагмент промежуточного ПО, подключенный к одной из таких точек. Большая часть функционала встроена, поэтому вам не нужно писать собственное промежуточное ПО для использования этих методов (если только вы не хотите настроить что-то специфическое).
- Большая часть функционала встроена, поэтому вам не нужно писать собственное промежуточное ПО для использования этих методов (если только вы не хотите настроить что-то специфическое).
Выгрузка: хранение данных вне контекстного окна
Нашему агенту не всегда нужно видеть все данные, возвращаемые каждым вызовом инструмента или сообщением человека, особенно если их объем велик.
Например, каждый вызов инструмента pull_market_report возвращает полную выгрузку данных (тысячи строк); однако агенту нужны лишь несколько чисел из нее, поэтому модель можно ограничить так, чтобы она видела только эти строки.
FilesystemMiddleware запускается каждый раз при вызове инструмента:
- Когда результат работы инструмента превышает примерно 20 000 токенов, полный результат записывается в /large_tool_results/{tool_call_id} до того, как он попадет в диалог.
- Модель видит только короткое превью (первые и последние несколько строк) плюс путь к файлу.
- Когда агенту позже понадобится квартальная выручка Компании B, он просматривает файл с помощью read_file.
Слишком длинные сообщения пользователя, например, вставленная расшифровка звонка, обрабатываются так же, но с более высоким порогом (50 000 токенов) и сохраняются в /conversation_history/.
Суммаризация: сжатие того, что уже есть
Как бы мы ни старались выгружать объемные результаты работы инструментов, контекст будет постепенно накапливаться в течение долгого цикла (например, поиск, заметки и черновики по пяти компаниям). Суммаризацию можно использовать для сжатия всего контекстного окна агента в краткое содержание того, что произошло к настоящему моменту, чтобы позволить ему продолжить исследовательские задачи.
- Пики — это поступление больших результатов инструментов/сообщений человека; выгрузка заменяет каждое из них коротким превью до того, как модель их увидит, поэтому контекст растет лишь незначительно.
- Суммаризация справляется с медленным ростом: как только использование достигает 85%, старые сообщения сжимаются в сводку, и объем контекста снова падает.
SummarizationMiddleware проверяет использование токенов прямо перед каждым вызовом модели:
- Как только использование превышает порог (по умолчанию 85% контекстного окна модели), отдельный вызов LLM сжимает старые сообщения в единую сводку.
- Старые сообщения удаляются из контекстного окна, а самые недавние сохраняются дословно.
- Модель теперь видит сначала сводку, а затем недавние сообщения (поэтому ничего недавнего не перефразируется).
Две важные детали:
- Это восстановимо. Сжатые сообщения записываются в /conversation_history/{session_id}.md. Если агенту при написании отчета понадобится деталь из исследования Компании А, он может прочитать ее обратно.
- Это циклично. По мере продолжения работы использование снова растет, и следующая сводка включает в себя предыдущую.
Вы также можете выполнять суммаризацию при смене темы, а не только при достижении определенного порога токенов. Может быть полезно настроить промпт для суммаризации.
Наша статья об управлении контекстом для Deep Agents подробно освещает оба аспекта.
Навыки: загрузка информации только тогда, когда она нужна
Допустим, у вашего отдела продаж есть специфический формат для квартальных бизнес-обзоров. Агенту эти инструкции нужны только раз в квартал, поэтому хранение их в системном промпте означает оплату за них (токенами и временем ответа) при каждом вызове. Вместо этого вы можете упаковать эту информацию как навык.
Навык — это папка с инструкциями (с дополнительными скриптами и справочными документами), которые дают агенту то, что ему нужно для специализированной задачи.
Агент видит краткое описание заранее и загружает полные инструкции для qbr-report только тогда, когда запрашивается QBR (другие задачи их никогда не содержат).
Навыки загружают контекст слоями, поэтому окно остается небольшим, пока что-то действительно не станет релевантным. Это называется прогрессивным раскрытием: модель видит «меню» в начале и запрашивает полный рецепт, когда он ей нужен, поэтому десять навыков обходятся примерно в ту же стоимость контекста, что и десять однострочников.
Вы указываете агенту на свои навыки, а SkillsMiddleware использует два хука:
- Перед запуском агент сканирует папку навыков и читает только заголовок каждого файла SKILL.md.
- При каждом вызове модели он добавляет эти имена и описания в системный промпт.
Полные инструкции попадают в контекст только тогда, когда модель решает, что навык релевантен (и считывает его с помощью инструмента read_file), поэтому наш агент проводит исследование без шаблона и загружает его только тогда, когда приходит время форматировать QBR.
Субагенты: изоляция шумной работы
Выгрузка эффективно борется с избыточными результатами, но субагенты — это хорошее проектное решение для работы, которая, как вы знаете, будет «шумной» (например, исследование компании по десяткам поисковых запросов и страниц). Субагент выполняет эту работу в собственном окне контекста и возвращает только финальный результат, так что главный агент никогда не видит «шума».
SubAgentMiddleware позволяет нам настраивать системный промпт и инструменты, доступные нашим субагентам.
В нашем случае главный агент передает каждую компанию субагенту-исследователю рынка.
Субагент-исследователь читает полный отчет в своем собственном контексте и возвращает всего три пункта, поэтому главный агент видит только эти три пункта (даже не превью необработанного отчета). Кроме того, поскольку задачи субагентов, как правило, невелики и имеют четкие границы, они часто могут работать на более дешевой модели и параллельно.
Долгосрочная память: сохранение информации между разговорами
К концу работы ваш агент узнает много нового. Что-то из этого полезно, что-то нет.
Допустим, вы говорите агенту: «Используйте маркированные списки в резюме, а не абзацы». Без памяти вам придется повторять это каждую неделю. В Deep Agents долгосрочная память представляет собой файл Markdown. Вы указываете на него агенту с помощью одного аргумента, а MemoryMiddleware берет остальное на себя:
- Загрузка: файл считывается в начале запуска.
- Внедрение: его содержимое добавляется в системный промпт при каждом вызове модели.
- Обновление: когда агент узнает что-то, что стоит сохранить, например ваши предпочтения по форматированию, он обновляет файл.
Смените модель, сохраните память
Deep Agents не зависит от конкретного провайдера, и это распространяется на память. Поскольку память представляет собой простой файл в вашем собственном хранилище (а не то, что удерживает провайдер), вы можете перенаправить тот же бэкенд на другую модель:
На следующей неделе другая модель сможет прочитать тот же файл и все равно написать резюме в виде списков.
Стратегии проектирования контекста, о которых следует помнить
Создаете ли вы решения на базе Deep Agents, используете другой инструмент или создаете его самостоятельно, вот на что следует обратить внимание:
- Большие объемы входных данных должны выгружаться, а не усекаться. Усечение приводит к потере данных; выгрузка сохраняет возможность их получения.
- Сжатие должно быть обратимым. После суммирования агент все равно может получить необходимую ему детализацию.
- Ноу-хау должны загружаться по требованию. Инструкции для каждой задачи в системном промпте расходуют контекст при каждом вызове.
- Шумную работу следует изолировать. Субагенты с собственным контекстом позволяют главному агенту сохранять фокус.
- Вы должны владеть памятью. Память в контролируемом вами хранилище переживет смену модели или провайдера.
- Значения по умолчанию должны быть настраиваемыми. Пороговые значения, которые подходят для одной задачи, редко подходят для любой другой.
Попробуйте
Хотите узнать больше от живого преподавателя? Я буду рассказывать об этом 3 ноября: Зарегистрируйтесь ЗДЕСЬ!











