— Егор, а можешь показать свой AGENTS.md?

от автора

Да не вопрос! На самом деле буквально три месяца назад у меня вообще не было никакого AGENTS.md. Он появился автоматом, когда я устанавливал code-review-graph.

История такая: я каждый день провожу стримы на Ютубе, где показываю процесс разработки своего проекта. И однажды в чатике мне посоветовали воспользоваться code-review-graph, чтобы сэкономить токенов в Codex. Я воспользовался советом, запустил установку через терминал — и в проекте автоматом появилась куча инструкций для разных агентов. Среди этих инструкций оказался и AGENTS.md.

Если вы, как и я поначалу, мало что понимаете в этих терминах и для чего они нужны, — сейчас объясню.

Для начала немного контекста. Меня зовут Егор Камелев, я проектировщик интерфейсов (UX-дизайнер). В апреле 2025 года решил попробовать себя в роли fullstack-разработчика с помощью LLM (Large Language Model, большая языковая модель; то, что нынче обычно называют ИИ).

В качестве пет-проекта выбрал CRM-систему для собственных нужд. А так как я всю дорогу фрилансер — получилась CRM для фрилансеров. И вот я уже больше года её разрабатываю.

Я не совсем простой проектировщик, немного умею работать с кодом и в целом разбираюсь в полном цикле проектирования, разработки, деплоя, тестирования и продвижения проектов. Но это мой первый проект, который я делаю своими руками от и до. А теперь к делу.

AGENTS.md — это документ. Текстовый файл, созданный с использованием языка разметки Markdown (отсюда и md в расширении файла). Он лежит в корневой директории проекта — и по умолчанию любой LLM-агент знакомится с ним перед началом каждого подхода к работе.

Code-review-graph — это инструмент, который строит структурную карту проекта. Он нужен, чтобы агент каждый раз не перечитывал весь проект (а в моём случае это уже больше 150к+ строк кода), а быстро находил нужные места и зависимости. Он индексирует код, строит граф связей — и отдаёт агенту только самое важное.

В чатике стрима мне сказали, что токены будут тратиться раз в 10 меньше, если я им воспользуюсь. Честно скажу — я такой разницы не заметил.

В общем, появился у меня AGENTS.md, наполненный исключительно текстом инструкции, как пользоваться этим самым code-review-graph.

Code-review-graph зависел от внешнего MCP-сервера (MCP — Model Context Protocol, протокол, через который агент подключается к внешним инструментам и источникам данных), который периодически не отвечал. Каждый второй раз, а иногда и чаще, запрос отваливался по 120-секундному тайм-ауту, и агент продолжал работать, не опираясь на граф. А две минуты ожидания — это многовато в современном мире.

Поэтому первая строка, которую я добавил в AGENTS.md самостоятельно, была такой: «Если code-review-graph не отвечает в течение 10 секунд — дальше двигайся без него».

И это сработало! Теперь агент, если не получал быстрого ответа от чужого сервера, шёл разбираться с проектом локально.

И вот именно с того момента AGENTS.md стал для меня инструментом, с помощью которого я исправлял затыки и косяки агента после каждого инцидента.

Забегу немного вперёд и скажу, что пару недель назад я попросил Codex написать мне локальный инструмент, который мог бы заменить code-review-graph. Агент справился с задачей минут за 30 (разумеется, он не сделал полноценный продуктовый инструмент, а сгенерировал локальный под мою задачу) — и теперь это часть проекта. Более того, я в любой момент могу оптимизировать решение исходя из собственных потребностей. Так что теперь в начале инструкции у меня уже стоит просьба работать с «Norm Codex Memory». О 120-секундных таймаутах я забыл.

Всё, вводная часть закончилась, теперь пойду по строчкам инструкции, ведь каждая из них — со своей историей.

В локальной среде сервер запускается на порту 8080.

Я заметил, что Codex несколько раз пытался поднимать сервер на других портах, у него не получалось, он упрямо пытался снова. Эта строка решила проблему.

Перед началом работы изучай содержимое папки doc, следуй правилам проекта. Если увидишь несоответствия — сообщай об этом и предлагай исправления и доработки. Если всё очевидно и понятно — в конце каждого подхода к работе дополняй документацию в папке doc (актуализируй существующую, создавай новую)

Пожалуй, это самая важная строка. Благодаря ей агент легко ориентируется в проекте, видит все решения и правила в документации и действительно прилежно актуализирует их после каждого подхода к работе.

Я периодически, раз в несколько дней, открываю случайные документы, чтобы проверить, насколько подробно и понятно там всё описано — и не разочаровываюсь.

Локальный сервер всегда считается уже поднятым на http://127.0.0.1:8080

Эту строку я написал после того, как понял, что Codex иногда пытается запустить уже запущенный сервер. После этой инструкции проблема исчезла.

Codex не должен запускать, перезапускать или останавливать dev-сервер без прямого запроса пользователя. Для проверки фронтенда использовать существующий сервер на 8080. Если он не отвечает в течение 5 секунд — сообщить об этом и продолжить без попытки запуска. Не запускать долгоживущие команды вроде manage.py runserver в foreground.

Это в ту же копилку. Агент своевольничал и иногда умудрялся запускать несколько долгоживущих команд, а останавливать их забывал. Обнаружил я это случайно. Пытался исправить какой-то неприятный баг на фронте, а у меня не получалось, с какой стороны ни подходил. Выяснилось, что причиной оказался работающий на заднем фоне процесс, который «сражался» с рендерингом актуальной версии кода и подсовывал закешированный вариант. После того, как я справился с этой проблемой — тут же добавил инструкцию в AGENTS.md, чтобы больше такого не повторялось.

Browser-use / Playwright / in-app browser использовать только по прямой просьбе пользователя: «открой в браузере», «проверь визуально», «сделай скриншот», «протестируй фронт». Для обычных мелких HTML/CSS/JS-правок не запускать browser-use/Playwright автоматически; ограничиваться кодовой проверкой и сообщать, что визуальная проверка не выполнялась.

Эта инструкция появилась, когда я понял две вещи. Первая: агент при каждом подходе к работе стремится протестировать результат в том числе на уровне фронта (того, как это выглядит в браузере) и на это уходит уйма времени (и, возможно, дополнительных токенов). Вторая: я в любом случае делаю подробное тестирование фронта вручную после каждого подхода к работе.

И я всегда нахожу не только те косяки, которые нашёл бы Codex, но и ещё в два раза больше косяков, которые Codex бы не нашёл. Поэтому получалась двойная работа за счёт времени и токенов, а результат получался тот же.

В какой-то момент мне так надоело ждать, пока Codex делает бесполезное тестирование, которое я всё равно должен буду повторить сам — что я написал эту строку в инструкции. С тех пор полёт нормальный: агент выполняет работу на треть быстрее, а качество всё то же, благодаря моему ручному тестированию.

Не используй термин MVP при работе над новыми частями и функциями проекта. У нас нет задачи проверять гипотезы и делать минимальные жизнеспособные версии — мы сразу работаем в парадигме «делаем правильно, надолго и архитектурно устойчиво». Наши компоненты готовы к масштабированию, учитывают вопросы безопасности, переиспользования в других участках системы. Во время проектирования мы стараемся не обрезать функционал, а, наоборот, думать на несколько шагов вперёд. В случае чего, я самостоятельно обозначу границы ближайшей реализуемой версии.

Эта инструкция говорит сама за себя. Меня в какой-то момент реально начало раздражать то, что Codex называл те или иные участки проекта MVP (Minimum Viable Product, минимально жизнеспособный продукт). Я всю дорогу старался делать основательные и продуманные решения, а агент — слепить что-то на коленке для проверки гипотезы. После появления этого текста в инструкции у нас возникло взаимопонимание и гармония.

Я не против MVP как подхода. Я против того, чтобы агент под видом MVP делал случайные временные решения, которые потом мешают развивать проект.

При чтении файлов с русским текстом в PowerShell всегда использовать Get-Content -Encoding UTF8; если видны Ð…/кракозябры, сначала перепроверить через -Encoding UTF8 или rg, не считать файл повреждённым по выводу Get-Content без явной кодировки.

Эта инструкция появилась потому что я работаю в Windows и периодически видел в размышлениях агента «Прочитал документ, но вместо нормального текста вижу кракозябры. Сейчас попробую по-другому…». Сформулировать инструкцию мне помог сам Codex — и теперь эта проблема тоже исчезла.

Добавляй в код комментарии, которые помогут разработчикам-людям быстрее сориентироваться в кодовй базе.

А вот тут интересно. Я ожидал, что после этой инструкции новый код будет прям переполнен комментариями. Но нет. Они появляются лишь изредка и в совсем специфичных местах, действительно требующих дополнительного описания. В остальных случаях, судя по всему, код написан так, что говорит сам за себя.

При принятии продуктовых решений по коду, архитектуре и прочему — ориентируйся на то, что мы стремимся к 30 000 платных пользователей на проде. Одномоментно сервером будут пользоваться 300 человек. Сейчас у нас два ядра и 3 гига оперативки — сигнализируй, когда увидишь, что этих мощностей недостаточно для нашего очередного нововведения.

Это, считайте, инструкция вдогонку про MVP. Я в какой-то момент понял, что у меня есть внутреннее представление эндгейма, к которому я стремлюсь в обозримом будущем, а у агента его нет. Это не прогноз и не обещание, а рабочий ориентир, чтобы агент не проектировал решения, которые развалятся при первом росте нагрузки. После этой инструкции Codex в каждой итерации стал объяснять, до каких нагрузок мы доживём на том, что есть, и к чему готовиться, когда они будут превышены.

При разработке используй DRY-подход. Прежде чем разрабатывать новую функцию или придумывать новый стиль — обязательно убедись в том, что чего-то похожего уже нет в проекте. Do your very best to make code DRY.

Если что, DRY — Don’t Repeat Yourself, принцип «не повторяйся». Эта строка появилась после того, как я пару раз ловил агент на том, что он, несмотря на всю документацию и правила ведения проекта, всё-таки умудряется иногда изобрести заново то, что уже есть и работает в коде. Стало гораздо лучше. Но не идеально. Я всё равно перепроверяю код — и иногда ловлю Codex на очередном изобретении велосипеда.

Любой пользовательский загрузчик файлов должен использовать общий дизайн и механику загрузки файлов: templates/core/parts/file_upload_dropzone.html с поведением static/js/user_files.js или модальное окно templates/core/parts/file_upload_modal.html, как на странице импорта контактов и в модалке загрузки нового файла. Не добавляй локальные голые input type=»file» с текстовым полем/обычной кнопкой выбора файла. Технический file input может существовать только внутри общего dropzone/upload-компонента.

Вот как раз хороший пример. У меня в проекте есть много разрозненных мест, где нужно загружать файлы. Но вот хоть ты тресни — агент не собирался использовать единый загрузчик и его оформление и каждый раз делал его по-новому. Пришлось писать эту строку — и теперь проблема решена.

В интерфейсных счётчиках избегай склоняемых форм, если можно написать стабильную подпись. Предпочитай формат вроде «Услуг подключено: 4», «Устаревших услуг: 2», «Файлов выбрано: 1», чтобы не плодить сложную и легко ломающуюся логику склонений.

Это мелочь, но она меня раздражала. Когда я не делал подробного проектирования перед постановкой задачи и доверял это агенту — он периодически забывал о том, что в русском языке есть склонения, и предлагал корявые решения. Теперь не предлагает. Вообще я считаю, что такие инструкции должны жить в рамках документации по проекту, но если что-то прям действительно часто повторяется и раздражает — можно перенести и на уровень повыше.

При проектировании новых моделей максимально их нормализуй. Не допускай того, чтобы в одном классе хранились параметры для десятков разных сущностей. Делай классы максимально специфичными. Нам это нужно для того, чтобы классы не разрастались по параметрам с ростом проекта и для того, чтобы равномерно распределять нагрузку на базу данных при большом количестве активных пользователей

Разумеется, эта строка появилась после того, как я несколько раз поймал агента на стремлении запихать всё в один класс. После этого проблема исчезла.

Кстати, как это произошло? После каждого подхода агента к работе, первое, что я проверяю вручную и очень внимательно — это файлы models.py. Потому что для меня ошибка или недоработка в модели данных приведёт к максимальным проблемам в дальнейшем. Codex делает так, что всё замечательно работает, но работоспособное решение может оказаться не готово к дальнейшему развитию проекта.

Перед тем, как делать что-либо на любом из прод-серверов — запрашивай у меня подтверждение.

Без комментариев. Как вы догадались — был инцидент. К счастью, агент не сделал ничего плохого. Ничего не удалил, не сломал. Но я офигел, когда он воспользовался моей локальной сессией по ssh — и пошёл выполнять работу на сервере за меня вместо того, чтобы, как обычно, просто дать мне инструкции.

Вот и всё! Документ живой, я периодически что-то добавляю, что-то удаляю. Каждая новая строка — это результат инцидента, а не мои фантазии. Как только я вижу, что где-то замедляюсь или что-то меня раздражает — избавляюсь от этой преграды.

Напоследок вот вам скриншот содержимого папки с документацией по проекту. У меня есть подозрение, что именно эта часть работы позволяет агенту не упираться в контекст и выполнять с первого подхода большинство поставленных задач.

Ведь каждый подход к работе для агента — это работа с чистого листа. Он как человек, страдающий потерей памяти: не помнит, что было в наших соседних диалогах. Поэтому я сделал всё возможное, чтобы он легко въезжал в курс дела и ничего не упускал:

  • Видел базовые правила в AGENTS.md;

  • Сразу после этого запускал инструмент с графом проекта, и быстро вникал в структуру связей;

  • Разобравшись с тем, в каких участках проекта предстоит работа, шёл в документацию и максимально погружался в контекст;

  • И только после этого лез в код.

Мои инструкции в AGENTS.md — это не «пиши хороший код», а журнал уже случившихся ошибок, превращённых в правила. Чем конкретнее правило связано с реальным инцидентом, тем оно полезнее.

Пока полёт нормальный. И если вы искали пример объёмного проекта, который человек без классического программистского бэкграунда делает с помощью LLM, и который не разваливается уже больше года — то вот он.

Полезные ссылки:

ссылка на оригинал статьи https://habr.com/ru/articles/1054504/