Почему AI-агенты игнорируют инструкции пользователя
Агенты часто игнорируют правила из-за переполнения контекстного окна или логических противоречий в коде. Узнайте, как провести диагностику и исправить работу Claude Code.
Почему агенты для написания кода игнорируют ваши инструкции
Агенты для написания кода игнорируют ваши инструкции по четырем причинам, и ни одна из них не связана с тем, что вы были слишком вежливы. Правило не попало в контекстное окно. Правило было слишком расплывчатым, чтобы проверить по нему действие. Что-то другое в контексте противоречило ему — обычно это код, который агент только что прочитал. Или правило все еще загружено, но находится далеко за пределами текущего шага, а агент работает с тем, что находится рядом.
У каждой причины есть свое решение, поэтому первая задача — научиться их различать. Заглавные буквы и слово IMPORTANT не являются диагностикой. В механике ниже в качестве примера используется Claude Code, поскольку его поведение при загрузке и сжатии данных подробно задокументировано по состоянию на август 2026 года. Другие инструменты отличаются в деталях, но в общих чертах работают так же.
Сначала определим два термина. Контекстное окно — это блок текста, который модель видит на конкретном шаге: системный промпт, ваши файлы с инструкциями, история диалога и каждый файл, который агент прочитал. Обвязка (harness) — это программа вокруг модели, которая считывает файлы с диска и собирает этот блок. Почти каждая жалоба в этом тексте на самом деле является жалобой на обвязку, а не на модель.
Файл инструкций — это сообщение, а не настройка
Файл инструкций не является конфигурацией. Среда выполнения не считывает CLAUDE.md и не принуждает к его исполнению. Инструментарий считывает файл с диска и вставляет текст в диалог. В Claude Code это содержимое передается как сообщение пользователя, размещенное после системного промпта. Это означает, что модель воспринимает ваши правила так же, как и любой другой введенный вами текст.
У этого есть неприятное следствие. Ваши правила конкурируют с любым другим текстом в окне на равных основаниях. Правило — это утверждение. Файл, который агент только что открыл, — это доказательство. Когда они противоречат друг другу, доказательство часто побеждает, и никакой ошибки не возникает, так как с точки зрения модели ничего не пошло не так.
Официальная документация прямо говорит об этом: файлы инструкций рассматриваются как контекст, а не как принудительная конфигурация. Чтобы заблокировать действие независимо от решения модели, вам нужен хук, а не предложение. Запомните это правило. Большинство исправлений в конце этой статьи представляют собой применение этого принципа к конкретному случаю.
Which instruction files load, and when
Claude Code walks up the directory tree from the directory you started it in. Every CLAUDE.md and CLAUDE.local.md from the filesystem root down to your working directory loads in full at launch. They are concatenated in that order, so the file closest to where you launched is read last, and within one directory the .local file is appended after the main one.
Files in subdirectories below your working directory behave differently. They do not load at launch. They load when the agent reads a file in that directory. The same is true of path scoped rules in .claude/rules/ that carry a paths: frontmatter field: they enter the context when a matching file is read, not on every turn.
That one difference explains a large share of reported failures. You put a rule in packages/api/CLAUDE.md, you ask a question about the API, and the agent answers without ever opening a file under packages/api/. The rule was not ignored. It was never present. If your repository splits guidance across per package instruction files in a monorepo, this is the first thing to check, every time.
One more loading trap, and it is the most common version of "the agent ignored my instructions": Claude Code reads CLAUDE.md, not AGENTS.md. A repository that standardised on AGENTS.md and has no CLAUDE.md gives Claude Code nothing to load at all. The supported bridge is a CLAUDE.md whose first line is @AGENTS.md, which imports the file at launch, with any Claude specific notes underneath. A symlink works too when you have nothing extra to add. Deciding what belongs in that file in the first place is a separate question, covered in splitting agent instructions from human documentation.
Подтверждение загрузки файла перед его перезаписью
Не меняйте содержимое файла, пока не убедитесь, что агент видит этот файл. Существует две проверки, и сначала следует выполнить более простую.
Выполните /context внутри сессии. Команда выводит текущее окно, разбитое по категориям, а список Memory files содержит названия всех файлов инструкций, которые были успешно загружены. Если файла нет в этом списке, значит, он не находится в контексте диалога, поэтому любые изменения в нём не принесут результата. /memory выводит пути к файлам и открывает их для редактирования, включая те, которые ещё не существуют.
Для более детальной проверки используйте логирование загрузок. Событие хука InstructionsLoaded срабатывает каждый раз, когда CLAUDE.md или файл правил попадает в контекст, а его сопоставитель (matcher) указывает причину загрузки: session_start, nested_traversal, path_glob_match, include или compact. Добавьте это в .claude/settings.json:
{
"hooks": {
"InstructionsLoaded": [
{
"matcher": "nested_traversal",
"hooks": [
{
"type": "command",
"command": "cat >> /tmp/instructions-loaded.log"
}
]
}
]
}
}Хук получает данные в формате JSON через стандартный поток ввода, поэтому cat дописывает всю запись целиком. Отслеживайте её с помощью tail -f /tmp/instructions-loaded.log во время работы. Код завершения этого события игнорируется, поэтому хук может только наблюдать, но не блокировать действия. Если ваш вложенный файл не появляется в этом логе в течение сессии, где вы ожидали его увидеть, прекратите редактирование. Проблема заключается в его расположении.
Как длительная сессия влияет на ваши правила
Здесь действуют два отдельных эффекта, требующих разных подходов.
Дистанция. Правило, заданное на 1-м шаге, остается в окне контекста на 90-м шаге, конкурируя с 90 шагами текста, который является более свежим и специфичным для текущей задачи. Это нельзя настроить, но можно измерить. Запустите ту же задачу в новой сессии. Если правило работает там, но перестает действовать в конце длинной сессии, причина в дистанции.
Сжатие. Когда окно заполняется, система суммирует ход беседы и продолжает работу на основе этого резюме. Сохраняется то, что алгоритм сжатия посчитал важным, а это не всегда совпадает с вашим мнением. Claude Code документирует результат для каждого механизма, и различия существенны. Корневой файл проекта CLAUDE.md и правила без области действия повторно считываются с диска после сжатия. Автоматическая память также перезагружается с диска. Правила с метаданными paths: теряются до тех пор, пока соответствующий файл не будет прочитан снова. Вложенные файлы CLAUDE.md в поддиректориях теряются до тех пор, пока не будет прочитан любой файл в этой поддиректории.
Расставьте свои инструкции согласно этой таблице, и вы увидите порядок их уязвимости. Правило, которое вы просто ввели в чат, — самое хрупкое в сессии: оно сохраняется, только если алгоритм сжатия решил его оставить. Правило в packages/api/CLAUDE.md находится на следующем уровне, так как оно было загружено один раз, удалено при сжатии и возвращается только при следующем чтении в этой директории. Правило в корневом файле проекта — самое надежное, так как оно считывается с диска каждый раз.
Поэтому, если инструкция должна действовать на протяжении всей сессии, ее следует поместить в корневой файл проекта без метаданных paths:. Все остальное — это компромисс, на который вы должны идти осознанно. В Управление содержимым окна контекста рассматриваются /compact с аргументом focus и /clear между несвязанными задачами; оба этих метода меняют частоту, с которой алгоритм сжатия принимает решения о ваших правилах.
Почему окружающий код важнее правила
Это сбой, который люди описывают чаще всего, а диагностируют реже всего. В вашем файле указано, что доступ к базе данных должен идти через уровень репозитория. Агент пишет обработчик, который вызывает ORM (объектно-реляционное отображение) напрямую. Вас проигнорировали не из-за стиля. Вас перевесили факты.
Правило описывает предпочтение. Код демонстрирует его реализацию. Когда агент открывает три файла в модуле, который собирается редактировать, и все три вызывают ORM напрямую, контекст содержит одно абстрактное предложение с одной стороны и три конкретных, актуальных, соответствующих задаче примера с другой. Копирование локального паттерна — обычно верное поведение. Здесь оно ошибочно только потому, что вы знаете то, чего не знает контекст: эти файлы являются legacy.
Поэтому запишите это в правило. Правила, которые называют свои собственные контрпримеры, выживают при столкновении с реальным репозиторием. Правила, которые просто заявляют предпочтение, — нет.
Новый доступ к базе данных должен идти черезapp/repositories/. Файлы вapp/legacy/по-прежнему вызывают ORM напрямую. Это старый код, а не паттерн. Не копируйте его.
Второе предложение выполняет всю работу. Оно говорит агенту, что именно он сейчас обнаружит и как это интерпретировать, еще до того, как он это найдет. Такое же исправление применимо к любому правилу, которому ваш репозиторий явно противоречит: стиль коммитов, которому не следует ваша история, структура тестов, которую игнорирует половина вашего набора, соглашение об импортах, которое соблюдается только в новом коде. Везде, где код не согласуется с файлом, укажите на это несоответствие в самом файле.
Нечеткое правило невозможно проверить, а значит, его нельзя соблюсти
«Пишите чистый код». «Не усложняйте архитектуру». «Придерживайтесь простоты». «Будьте осторожны при миграциях». Ни одно из этих требований нельзя проверить с помощью конкретного действия — ни агентом, ни вами. Если агент получает правило, которое он не может сопоставить со своим результатом, он начинает гадать, а вы оцениваете его догадки на основе собственных ощущений.
Вот тест, который нужно применять к каждой строке вашего файла. Напишите команду оболочки, которая завершится с ненулевым кодом, если правило нарушено. Если вы не можете написать такую команду, правило невозможно проверить. Сравните эти пары:
- Нельзя проверить: «Пишите короткие функции». Можно проверить: «Функция длиннее 60 строк должна иметь комментарий сверху с объяснением причин».
- Нельзя проверить: «Тестируйте свои изменения». Можно проверить: «Запустите
npm testи вставьте количество ошибок перед тем, как пометить задачу выполненной». - Нельзя проверить: «Держите файлы в порядке». Можно проверить: «HTTP-обработчики должны находиться в
src/api/handlers/. Никакие другие файлы не должны там размещаться». - Нельзя проверить: «Форматируйте код правильно». Можно проверить: «Используйте отступ в 2 пробела в файлах
.ts».
«Не усложняйте архитектуру» — это правило, от которого люди отказываются в первую очередь, потому что решение заключается не в сокращении предложения, а в его расширении: четкое описание того, что на самом деле означает минимально необходимое изменение дает агенту критерии, по которым он может оценить свой diff.
Размер файла — это та же проблема под другим углом. Рекомендации Claude Code нацелены на объем менее 200 строк на файл инструкций и прямо указывают, что длинные файлы снижают точность следования им. Файл на 700 строк не является более строгой инструкцией. Это 700 строк утверждений с повышенной вероятностью противоречий, которые расходуют ваше окно контекста на каждом этапе, что напрямую отражается на потреблении токенов. Структурирование файла таким образом, чтобы каждое правило находилось под заголовком, который легко просканировать взглядом, описано в написании файла инструкций, с которым может работать агент. Еще лучше — удалите части, которые описывают, а не инструктируют: обзор каталогов, где лежат обработчики и модели, — это структура, которую агент может запросить по мере необходимости из разобранной карты репозитория, вместо того чтобы постоянно держать её в окне контекста.
Как провести диагностику за десять минут
Выполняйте эти действия по порядку. Пропуск шагов до последнего — причина, по которой у пользователей накапливаются длинные списки противоречивых правил, которые всё равно не работают.
- Убедитесь, что файл загружен. Выполните
/contextи изучите список файлов в Memory. Если файла там нет, исправьте путь и остановитесь. Остальные пункты списка пока не имеют значения. - Воспроизведите проблему в новой сессии. Запустите новую сессию и выполните минимальную задачу, которая должна активировать правило. Если здесь всё работает, а в длительной сессии — нет, проблема в удалённости контекста или сжатии (compaction). Если ошибка возникает и здесь, значит, проблема в самом правиле.
- Устраните конкуренцию. Попробуйте применить то же изменение в директории, где существующий код уже соответствует правилу. Если соответствие восстановилось, значит, окружающий код «перевешивал» вашу инструкцию.
- Найдите конфликт. Наличие двух файлов с разными указаниями для одного и того же поведения — задокументированная ошибка: модель может выбрать любой из них произвольно, не сообщая вам об этом.
- Сделайте правило проверяемым и повторите тест. Перепишите правило, добавив конкретный путь и условие. Значительный рост соответствия правилу означает, что причиной была формулировка.
Шаг 4 выполняется одной командой. Ищите по всем источникам инструкций, а не только в том файле, который вы редактировали:
grep -rni "migration" --include="CLAUDE.md" --include="CLAUDE.local.md" .
grep -rni "migration" .claude/rules/ ~/.claude/CLAUDE.md ~/.claude/rules/ 2>/dev/nullНахождение двух файлов с противоречивыми указаниями — это и есть ваша ошибка. Удалите один из них. Не пытайтесь приоритизировать их с помощью более строгих формулировок, так как механизма ранжирования не существует.
Способы исправления: от простых к эффективным
Каждый последующий шаг требует больше усилий для настройки, но дает больше контроля. Начинайте с верхних пунктов, если правило легко переформулировать. Переходите к нижним, если цена ошибки становится критической.
- Сделайте правило конкретным. Укажите путь, команду или условие. Добавьте контрпримеры, которые агент может найти в репозитории, как показано ранее. Это бесплатно и решает значительную часть проблем.
- Переместите правило ближе к объекту управления. Используйте вложенный
CLAUDE.md, правило с ограничением пути в.claude/rules/или комментарий в начале самого файла. Правило будет прочитано одновременно с кодом, к которому оно относится. Учитывайте компромисс: данные, загруженные таким образом, удаляются при следующей очистке и возвращаются при следующем чтении. - Перенесите контроль в хук. Текст — это просьба. Хук — это решение. Хуки исполняются как код в определенные моменты жизненного цикла и применяются независимо от выводов модели.
- Передайте правило детерминированному инструменту и удалите текстовое описание. Это касается форматирования, порядка импортов, длины строки, запрещенных импортов и структуры сообщений коммитов. Используйте
ruff format,prettier --write,eslintили хукpre-commit. Форматировщик всегда прав и не тратит токены. Текстовая инструкция права в большинстве случаев, но потребляет токены при каждом обращении.
Разбор шага 3. Допустим, агенту запрещено редактировать файлы миграций. Добавьте это в .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/guard-migrations.sh"
}
]
}
]
}
}И это в .claude/hooks/guard-migrations.sh:
#!/usr/bin/env bash
set -euo pipefail
path=$(jq -r '.tool_input.file_path // empty')
case "$path" in
*/migrations/*)
echo "Files under migrations/ are written by hand. Stop and ask first." >&2
exit 2
;;
esac
exit 0Выполните chmod +x .claude/hooks/guard-migrations.sh, затем начните новый сеанс и попросите агента отредактировать файл в migrations/. Редактирование будет отклонено, а ваше сообщение вернется в качестве причины. Код завершения 2 в PreToolUse блокирует вызов инструмента до его запуска, а текст из stderr передается модели как сообщение о блокировке. ${CLAUDE_PROJECT_DIR} указывает на корень проекта, поэтому хук работает из любого каталога, в котором находится агент. Агенту не нужно соглашаться с правилом, помнить его или иметь в контексте. Редактирование не произойдет.
Для простого запрета без сложной логики используйте permissions.deny в настройках: это выполняет ту же задачу без необходимости поддерживать скрипты, а права доступа определяют, что будет запущено без лишних вопросов. Если инструкцию необходимо разместить на уровне системного промпта, а не в сообщении пользователя, используйте --append-system-prompt. Однако ее придется передавать при каждом вызове, что лучше подходит для скриптов, чем для интерактивной работы.
Чего нельзя добиться инструкциями
Чётко разделяйте зоны ответственности. Размещение, формулировки, конфликты между файлами и размер файлов — это проблемы автора, которые решаются автором. Остальное — это поведение модели, и лучшие формулировки его не исправят.
Согласие не означает выполнение. Агент подтвердит правило, правильно повторит его вам и нарушит через два вызова инструментов. Подтверждение ничего не стоит и ничего не гарантирует. Не воспринимайте его как исправление и не считайте его проверкой.
Некоторые привычки устойчивы. Добавление комментариев, защитная обработка ошибок, написание итогового резюме, выполнение очевидной следующей команды. Они возвращаются даже при наличии правила, запрещающего их, пусть и реже, но не исчезают совсем. Вы можете измерить частоту ошибок самостоятельно: выполните одну и ту же задачу десять раз в новых сессиях и подсчитайте нарушения. Если количество нарушений должно быть равно нулю, правило нужно убрать из промпта. Завершение задачи, когда часть работы ещё не выполнена — это привычка того же рода, и её исправление носит структурный, а не вербальный характер: навык борьбы с ленью заменяет фразу на дерево глубины и файлы-шлюзы, которые агент должен закрыть, прежде чем сможет заявить о завершении.
Ваша собственная сессия становится примером. Если агент нарушил правило на шаге 12, а вы проигнорировали это, нарушение остаётся в контексте как демонстрация, и оно гораздо свежее, чем само правило. Исправляйте нарушение в тот же момент, когда его заметили. Неисправленное нарушение обучает модель на оставшуюся часть сессии.
Файл инструкций не является границей безопасности. Он формирует поведение, но не принуждает к нему. Всё, где ошибка обходится дорого — учётные данные или деструктивные команды — должно регулироваться правами доступа или хуками. Ограничение доступа агента к секретам применяет тот же принцип к данным: не просите агента не читать файл, сделайте так, чтобы файл был недоступен для чтения.
Кратко: докажите, что файл загружен, сделайте правило проверяемым, разместите его рядом с тем, что оно регулирует, и если частота ошибок всё ещё критична — уберите правило из текста. Правило, которое агент не может проигнорировать — это правило, о котором агента никогда не просили.
FAQ
Почему Claude Code игнорирует мой CLAUDE.md?
Убедитесь, что файл был загружен, прежде чем делать вывод о том, что он игнорируется. Выполните /context и изучите список Memory files; если файла нет в этом списке, значит, он не участвует в диалоге. Файлы с инструкциями передаются как сообщение пользователя после системного промпта и рассматриваются как контекст, а не как обязательная конфигурация, поэтому строгая гарантия соблюдения правил отсутствует. В большинстве случаев проблема вызвана одной из четырех причин: файл находится в поддиректории, которую агент не просматривал; два файла содержат противоречивые указания, и модель выбрала одно из них произвольно; правило сформулировано слишком расплывчато, чтобы проверить по нему действие; или окружающий код демонстрирует поведение, противоположное тому, что указано в правиле.
Изменяет ли что-то редактирование файла инструкций в середине сессии?
Нет, для копии, которая уже находится в диалоге. Файлы, расположенные выше вашей рабочей директории, загружаются целиком при запуске, поэтому модель оперирует текстом, который был актуален на момент старта. Чтобы применить изменения, начните новую сессию или попросите агента прочитать файл с помощью стандартных инструментов работы с файлами — это добавит текущую версию в диалог как новое сообщение. После выполнения команды compaction файл из корня проекта считывается с диска заново, поэтому новая версия попадет в контекст в этот момент.
Какой файл имеет приоритет, если корневой CLAUDE.md и вложенный файл противоречат друг другу?
Никакой, надежного механизма нет. Обнаруженные файлы конкатенируются в контекст, а не переопределяют друг друга. Они добавляются в порядке от корня файловой системы до вашей рабочей директории, поэтому файл, расположенный ближе всего, просто считывается последним. Механизма приоритетов для разрешения противоречий не существует, и документация Claude Code указывает, что противоречивые правила могут применяться произвольно. Пишите вложенные файлы как дополнения, указывая путь, к которому они относятся, и удаляйте противоречия, вместо того чтобы пытаться перекрыть их приоритетом.
Сохраняются ли мои инструкции после /compact?
Это зависит от способа их загрузки. Файлы из корня проекта CLAUDE.md, правила без области действия и данные из автопамяти повторно считываются с диска после compaction. Правила с фронтметром paths: и вложенные файлы CLAUDE.md в поддиректориях теряются до тех пор, пока соответствующий файл не будет прочитан снова. Все, что вы вводили только в чат, сохранится, только если алгоритм суммаризации случайно оставил это в контексте. Если правило должно действовать на протяжении всей сессии, поместите его в файл в корне проекта без фронтметра paths:.
Когда правило стоит оформить как хук, а не как текстовое описание?
Когда проверка является детерминированной, а цена ошибки выше, чем затраты на написание небольшого скрипта. К таким случаям относятся ограничения на пути к файлам, обязательные команды перед коммитом и запрещенные вызовы инструментов. Хук PreToolUse, который завершается с кодом 2, полностью блокирует вызов инструмента и возвращает ваш текст из stderr модели в качестве причины отказа, поэтому правило будет работать независимо от того, находится ли оно в контексте. Все, что может проверить форматер или линтер, должно быть передано этим инструментам и полностью удалено из файла инструкций.