Вложенные файлы AGENTS.md в монорепозитории
Использование одного файла AGENTS.md в корне монорепозитория приводит к потере контекста. Узнайте, как настроить вложенную структуру для оптимизации работы AI-агентов в проекте.
Что означают вложенные AGENTS.md в монорепозитории
Вложенные файлы AGENTS.md в монорепозитории означают наличие одного небольшого файла в корне репозитория и по одному дополнительному файлу внутри каждой директории сервиса. Корневой файл содержит несколько правил, актуальных для всего проекта, а также карту расположения остальных файлов. Каждый сервисный файл содержит команды и соглашения, относящиеся только к этой директории. Агент, редактирующий services/worker/queue.py, считывает корневой файл и файл конкретного рабочего модуля, не тратя контекст на фронтенд, с которым он не будет работать.
Ничего устанавливать не нужно. AGENTS.md — это соглашение, и в исходном проекте об этом сказано прямо:
AGENTS.md — это обычный Markdown. Используйте любые заголовки; агент просто парсит предоставленный вами текст.
Именно поэтому стоит правильно освоить этот метод. Формат не изменится в процессе работы. Проблемы могут возникнуть только с размещением и поддержкой, и то и другое — ваша зона ответственности.
Почему один большой файл AGENTS.md в корне перестает работать?
Один файл AGENTS.md объемом 600 строк в корне репозитория, содержащего веб-приложение, фоновый обработчик и директорию Terraform, дает сбои по четырем причинам.
Он устаревает, так как у него нет владельца. Инженер, переименовывающий тестовый скрипт в apps/web, редактирует файлы в apps/web. Корневой файл AGENTS.md не попадает в этот diff, поэтому никто из проверяющих не видит несоответствия. Через шесть недель файл описывает этап сборки, которого больше не существует, а человек, который внес изменения, уже забыл о них.
Он расходует контекст при каждой задаче. Эти файлы загружаются в начале сессии, еще до того, как агент узнает, о чем вы собираетесь спросить. В документации Claude Code указано ограничение: «старайтесь не превышать 200 строк на файл CLAUDE.md. Более длинные файлы потребляют больше контекста и снижают точность выполнения инструкций». Codex перестает объединять файлы инструкций, как только их суммарный размер достигает 32 KiB — это значение по умолчанию для project_doc_max_bytes. Корневой файл, описывающий четыре сервиса, тратит этот лимит на три из них при выполнении каждой задачи.
Инструкции начинают противоречить друг другу. Веб-директория требует pnpm test. Обработчик требует pytest -q. Если записать это в один файл, каждое правило будет верным лишь частично, поэтому агенту приходится угадывать, какое из них применимо. В документации Claude Code результат описывается так: «если два правила противоречат друг другу, Claude может выбрать одно из них произвольно». Файл в каждой директории исключает необходимость догадок, так как в контексте всегда находится только одно из двух правил.
Он заполняется фактами, которые агент может прочитать из кода. Дерево директорий, список зависимостей, краткое описание функций каждого пакета. Проверка /doctor в Claude Code существует именно для того, чтобы удалять такие данные. Она «отсекает контент, который Claude может извлечь из кодовой базы, например, структуру директорий, списки зависимостей и обзоры архитектуры», и оставляет «подводные камни, обоснования и соглашения, которые отличаются от стандартных настроек инструментов». Это предложение — лучший известный мне критерий для определения того, стоит ли вообще включать строку в файл.
Читает ли агент корневой файл или только ближайший?
Здесь большинство пользователей ошибаются в понимании модели, поэтому стоит привести официальное соглашение разработчиков, а не пересказывать его:
Размещайте файл AGENTS.md внутри каждого пакета. Агенты автоматически считывают ближайший файл в дереве каталогов, поэтому приоритет имеет самый близкий файл, и каждый подпроект может содержать специализированные инструкции.
О конфликтах:
Файл AGENTS.md, расположенный ближе всего к редактируемому файлу, имеет приоритет; явные запросы пользователя в чате переопределяют всё остальное.
Фраза «имеет приоритет» для многих звучит как «корневой файл игнорируется». Это не так. В инструментах, реализующих данное соглашение, считываются и объединяются все файлы на пути от корня репозитория до рабочей директории. Ближайший файл побеждает только в том случае, если два файла содержат противоречивые указания по одному и тому же вопросу.
Codex прямо описывает этот механизм: «Codex объединяет файлы от корня вниз, соединяя их пустыми строками. Файлы, расположенные ближе к вашей текущей директории, переопределяют предыдущие инструкции». Claude Code использует аналогичный подход для своего файла. Файлы в иерархии каталогов выше рабочей директории «загружаются полностью при запуске», и «все обнаруженные файлы объединяются в контекст, а не переопределяют друг друга». Директории ниже рабочей директории ведут себя иначе: Claude Code загружает эти файлы по требованию, «когда Claude читает файлы в этих директориях».
Из этого следуют два практических вывода. Корневой файл становится префиксом для каждой сессии в репозитории, поэтому каждая строка в нём — это то, за что вы платите сотни раз в неделю. Файл в конкретной директории ничего не стоит, пока агент работает в другом месте, а значит, детализация там обходится дёшево и должна находиться именно там.
Данное поведение было проверено по документации Codex и Claude Code в августе 2026 года. Инструменты реализуют это соглашение с небольшими различиями и могут обновляться, поэтому уточняйте правила загрузки для того агента, который использует ваша команда.
Рабочая структура репозитория для трех сервисов
repo/
AGENTS.md rules true everywhere, plus the map
apps/web/AGENTS.md TypeScript client, Vite, Vitest
services/worker/AGENTS.md Python queue consumer, pytest
infra/AGENTS.md Terraform and the deploy scriptsКорневой файл намеренно сделан коротким. Он указывает, где искать информацию, и содержит только те правила, которые действуют во всех директориях.
# AGENTS.md
This is a monorepo. Each top-level directory ships its own AGENTS.md.
Read this file and the AGENTS.md nearest the code you are editing
before you change anything.
- `apps/web` browser client
- `services/worker` queue consumer
- `infra` Terraform and deploy scripts
## Rules for the whole repository
- The package manager is `pnpm`. `npm install` writes a second lockfile
that CI ignores, so the install you tested is not the install that ships.
- Any `generated/` directory is build output. Edit the schema in
`schemas/` and run `pnpm codegen` instead.
- `.env.local` holds real credentials. Do not read it and do not print it.
- If you change code in a directory, update that directory's AGENTS.md
in the same commit.Файл в каждой директории содержит детали и может быть настолько подробным, насколько это необходимо для конкретной директории.
# apps/web
Browser client. Vite and React, TypeScript with `strict` on.
## Commands
- `pnpm dev` serves on port 5173.
- `pnpm test` runs Vitest once and exits.
- `pnpm typecheck` runs `tsc --noEmit`.
## Conventions
- One component per file under `src/components/`.
- All HTTP goes through `src/api/client.ts`. Do not call `fetch` directly,
because the client attaches the auth header and retries on 429.
## Traps
- `pnpm build` does not type check. Vite strips the types instead of
checking them, so a broken type still produces a green build.
Run `pnpm typecheck` as a separate step.Файл рабочего процесса имеет ту же структуру, но другое содержание: команду установки, pytest -q, причину, по которой потребитель должен сохранять идемпотентность, и миграцию, которая должна выполниться до прохождения тестов. В файле инфраструктуры вы прописываете правила, которые не позволяют агенту нанести вред. Никогда не запускайте terraform apply. Выполняйте terraform plan и на этом останавливайтесь, а также указывайте бэкенд состояния, который уже настроен, чтобы агент не пытался инициализировать новый.
Обратите внимание, чего нет ни в одном из этих файлов: описания назначения каждого сервиса. Это информация для людей. Upstream проводит ту же границу, утверждая, что «файлы README.md предназначены для людей: быстрый старт, описание проекта и правила внесения правок», в то время как AGENTS.md содержит «дополнительный, иногда детальный контекст, необходимый агентам для написания кода: этапы сборки, тесты и соглашения». В разделении между AGENTS.md и README для людей эта граница разбирается предложение за предложением, а файл DESIGN.md, фиксирующий причины выбора архитектуры кода охватывает третий тип файлов — тот, который объясняет принятые решения, а не команды.
Кто обновляет файл при изменении кода?
Существует одно правило, и оно относится к корневому файлу: любой, кто изменяет код в директории, обязан обновить файл AGENTS.md в этой же директории в рамках того же коммита.
Это работает по техническим причинам, а не из-за корпоративной культуры. Файл в конкретной директории находится в том же diff, что и код, поэтому рецензент pull request видит их одновременно. Корневой файл принадлежит всем, а значит — никому; он никогда не попадает в diff, который кто-либо просматривает в данный момент.
Подкрепите это правило проверкой в pull request. Она находит ближайший файл AGENTS.md для каждого измененного файла и сообщает, если этот файл не был затронут.
#!/usr/bin/env bash
# Warn when code changed but the nearest AGENTS.md above it did not.
changed=$(git diff --name-only origin/main...HEAD)
nearest_doc() {
d=$(dirname "$1")
while [ "$d" != "." ]; do
if [ -f "$d/AGENTS.md" ]; then echo "$d/AGENTS.md"; return; fi
d=$(dirname "$d")
done
echo "AGENTS.md"
}
printf '%s\n' "$changed" | while read -r f; do
[ -n "$f" ] || continue
case "$f" in AGENTS.md|*/AGENTS.md) continue ;; esac
doc=$(nearest_doc "$f")
printf '%s\n' "$changed" | grep -Fqx "$doc" && continue
echo "note: $f changed but $doc was not updated"
doneВ ветке, где был переработан API client, но не была обновлена документация, вывод выглядит так:
note: apps/web/src/api/client.ts changed but apps/web/AGENTS.md was not updatedПусть это будет предупреждение, а не ошибка сборки. Жесткий запрет приучает людей добавлять пустую строку в файл только ради того, чтобы CI стал зеленым. Файл, отредактированный для удовлетворения робота, стоит меньше, чем полное отсутствие файла. Предупреждение дает рецензенту повод задать вопрос, и именно это работает на практике.
Как определить, что файл AGENTS.md устарел?
Существует две проверки, которые можно выполнить сегодня, и один симптом, который вы заметите во время сессии.
Сравните дату изменения каждого файла с датой кода, который он описывает. %cs выводит дату коммита в формате YYYY-MM-DD.
for f in $(git ls-files '*AGENTS.md'); do
d=$(dirname "$f")
printf '%s doc:%s code:%s\n' "$f" \
"$(git log -1 --format=%cs -- "$f")" \
"$(git log -1 --format=%cs -- "$d")"
doneapps/web/AGENTS.md doc:2026-02-11 code:2026-08-07
services/worker/AGENTS.md doc:2026-07-29 code:2026-08-09
infra/AGENTS.md doc:2026-08-01 code:2026-08-01Если дата документации отстает от даты кода на шесть месяцев, это не доказывает, что файл неверен. Это лишь указывает, какой файл следует прочитать в первую очередь, и это всё, что нужно от проверки, занимающей одну секунду.
Ищите пути, которые больше не существуют. Документация устаревает вполне конкретным образом: она продолжает описывать код, который был удален. Каждый путь в этих файлах оформлен в обратных кавычках, поэтому их легко извлечь и проверить.
grep -o '`[^`]*`' apps/web/AGENTS.md | tr -d '`' | grep '/' | while read -r p; do
[ -e "$p" ] || [ -e "apps/web/$p" ] || echo "missing: $p"
doneПросматривайте вывод вручную, а не встраивайте эту проверку в CI. Она также помечает шаблоны (globs), такие как src/**/*.ts, и любые процитированные URL, поскольку оба содержат косую черту и не являются файлами на диске.
Симптом во время сессии. Агент читает файл, пытается открыть src/api/client.ts, потому что файл дал ему такую инструкцию, и инструмент возвращает:
No such file or directoryВ результате агент поступает логично и пишет собственную обертку fetch. В этом и заключается реальная цена устаревшего файла. Агент не игнорирует вашу документацию. Он следует ей, переходит по пути, который был удален три месяца назад, и пересобирает код, который у вас уже есть. Такой навык, как Ponytail, который ограничивает агента минимально необходимыми изменениями, делает этот инстинкт пересборки более редким, но он не поможет найти вспомогательный инструмент, на который ваш файл указывает неверно.
Читает ли Claude Code файлы AGENTS.md?
Нет, и об этом стоит сказать прямо, так как вложенная структура зависит именно от этого. По состоянию на август 2026 года в документации указано: «Claude Code читает CLAUDE.md, а не AGENTS.md». Этот шаблон по-прежнему работает, вам просто нужно разместить CLAUDE.md рядом с каждым AGENTS.md.
Форма импорта подходит, когда вы хотите добавить специфичные для инструмента строки поверх общих. Добавьте это в services/worker/CLAUDE.md:
@AGENTS.md
## Claude Code
Use plan mode for changes under `services/worker/migrations/`.Форма символической ссылки подходит, когда нет необходимости добавлять что-либо специфичное для инструмента.
git ls-files '*AGENTS.md' | while read -r f; do
ln -s AGENTS.md "$(dirname "$f")/CLAUDE.md"
done
ls -l apps/web/CLAUDE.mdln не выводит ничего при успешном выполнении, поэтому проверьте список: apps/web/CLAUDE.md -> AGENTS.md. Затем запустите сессию и выполните /context, где загруженные файлы появятся в разделе Memory files. В Windows для создания символической ссылки требуются права администратора или включенный режим разработчика (Developer Mode), поэтому используйте там импорт @AGENTS.md.
С этим связана одна ловушка. После /compact корневой файл считывается с диска заново, но вложенные файлы в поддиректориях не перечитываются. Они загружаются в следующий раз, когда агент обращается к файлу в этой директории. Если кажется, что правило для конкретной директории перестало действовать в середине долгой сессии, обычно причина именно в этом; обращение к любому файлу в этой директории восстановит его действие.
Настройки, указывающие другим агентам на AGENTS.md
Codex читает AGENTS.md нативно. На каждом уровне он сначала проверяет AGENTS.override.md, что позволяет задать локальное переопределение для одной директории без редактирования общего файла. Объединение прекращается, как только суммарный размер достигает 32 KiB — это значение по умолчанию для project_doc_max_bytes, что является еще одной причиной держать корневой файл небольшим.
Aider использует его через .aider.conf.yml со строкой read: AGENTS.md.
Gemini CLI использует его через .gemini/settings.json с помощью { "context": { "fileName": "AGENTS.md" } }.
В основной документации описано переименование с обратной совместимостью для репозиториев, которые все еще используют старое единственное число: mv AGENT.md AGENTS.md && ln -s AGENTS.md AGENT.md.
В очень больших монорепозиториях настройка claudeMdExcludes в Claude Code позволяет пропускать родительские файлы по пути или шаблону (glob), что полезно, если директория другой команды находится выше вашей.
В чем отличие от памяти агента или навыка?
Эти механизмы выглядят похоже, но работают по-разному в случае сбоев, поэтому важно точно понимать, какой из них вам нужен.
Файл AGENTS.md создается вами, фиксируется в git, проходит проверку в pull request и является идентичным для всех, кто клонирует репозиторий. Память агента создается самим агентом, хранится вне репозитория и привязана к конкретной машине. Документация Claude Code проводит ту же границу: CLAUDE.md содержит «Инструкции и правила», которые пишете вы, автоматическая память содержит «Обучающие данные и паттерны», которые пишет Claude, а директория с памятью не синхронизируется между машинами. Проверка проста. Если факт должен быть верным для коллеги, работающего с чистой копией репозитория, он не может храниться в памяти. Как память агента сохраняется между сессиями описывает эту часть системы.
Навык — это третий элемент. AGENTS.md — это контекст, который загружается в каждой сессии; навык — это процедура, которая загружается по мере необходимости. Документация Claude Code предлагает полезное правило: «Если запись представляет собой многошаговую процедуру или важна только для одной части кодовой базы, перенесите её в навык или правило, ограниченное путем». Вторая часть этого предложения — именно то, что решают вложенные файлы AGENTS.md. Первая часть — это то, для чего предназначены навыки агента, а если одна и та же процедура требуется более чем в одном репозитории, используйте общий навык для нескольких репозиториев вместо того, чтобы копировать одни и те же абзацы в десять разных файлов AGENTS.md.
Разработчики upstream отмечают, что «на момент написания основной репозиторий OpenAI содержит 88 файлов AGENTS.md». Это число — главный аргумент. Большому репозиторию не нужен файл большего размера. Ему нужно больше маленьких файлов, каждый из которых находится рядом с описываемым кодом и за который отвечает тот, кто последним вносил изменения в этот код.
FAQ
Вложенный файл AGENTS.md заменяет корневой или дополняет его?
Он его дополняет. Разработчики upstream утверждают, что «приоритет имеет ближайший файл», что описывает поведение при конфликтах, а не процесс загрузки. Codex «конкатенирует файлы от корня вниз, разделяя их пустыми строками», а Claude Code объединяет все найденные файлы при обходе дерева от рабочей директории вверх, вместо того чтобы перезаписывать их. Ближайший файл побеждает только в том случае, если два файла содержат противоречивые инструкции по одному и тому же вопросу. Пишите общие правила в корне один раз и не дублируйте их в каждой директории.
Какого размера должен быть корневой AGENTS.md?
Достаточно малого, чтобы вы не возражали против его добавления к каждому вашему запросу в этом репозитории, так как именно это и происходит. Документация Claude Code рекомендует ограничиваться 200 строками на файл и предупреждает, что более длинные файлы «снижают точность следования инструкциям». Codex по умолчанию прекращает объединение файлов инструкций при достижении 32 KiB суммарного объема. Если ваш корневой файл описывает четыре сервиса, большая его часть будет бесполезным грузом для любой конкретной задачи. Перенесите детали в файлы по директориям, оставив в корне лишь карту.
Как предотвратить устаревание этих файлов?
Добавьте в корневой файл одно правило: тот, кто изменяет код в директории, обновляет AGENTS.md в этой же директории в рамках того же коммита. Размещение файла рядом с кодом помогает соблюдать правило, так как изменение попадает в тот же diff pull request, который уже изучает человек. Добавьте предупреждение в CI, которое сопоставляет каждый измененный путь с ближайшим файлом AGENTS.md выше по дереву, и периодически сравнивайте результат git log -1 --format=%cs для каждого файла с результатом выполнения той же команды для директории, которую он описывает.
Читает ли Claude Code файлы AGENTS.md?
Нет. По состоянию на август 2026 года в документации указано: «Claude Code читает CLAUDE.md, а не AGENTS.md». Создайте CLAUDE.md в той же директории, указав @AGENTS.md в первой строке; это загрузит общий файл и позволит добавить инструкции, специфичные для Claude, ниже. Символическая ссылка, созданная с помощью ln -s AGENTS.md CLAUDE.md, работает, если не нужно добавлять ничего дополнительного, хотя в Windows для этого требуются права администратора или включенный режим разработчика. Выполните /context в сессии и убедитесь, что файл появился в разделе Memory files.
Куда поместить правило, которое нужно лишь иногда?
Не в AGENTS.md. Этот файл загружается в каждой сессии, поэтому каждая строка в нем конкурирует за внимание с запросом, который вы ввели. Процедура из нескольких шагов, которая требуется время от времени, относится к навыкам (skills), которые загружаются по запросу. Правило, применимое к одной директории, должно находиться в AGENTS.md этой директории. Факт, который агент может прочитать непосредственно из кода, например дерево директорий или список зависимостей, не должен находиться ни там, ни там.