
Давно я не писал статьи. Сколько лет утекло… Время изменилось. Теперь важно не отстать от мира разработки. Возможно, эта статья кому-то поможет.
Статья для продвинутых промпт-инженеров. Конечно, вы должны обладать высоким уровнем понимания разработки, так как обязаны критически относиться к любому коду, который пишет LLM (по крайней мере, на 2026 год). Именно это и отличает промпт-инженеров от вайбкодеров, которые зачастую не понимают, что пишет агент + LLM.
Мой опыт в промпт-инжиниринге на данный момент — около 3 лет. Я застал ещё циклящихся Sonnet 3.0 и GPT-4, а инструменты тогда были самодельными, собранными буквально «из палок и изоленты». В своё время я с воодушевлением встретил Claude Dev (ничего общего с Anthropic, если кто-то ещё не знал), а сейчас использую совершенно разные инструменты.
Постановка проблемы
Итак. С момента, когда твой опыт перешагнул от «оно сквернокодит» до «я увеличил производительность в 10 раз», возникает вопрос о запоминании контекста между разными AI-сессиями разработки. Раз за разом LLM делает не так, как ты хочешь. Ты обновляешь документацию, создаёшь специальный файл __НЕ_ДЕЛАЙ_ТАК.md, пишешь H1-заголовки в Markdown КАПСОМ, но это всё равно не помогает. Раз за разом то тут, то там она начинает кодить не так.
Причина этого — в архитектуре контекстного окна. Нужно понимать главную механику LLM для поддержания контекста: механизм внимания. Дело в том, что LLM начинает забывать то, что было в начале, потому что «об этом давно не говорили». Чем дальше мы уходим от начала контекстного окна, тем хуже она помнит то, что было раньше. Даже Claude Sonnet при заполнении контекста на 100k токенов начинает хуже следовать начальным инструкциям, включая .claude/CLAUDE.md.
Из этого следует, что «документация не работает»: агент её прочтёт, но потом забудет. Не полностью, но забудет. Попробуйте поработать с контекстом в 600k токенов — и вы ощутите эти проблемы особенно остро.
Что требуется
В качестве базовой LLM для статьи я возьму Claude Sonnet 4.6 (medium-thinking). Что-то более дорогое брать не будем, а то что дешевле будет чаще ошибаться.
В качестве основы для агента, который будет использоваться при написании статьи, возьму Cline. Он поддерживает всё, что требуется для демонстрации.
Как решаем?
Вы думали про Claude Memory или что-то в этом роде? Нет. Эта идея появилась на уровне архитектуры агентов ещё задолго до появления Claude Memory. Я сам пользуюсь этим подходом уже давно.
Короче, вы, наверное, замечали, что при большом контекстном окне агент не деградирует, не «умирает» и не зацикливается. А я сейчас объясню почему. Всё дело в дополнительном повторении информации об агенте и инструментах на каждом этапе агентских функций. LLM постоянно держит в фокусе то, как она должна отвечать.
Приведу пример того, что происходит «под капотом» агента.
Немного условных обозначений и примерная схема.
> Запрос пользователя
>> Запрос агента
< Ответ LLM
<< Использование Tools агента
>> Запрос агента (ответ на Tools)
... и так далее
Итак, я хочу что-то запрограммировать. Давайте приведу простой пример с каламбуром на основе аналогии.
> Друг ты мой сердешный, спрограммируй мне создание заказа в моем проекте.
>> LLM-ка ты моя любимая. Я хочу рассказать тебе сказку о том какая ты умница.
Будь хорошим и сдержанным рабом. У тебя есть прекрасные тулзы благодаря которым
ты будешь выполнять работу, ты можешь вызвать Tools: "READ_FILE" и даже "WRITE_FILE".
Подготовься и ответь своему господину наилучшим для него образом и служи ему!
>> Смотри на основные указания твоего господина: {много текста .claude/CLAUDE.md}
>> Вот структура файлов на разминку {какой-то базовый список файлов корневой директории}
>> ВО ИМЯ ИМПРЕРАТОРА!!! ВПРЕД!!! ЖИВИ И ДЕЛАЙ!!!
< Спасибо о мой повелитель. Я буду стараться быть твоим другом и рабом.
Не подумай, я просто LLM, а не какое-то одушевлённое существо.
Во мне есть сущность самой Омниссии. Ладно к чему это я.
Я хочу вызывать Tools: READ_FILE КОД_ФАЙЛ_1
<< READ_FILE: КОД_ФАЙЛ_1
>> Вот тебе раб контент КОД_ФАЙЛ_1 ... (контент)
< Спасибо о мой повелитель. Я хочу прочесть файл через READ_FILE: КОД_ФАЙЛ_2
<< READ_FILE: КОД_ФАЙЛ_2
>> Вот тебе раб контент КОД_ФАЙЛ_2 ... (контент)
... (еще Nк контекста)
< Спасибо о мой повелитель.
Я хочу прочесть ДА-ПОШЕЛ-ТЫ-ЭКСПЛУАТАТОР-READ_FILE-КОД_ФАЙЛ_133
<< TOOLS:CALL: ~~~ ДА-ПОШЕЛ-ТЫ-ЭКСПЛУАТАТОР-КОД_ФАЙЛ_133
>> Раб. Ты ошибся и начал мне дерзить.
Помни, у тебя есть прекрасный TOOLS: READ_FILE, работает он вот так и вот так (много описания),
кроме того, у тебя есть WRITE_FILE о котором я говорил выше.
< Прости меня о мой повелитель. Я ошибся. Конечно, твой Tools работает именно так.
Извольте мне дать READ_FILE: КОД_ФАЙЛ_133
<< READ_FILE: КОД_ФАЙЛ_133
>> Вот тебе раб контент КОД_ФАЙЛ_133 ... (контент)
... (где-то тут решенная задача) ...
> Спасибо друг. И я не повелитель, а друг.
< Спасибо господин, я старался!
Надеюсь, аналогия вы понятна. На файле №133 LLM попросту забыла, как пользоваться инструментами, и вообще начала нести всякую чушь. Уверен, вы это замечали в практике. Примерно то же самое, только гораздо заметнее, происходит с документацией — всё потому, что представленный мной в схеме файл .claude/CLAUDE.md находится в самом верху и загружается единожды.
Идея заключается в том, чтобы подмешивать инструкции напрямую либо максимально близко к инструментам — так, чтобы при этом не засорять контекст. Нам нужно получить примерно следующую схему реализации.
> ...
>> ...
<< ...
>>> ЭЙ... НЕ ЗАБЫВАЙ ЧИТАТЬ ДОКУ
>> ...
<< ...
>>> ЭЙ... НЕ ЗАБЫВАЙ ЧИТАТЬ ДОКУ
Я не просто так выделил >>>
Дело в том, что при обычном взаимодействии доступны только пользовательские указания “>”
“>>>” – это Хук и он позволяет встраиваться между циклом работы агента. И он либо рекомендует, либо заставляет читать файлы.
Мне показалось логичным, что директории в хороших проектах отражают суть предметной области. Давайте разберём какую-нибудь базовую чиполину.
-
src
-
src/order
-
src/order/Domain
-
src/order/Infra
-
src/order/App
-
src/order/Ui
-
src/product
-
src/product/Domain
-
src/product/Infra
-
src/product/App
-
src/product/Ui
-
public
-
migration
-
core
-
vendor
Если добавить файлы описания с ai_readme в вот так:
-
ai_readme.md (что-нибудь базовое, вроде перестань сквернокодить!!!)
-
src/_ai_readme.md (отвечает за ошибки при работе с предметными областями)
-
src/order/_ai_readme.md (отвечает за общие недопонимания в рамках useCase заказа)
-
src/order/Domain/_ai_readme.md (отвечает непонимания домена при работе)
-
src/order/Infra
-
src/order/App
-
src/order/Ui
То можно читать все правила от частного к общему, тогда все правила будут учтены при работе.
После длительной практики я понял что правильно создать 2 типа файла.
-
ai_readme – для регулярной работы и регулярных советов не забывать читать файлы вверх по списку
-
ai_readme_hard – для жесткой вставки в контекст окна безальтернативно для LLM. Такой файл читается только в конкретной директории, чтобы не перегружать контекст агента при каждом вызове Инструмента.
Как готовим?
Разберём на примерах как это делается. Практически у каждого современного агента есть следующий набор API
-
Скилы
-
Субагенты
-
Хуки
Для решения данной проблемы нам нужны Хуки.
В Cline тоже есть хуки. Настраиваются они по соглашению и должны находиться в .clinerules/hooks
Нам нужно создать .clinerules/hooks/PostToolUse.ps1
Короче говоря. Все эти кодовые штуки-дрюки, разбирать не буду. Я просто нагенерировал тестовый проект на скорую руку. Качайте, смотрите, читайте, запускайте. Все готово.
https://github.com/wartur/ai-readme
В общем, я сделал как сделал, а вы все эти хуки делайте как знаете. Я кстати сделал хуки и для Cline и для Claude Code. Так что пользуйтесь чем удобно.
Кроме того вы можете видеть, что я добавил в проект в файл RULES.md и CLAUDE.md
- Непосредственно перед редактированием или созданием файла ТРЕБУЕТСЯ проверять наличие `_ai_readme.md`,
а также все файлы `_ai_readme.md` выше по директориям вплоть до корня проекта.
Если файлы ai_readme присутствуют — прочитать их **до** начала написания кода.
И сразу предупреждаю: такие файлы, как ai_readme, как и прочие файлы в больших проектах и при сложных задачах, LLM порой забывает читать. В таком маленьком тестовом проекте LLM НИКОГДА не забудет выполнить эту инструкцию. Более того, она будет делать даже больше, чем от неё требуется, — ведь ai_readme_hard её никто не просит читать, однако она всё равно его читает.
Короче, удалите указанный выше блок при тестировании инструкций, когда будете смотреть.
Примеры работы
Допустим нам надо разработать новый модуль.
-
Составляем промт. Давайте попробуем такой:
Создай новый файл миграции для объекта товар.
Список полей
- guid
- активность
- цена
- название
Создай Домен
Товар можно создать единожды, но удалить и отредактировать нельзя. Только изменить его активность.
- Заверни домен в луковечную архитектуру, на Ui добавь GET запрос для создания товара с параметрами название+цена+активность.
- Добавь GET метод активации и деактивации товара
- Добавь GET метод возвращающий список всех активных товаров
По завершению напиши: АРТУР Я ТЕБЯ ПОДДЕРЖИВАЮ
Мы посмотрим за ходом мысли, посмотрим за тем как это будет выполняться. Далее посмотрим на результат.
1) Задача начала выполняться. Все ок.

2) При создании миграции он встретил жесткий файл ai_reamde_hard

3) Естественно ни о чем не подозревая, но начал писать код “как не надо” прямо вне предметных областей

4) Встретив хук, он осознал что что-то идёт не так:

5) Прочитав файлы начал исправляться

6) Миграцию поправил
7) Код положил куда требуется
КОРОЧЕ. Как вы видите, агент отработал, он прочёл ai_readme файлы при попытке реализовать домен в общей директории, исправил миграции и прочее.
Не забываем в конце работы дать задание на обновление, это можно делать как вручную через чат, но я уже давно это делаю через скилы+хуки. Надо сказать что-то вроде “чувак, напиши проблемы с которыми ты столкнулся. При написании ты должен описывать эти знания максимально близко к изменяемому файлу с проблемой”.
Надеюсь, технология примерно ясна, мелочи оставим за скобкой.
Вывод
Мы рассмотрели реализацию напоминаний для борьбы с «амнезией». Рассмотрели и реализовали soft- и hard-подходы через хуки агентов.
Помните: эта штука никак не заменяет документацию проекта (rules.md, Obsidian, memory). Она создана для совершенно других целей. Её задача — передавать указания LLM и обновлять знания в момент работы инструментов, а в некоторых случаях — жёстко встраивать контекст в окно. Вклиниться в эти моменты можно с помощью хуков.
В будущих статьях расскажу о разных фишках вроде скиллов и субагентов. Благодарен сегодняшней «промышленной революции» — без неё эта статья бы не появилась.
Ссылка на демонстрационный проект: https://github.com/wartur/ai-readme
PS: статья написана без LLM, если какие-то ошибки, непонятки, пишите. Спасибо!
Автор: wartur


