На коротких задачах coding-агент выглядит почти как живой разработчик: читает код, гоняет тесты, находит проблему, предлагает diff, но на длинной дистанции магия заканчивается. Стоит агенту или пользователю подмешать еще пару логов, несколько файлов "на всякий случай" или еще один MCP-сервер, и агент начинает забывать договоренности, повторять уже проверенные шаги и терять план.
Обычно это объясняют так: "модель тупит" или "надо лучше промптить", но на практике проблема часто в другом: мы складируем состояние задачи в историю чата и надеемся, что модель удержит его сама. Не удержит.
Контекст у LLM - это не бездонный мешок, а рабочая часть "памяти" модели, ее нужно проектировать: что хранить отдельно, что подмешивать just-in-time, что выбрасывать после шага и что обязательно возвращать после compaction.
В этой статье я разберу context engineering на примере coding agents, а конкретно на Claude Code: почему long context до сих пор деградирует, почему проблема особенно больно бьет по агентам, чем полезны /compact и Plan Mode, и как собрать минимальный контекстный конвейер без магии и лишней философии.
Этот текст будет полезен, если вы:
уже используете Claude Code, Cursor, Copilot Chat, OpenCode или похожие инструменты;
пробовали давать агенту задачи длиннее, чем "сделай маленький diff";
замечали, что после 10-20 шагов агент начинает "плыть";
хотите не еще один магический промпт, а инженерный минимум: артефакты, правила, хуки и политику управления контекстом.
Ниже примеры будут в основном на Claude Code, но сама проблема шире одного продукта: похожие эффекты возникают у большинства coding-агентов, которые живут в одной длинной сессии, читают код, запускают команды и накапливают историю действий.
Дальше я опираюсь на исследования long context, работы про coding-агентов и документацию Claude Code. Это разные типы источников: часть работ 2025-2026 годов пока существует как свежие preprint'ы, а docs описывают механику конкретного продукта. Но вывод у них общий: длинная агентная сессия деградирует не потому, что вы "неправильно написали промпт", а потому что рабочая память модели ограничена.
Поэтому контекст в такой задаче - это не вся история чата, а только то, что модель получает для следующего шага. Вопрос не в том, как поместить в окно побольше, а в том, как положить туда нужное.
Чтобы дальше не путаться в терминах, удобно зафиксировать четыре понятия:
Рабочий контекст (working context) - то, что модель реально видит прямо сейчас и использует для следующего шага.
Устойчивое состояние (durable state) - то, что должно переживать compaction, длинную паузу, новую сессию и смену фазы "plan -> act -> review".
Compaction - освобождение места за счет очистки старых tool outputs и сжатия истории разговора.
Re-inject - повторное подмешивание критичного состояния после compaction или при старте новой сессии.
Контекст не копится. Он компилируется под следующий шаг.
Одна из первых широко цитируемых работ, которая хорошо показывает проблему длинного контекста, - это Lost in the Middle. В ней авторы показали, что модель может заметно хуже использовать релевантную информацию, если нужный фрагмент находится в середине длинного ввода, а не в начале или в конце.
Более свежие работы только усиливают этот вывод.
Context Rot показывает, что даже рост числа входных токенов сам по себе начинает подъедать качество, даже когда сама задача не становится сложнее. Проблема не только в "очень длинных документах", а в самом факте разрастания входа.
NoLiMa убирает прямой lexical overlap между вопросом и нужным фрагментом и показывает, насколько быстро модели теряют надежность, когда нельзя просто зацепиться за буквальное совпадение слов.
На коде все выглядит еще интереснее.
LongCodeU показывает просадку на задачах понимания длинного кода задолго до маркетинговых размеров окна.
ContextBench смотрит не только на финальный "решил / не решил", но и на то, как coding-агент вообще добывает контекст: один из неприятных выводов в том, что между тем, что агент исследовал, и тем, что он реально использовал, остается заметный зазор.
LongCLI-Bench показывает, что long-horizon программирование остается тяжелой задачей даже для frontier-систем: а human-agent collaboration даёт более заметный прирост.
Если подвести итог по этим работам, получится очень простой вывод:
Когда мы говорим "длинный контекст", легко представить один большой документ, но у coding-агента контекст растет иначе. Он раздувается не только текстом-кодом, но и всем процессом работы:
историей диалога;
кусками файлов и результатами поиска;
выводом тестов и shell-команд;
CLAUDE.md;
загруженными skills;
определениями инструментов из MCP;
промежуточными summary;
уже проверенными гипотезами и планами.
В документации How Claude Code works система описана как цикл gather context -> take action -> verify results -> repeat. Туда же в явном виде попадают история разговора, содержимое файлов, вывод команд, CLAUDE.md, skills и системные инструкции. Отдельно оговаривается, что MCP-серверы добавляют определения инструментов в запросы и тоже расходуют контекст.
Именно поэтому для coding-агентов проблема long context ощущается особенно резко. Через 15-20 шагов в "окне" у вас уже живут не задача и доказательства, а история исследования. И если эта история не вычищается и не выносится в устойчивые артефакты, сессия почти неизбежно начинает дрейфовать.
На длинной сессии первый и естественный подход - /compact. И да, он действительно полезен - помогает продолжить работу, когда окно уже подходит к пределу.
Но важно понимать, какую задачу он решает. В Claude Code compaction - это прежде всего механизм освобождения места. В официальной документации прямо сказано: когда контекст заполняется, система сначала чистит старые tool outputs, а затем суммаризирует разговор. Одновременно документация предупреждает, что ранние инструкции из разговора могут потеряться, и рекомендует держать persistent rules в CLAUDE.md.
То есть /compact - это, по сути, сборщик мусора, а не архитектура памяти.
Это хорошо совпадает и с работами про управление контекстом. Например, The Complexity Trap показывает, что сложная LLM-суммаризация истории не всегда принципиально лучше простой очистки старого шума. А Context as a Tool предлагает смотреть на контекст как на отдельный рабочий инструмент, а не как на append-only ленту истории.
Практический вывод здесь очень простой:
Plan Mode в Claude Code - однозначно полезный режим. Он переводит агента в read-only работу: сначала разобраться, собрать план, только потом переходить к изменениям. В документации это описано в том же разделе How Claude Code works.
Для сложных задач это уже хороший шаг: вы отделяете фазу исследования от фазы правок и снижаете риск того, что агент сразу полезет "чинить как видит".
Но у Plan Mode есть важное ограничение: он дисциплинирует поведение, но не решает проблему работы с памятью.
Если план живет только в сообщениях, то:
compaction его размоет;
новая сессия не гарантирует, что агент снова соберет тот же state;
в длинной сессии план начнет дрейфовать вместе с остальным контекстом.
В issue tracker Claude Code есть показательный кейс #26061, где после context compression терялся workflow state вида plan approved -> implementation in progress. Это в некотором виде является хорошим сигналом, что хранить состояние процесса только в истории диалога - плохая идея.
Если совсем коротко, формула такая:
Plan Mode полезен как режим исследования;
/compact полезен как механизм очистки;
но устойчивость длинной coding-сессии появляется только тогда, когда у вас есть внешнее состояние и явная политика контекста.
Если упростить до одной фразы:
Prompt engineering - это что сказать модели.
Context engineering - это что именно положить модели в рабочее окно на текущем шаге, что оставить снаружи как срез некоторого состояния, что выбросить и что вернуть после compaction.
Но для больших задач этого определения уже мало, на практике context engineering для coding-агентов - это не "чуть лучше собрать промпт", а построить для агента управляемую память.
У большой задачи почти всегда есть два разных слоя:
Рабочий контекст текущего шага - файлы, фрагменты кода, вывод команды, кусок лога, текущая цель.
Устойчивое состояние задачи - план, текущая фаза, уже принятые ограничения, подтвержденные факты, опровергнутые гипотезы, ссылки на полные логи и артефакты.
Проблема в том, что в реальной сессии эти два слоя очень легко слипаются и чат начинает играть сразу три роли:
интерфейса управления;
временного рабочего окна;
хранилища истины о задаче.
Именно в этот момент длинная сессия начинает деградировать, а чем дольше вы работаете, тем больше "история" вытесняет из окна "состояние задачи".
Поэтому context engineering - это в первую очередь дисциплина разделения:
что должно жить в рабочем окне только сейчас;
что должно жить вне окна постоянно;
что нужно удалять сразу после шага;
что нужно возвращать после compaction или новой сессии;
что лучше изолировать в самостоятельную логику, например в subagent или skill.
Если смотреть совсем прагматично, у context engineering для coding-агентов есть пять обязательных решений.
Если план, ограничения и подтвержденные факты живут только в переписке, то после 10-20 шагов они уже не являются надежным состоянием. Значит, нужен внешний источник истины: PLAN.md, TODO.md, DECISIONS.md, EVIDENCE.md, лог-файлы, issue, ADR или любой другой устойчивый артефакт.
Окно не должно получать "всю историю", оно должно получать только то, что нужно для следующего действия: короткий фрагмент кода, сжатую выжимку из лога, текущий шаг, ограничения и пару проверенных фактов.
Большая часть tool outputs полезна ровно один раз, например полный stack trace, огромный grep, verbose stdout и длинный diff редко нужны модели целиком на следующем шаге. Их надо выносить в файл, а в окно оставлять summary.
Compaction освобождает место, но не гарантирует сохранность workflow state, поэтому нужно заранее определить минимальный пакет re-inject: текущая фаза, активный TODO, ключевые решения, может быть 3-5 строк последнего подтвержденного summary.
Исследование большого репозитория, чтение длинных логов, code review, сравнение вариантов исправления - это кандидаты на отдельную логику работы. Их удобно выносить в subagents, skills или хотя бы в отдельную свежую сессию.
Именно поэтому для длинных задач context engineering - это не nice-to-have и не "продвинутый стиль работы", а это обязательная инженерная практика и как только задача перестает быть маленьким diff'ом, вы уже работаете не только с моделью, но и с ее памятью.
В этом смысле контекстный конвейер выглядит примерно так:
rules -> state -> JIT retrieval -> pruning -> compaction policy -> re-inject -> isolation
Это и есть минимальная рабочая модель, которая отделяет длинную агентную задачу от просто длинного чата.
Где именно ломается длинная сессияЕсли посмотреть на реальные длинные coding-сессии, симптомы обычно повторяются.
|
Симптом |
Что это обычно значит |
Практичная контрмера |
|---|---|---|
|
Агент повторяет уже проверенные шаги |
Подтвержденные гипотезы и решения остались только в чате |
Вынести факты в |
|
Агент читает много, но принимает решение по случайному куску |
Рабочий контекст слишком шумный, а точность отбора слишком низкая |
Использовать JIT retrieval: |
|
После |
Сжатие истории может подтереть важные детали |
Делать re-inject критичного состояния |
|
Plan Mode был, план вроде есть, а дальше все равно начинается дрейф |
План живет в сообщениях, а не во внешнем состоянии |
Держать фазу и текущий шаг в |
Представьте задачу: агент чинит падение checkout для пользователей с просроченной картой.
Плохой процесс обычно выглядит так:
полный stack trace вставили в чат;
план согласовали сообщением выше;
по дороге накопились три гипотезы, две из которых уже опровергнуты;
после /compact агент помнит, что "что-то сломано в платежах", но уже не помнит, что именно исключили и на каком этапе находится.
Хороший процесс выглядит иначе:
полный stack trace ушел в logs/checkout-expired-card.txt;
краткое summary и путь к логу попали в EVIDENCE.md;
текущая фаза записана в PLAN.md;
активный шаг лежит в TODO.md;
опровергнутые гипотезы зафиксированы в DECISIONS.md;
после compaction хук автоматически возвращает текущий шаг и ключевые решения в окно.
В первом случае чат становится свалкой состояния, во втором - управляющей плоскостью.
Что лечит: потерю task state после длинной сессии, /compact или новой сессии.
Правило: чат - не источник истины. Источник истины - внешние артефакты.
PLAN.md - фазы работ
TODO.md - активные шаги
DECISIONS.md - принятые ограничения и rejected paths
EVIDENCE.md - подтвержденные факты и ссылки на логи
logs/ - сырые outputs
repo/ ├── CLAUDE.md ├── PLAN.md ├── TODO.md ├── DECISIONS.md ├── EVIDENCE.md └── logs/
# TODO.md - [ ] Воспроизвести падение checkout на expired card - [ ] Найти точку, где появляется ожидаемый тип ошибки - [ ] Обновить тест - [ ] Подготовить минимальный diff
Сначала синхронизируй внешнее состояние задачи. 1. Прочитай `CLAUDE.md`, `PLAN.md`, `TODO.md`, `DECISIONS.md`, `EVIDENCE.md` 2. Если файлов нет - создай минимальный каркас 3. Не храни утвержденный план, решения и подтвержденные выводы только в чате 4. После каждого завершенного шага обновляй соответствующий файл 5. В ответе возвращай только: - что сделал - что узнал - что следующее
Что лечит: context explosion из-за длинных логов, stack traces и verbose stdout.
Правило: полный stdout - в файл. В окно - только summary и путь к полному выводу.
полный вывод -> logs/...
в чат -> 5-8 строк summary
в EVIDENCE.md -> выжимка + путь к файлу
npm test -- checkoutExpiredCard > logs/checkout-expired-card.txt 2>&1 tail -n 80 logs/checkout-expired-card.txt
После команды: 1. Прочитай последние 80 строк `logs/checkout-expired-card.txt` 2. Выдели 3-5 строк с причиной падения 3. Обнови `EVIDENCE.md` 4. В чат верни только короткую выжимку и путь к файлу
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": ".claude/hooks/block-noisy-bash.sh" } ] } ] } }
#!/usr/bin/env bash set -euo pipefail INPUT=$(cat) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""') if [[ "$COMMAND" =~ (pytest|npm\ test|pnpm\ test|go\ test|cargo\ test) ]] && \ [[ ! "$COMMAND" =~ (>\ |tee\ |2>&1) ]]; then echo "Long test output must be redirected to logs/... and summarized instead of being printed into chat." >&2 exit 2 fi exit 0
Что лечит: низкую точность отбора контекста.
Правило: сначала сузить область поиска, потом читать.
один проход поиска
не больше 5 файлов до первого summary
не больше ~200 строк на файл
сначала карта потока, потом следующее чтение
Не читай весь репозиторий. Сначала сделай короткий JIT retrieval: 1. Один проход поиска по коду 2. Открой не больше 5 файлов 3. Читай не больше ~200 строк на файл до первого summary 4. После этого остановись и верни: - карту потока - ключевые точки входа - какие файлы действительно релевантны - что читать следующим шагом
# .claude/skills/trace-flow/SKILL.md --- name: trace-flow description: Find the minimal set of files for a code path context: fork agent: Explore disable-model-invocation: true allowed-tools: Read, Grep, Glob --- Research $ARGUMENTS using the smallest possible context. Rules: 1. Start with search 2. Open at most 5 files 3. Quote file paths and line ranges 4. Return: - likely entrypoints - key callees - missing links - next best search
/trace-flow checkout expired card validation path
Что лечит: постоянный налог на context window.
Правило: CLAUDE.md - это always-on rules, а не wiki проекта.
Оставлять в CLAUDE.md стоит только:
workflow rules
build/test команды
архитектурные ограничения
формат артефактов
compact instructions
# CLAUDE.md ## Workflow - Before starting, read `PLAN.md`, `TODO.md`, `DECISIONS.md` - Do not paste long logs into chat; save them to `logs/` and summarize - After each verified step, update `EVIDENCE.md` ## Commands - Test: `pnpm test` - Lint: `pnpm lint` - Typecheck: `pnpm typecheck` ## Constraints - Do not change public API without approval - Prefer the smallest safe diff - Do not touch retry logic outside `src/payments/` ## Compact Instructions - Preserve current phase from `PLAN.md` - Preserve active items from `TODO.md` - Preserve key decisions from `DECISIONS.md` - Preserve latest verified findings from `EVIDENCE.md`
Сожми текущий `CLAUDE.md` до короткого high-signal файла. Оставь только: - always-on workflow rules - build/test commands - architectural constraints - compact instructions - правила работы с `PLAN.md` / `TODO.md` / `DECISIONS.md` Все длинные reference-материалы вынеси в отдельные files или skills.
Что лечит: потерю workflow state после /compact.
Правило: compaction не восстанавливает state. Если state важен, его нужно вернуть явно.
Минимальный пакет re-inject:
текущая фаза
активный TODO
ключевые решения
последние подтвержденные выводы
{ "hooks": { "SessionStart": [ { "matcher": "compact", "hooks": [ { "type": "command", "command": ".claude/hooks/reinject-state.sh" } ] } ] } }
#!/usr/bin/env bash set -euo pipefail echo "Re-read project state before next action." echo echo "Current phase:" sed -n '/^## Current phase/,+3p' PLAN.md 2>/dev/null || true echo echo "Active TODO:" sed -n '1,12p' TODO.md 2>/dev/null || true echo echo "Key decisions:" sed -n '1,10p' DECISIONS.md 2>/dev/null || true echo echo "Latest evidence:" sed -n '1,8p' EVIDENCE.md 2>/dev/null || true
/compact focus on current bug, active TODO, rejected hypotheses, and failing test path
Что лечит: смешивание основного рабочего воркфлоу с тяжелым исследованием.
Правило: все, что требует длинного чтения или отдельного ресерча, должно находится в отдельном окне.
Подходит для:
длинных логов
code review
поиска root cause
исследования большого репозитория
сравнения вариантов исправления
# .claude/agents/log-investigator.md --- name: log-investigator description: Read long logs and return root cause, not transcript permissionMode: plan --- Investigate large logs and return only: 1. probable root cause 2. exact file paths / stack frames 3. strongest next action Do not modify files. Do not paste long excerpts unless strictly necessary.
Use the log-investigator subagent on `logs/checkout-expired-card.txt` and return only root cause + next step.
# .claude/skills/research-bug/SKILL.md --- name: research-bug description: Investigate a bug in an isolated context context: fork agent: Explore disable-model-invocation: true --- Investigate bug: $ARGUMENTS Process: 1. Find the smallest relevant set of files 2. Read logs only as needed 3. Return: - root cause hypothesis - strongest supporting evidence - missing information - next best check
/research-bug checkout expired card failure
вынести план из чата в PLAN.md;
вынести решения в DECISIONS.md;
перестать хранить длинные логи в сообщениях чата;
сократить CLAUDE.md до короткого high-signal файла;
добавить re-inject после compaction;
вынести хотя бы одну шумную исследовательскую подзадачу в subagent;
между несвязанными задачами использовать новую сессию или /clear, а не один бесконечный чат.
Этого уже хватает, чтобы coding-агент реже "забывал, где находится", и чаще принимал решения по фактам, а не по шуму "чата".
В основе большинства провалов длинной агентной сессии лежат две проблемы.
Первая - рабочий контекст быстро превращается в шум. Туда попадают длинные логи, лишние файлы, старые tool outputs, промежуточные гипотезы и куски прошлых решений. Модель формально "видит много", но использовать этот массив надежно уже не может, отсюда повторные шаги, случайные решения по нерелевантным кускам и дрейф после compaction.
Вторая - состояние задачи слишком часто живет только в чате. План, текущая фаза, подтвержденные факты, опровергнутые гипотезы и принятые ограничения остаются внутри истории диалога, хотя именно они должны переживать compaction и новую сессию. В результате агент теряет не только детали, но и сам workflow state.
Из первой проблемы следует необходимость pruning, JIT retrieval и изоляции шума. Из второй - необходимость устойчивого состояния, внешних артефактов и re-inject критичного контекста.
Именно на пересечении этих двух задач и появляется context engineering, это не украшение поверх prompt engineering и не "продвинутая техника для энтузиастов". Для больших задач context engineering - обязательный подход к работе, как только вы просите агента не просто сделать маленький diff, а пройти длинный инженерный флоу, вы обязаны управлять его "памятью" так же внимательно, как управляете кодом, тестами и архитектурными ограничениями.
Большие задачи у coding-агентов выигрывают не от максимального объема контекста, а от правильной организации контекста и в этом смысле самый важный сдвиг очень простой: перестать воспринимать чат как хранилище истины и начать строить контекстный конвейер.
Источник


