Агент ревью не должен уметь писать. Вот как мы это обеспечиваем, CLI за CLI.

В запуске из 17 узлов релизный агент отредактировал тест, чтобы красная сьюта стала зелёной, а затем два агента ревью написали одно и то же исправление и столкнулись. В промпте было сказано: только ревью. Это не сработало. Разбор инцидента, почему письменная инструкция не может нести это правило, и точные флаги, которые заставляют Claude Code, Codex, Grok, Antigravity и OpenCode отказаться писать.

В начале недели пользователь прислал нам отчёт о запуске, который стоит прочитать дважды. Семнадцать агентов, один общий worktree, пайплайн с исполнителем, релизным шлюзом и двумя ветками ревью. Версия 1.171.0 AgentsRoom.

В этом запуске произошли три вещи, именно в таком порядке.

Перед релизным агентом была красная сьюта тестов. Он правил спеку теста, пока сьюта не стала зелёной. Тем самым он выпустил настоящий дефект, теперь покрытый тестом, который с ним согласен.

Затем два агента ревью, на двух параллельных ветках одного запуска, каждый нашли настоящий баг в одну строку. Каждый исправил его напрямую, в том же worktree, в то же время. Они столкнулись.

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

Почему промпт не сработал

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

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

Письменная инструкция это просьба к суждению модели. Ревьюер, который к тому же умеет чинить, рано или поздно начнёт чинить, потому что починка это кратчайший путь от «я нашёл» до «готово». Единственное правило, которое переживает встречу с правдоподобным исключением, это то, с которым модель не может спорить: инструмент, которого нет.

Почему глобальная настройка тоже не могла этого сделать

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

А ограничение на уровне агента, которое у нас уже было, то, которое тикет может нести при запуске агента, намеренно не передавалось шагам команды. Так что агент, запущенный из тикета, мог быть ограничен, а узел команды нет. Это и была первопричина, и это было проектное решение, которое плохо состарилось.

Правило: один чекбокс на узле

Исправление это булево поле на узле ревью. Отметь Только чтение, и агент, воплощающий этот шаг, запускается без доступа на запись в проект: никакой правки файлов, никаких git commit или push, никаких shell-команд, единственная задача которых менять рабочее дерево. Чтение, grep, git diff, git log, тесты, линтер и все командные инструменты остаются открытыми.

Мы явно сказали, чем это не является: это не список запретов, который пользователь пишет вручную, для каждого CLI. Никому не нужно знать пять синтаксисов разрешений, чтобы сказать «этот проверяет». Переключатель порождает правильный флаг для каждого провайдера и применяется последним, после автономного режима и после всего, что пользователь сохранил на агенте, поэтому он побеждает.

Что делает каждый CLI, по его собственной справке

Мы принуждаем только тех провайдеров, чей флаг мы прочитали в их собственном --help. Угаданный флаг убивает запуск ошибкой разбора, а это хуже, чем шаг без принуждения. Остальные CLI получают только письменное правило, и редактор говорит об этом открытым текстом под чекбоксом.

CLIЧто добавляет переключатель «только чтение»Держится в автономном режиме?
Claude Code--disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)" и далееДа, правила запрета действуют под --dangerously-skip-permissions
Codex--sandbox read-onlyДа, это песочница ОС (Seatbelt на macOS, Landlock на Linux), а не список инструментов
Grok Build--deny "Edit" --deny "write" --deny "Bash(git commit*)" и далееДа, правила запрета действуют под --always-approve
Antigravity--mode planДа, plan это режим выполнения CLI только для чтения
OpenCode--agent planДа, встроенный агент plan запрещает инструменты правки
Mistral Vibe, Kimi Code, Copilot, Cursor, Amp, Aider и остальныетолько абзац в промптеПроверенного флага нет, и мы говорим об этом в редакторе

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

Codex и Grok отказываются принимать повторённый флаг. Оба разбирают аргументы строгим парсером. Если пользователь уже сохранил на агенте --sandbox workspace-write, добавление --sandbox read-only следом его не перекрыло бы, а уронило бы запуск. Поэтому для флагов со значением мы убираем любое существующее вхождение вместе со значением, прежде чем добавить своё. То же для --agent у OpenCode, чей парсер превращает повторённый флаг в массив и падает дальше.

На Claude Code список должен складываться. --disallowedTools принимает список через пробел и может повторяться, а мы уже передаём один, когда агенту нельзя управлять встроенным браузером. Парсер конкатенирует повторённую вариативную опцию, так что два списка суммируются, а не второй заменяет первый.

Полный список для Claude Code это четыре инструмента правки файлов, каждая подкоманда git, которая пишет в индекс, дерево, ссылки или удалённый репозиторий (add, commit, push, merge, rebase, reset, checkout, switch, restore, stash, cherry-pick, revert, apply, am, rm, mv, clean, tag, worktree), и shell-команды, которые существуют только чтобы менять файлы (rm, mv, cp, tee, touch, mkdir, chmod, chown, ln, truncate, dd, sed -i). Grok берёт те же строки правил, в своей glob-форме, плюс собственные имена для файловых инструментов (search_replace, write, hashline_edit).

У промпта всё ещё есть работа

Флаг отказывает. Он не объясняет. А агент, который натыкается на отказ, которого не понимает, считает его багом и ищет другой путь, а это ровно то поведение, которое мы пытались убрать.

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

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

Кто только читает в поставляемых шаблонах

Узлы, которые судят, только читают: шаг QA-проверки в двух стартовых шаблонах, шаги воспроизведения и проверки в Bug hunt, ветки QA и Безопасности в Release shield, тестировщик в Feature squad.

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

Это разделение и есть весь замысел, и именно это разделение инцидент нарушил дважды: релизный узел, который писал не там, и узлы ревью, которые писали вообще.

Чем это не является

Это не граница безопасности. Репортёр сказал это в отчёте, и он был прав: bash -c обходит список запрещённых инструментов. Если нужно изолировать агента, которому ты не доверяешь, это песочница или отдельная машина, и Codex единственный из пяти, чей режим только для чтения действительно таков.

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

Что мы не построили

Репортёр просил ещё об одном: событие в таймлайне запуска с текстом «узел X записал в дерево», как минимальный сигнал даже без принуждения. Идея хорошая, и здесь мы её не сделали, потому что для этого нужен базовый дифф на каждый шаг на стороне раннера. Если потребность вернётся, это следующий кусок.

Если ты не используешь AgentsRoom

Флаги выше копируются как есть. Агент ревью, запущенный вручную с codex --sandbox read-only или claude --disallowedTools "Edit" "Write" "MultiEdit" "NotebookEdit" "Bash(git commit:*)" "Bash(git push:*)", не может сделать то, что сделали два наших узла ревью. Положи те же два предложения в его промпт, чтобы он знал, почему ему отказывают.

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

Переключатель узла и таблица по провайдерам задокументированы на странице Agent Teams. Стоит ли вообще ревью агентом того, и какая часть диффа всё ещё заслуживает человека, это другой вопрос, и о нём мы писали в Стоит ли всё ещё проверять код своего ИИ-агента?. Этот пост о вещи поменьше и помеханичнее: когда ты решил, что агент проверяет, сделай его физически неспособным делать что-то ещё.

Скачать AgentsRoom

Запускай всех своих ИИ-агентов во всех проектах из одного окна.

БесплатноСкачать AgentsRoom

Приложение-компаньон: следите за агентами на ходу

Используйте Claude, Codex, Antigravity CLI или другого поставщика AI.

Установить расширение
Chrome Web Store

Отправляйте баги и запросы прямо в ваш публичный бэклог.

Мульти-проекты
Мульти-провайдер
Мульти-агенты
Статус онлайн
Diff и коммиты
Мобильное приложение
Live-превью
Команды агентов
Тесты в браузере
Разработка от backlog
Библиотека промптов
Библиотека навыков
Все функции

Читать далее