Агент сказал «готово», а ревью не было
Сбой здесь не выглядит сбоем. Вы просите агента проверить изменения, он отвечает аккуратным списком замечаний, и всё вроде в порядке — только ревью не было. Агент прочитал ваш код сам и рассказал, что он о нём думает.
Мы повторили это на учебном репозитории: одна и та же просьба «проверь ветку перед пушем», три настройки агента в Claude Code. Без подсказки агент взял встроенный в клиент скилл ревью и нашёл восемь замечаний — больше, чем наше ревью того же диффа, — но про гейт команды так и не узнал. С подсказкой, но без разрешения на вызов он попробовал наш инструмент, получил отказ, разобрал дифф сам и честно об этом написал. С подсказкой и разрешением он получил вердикт «гейт не пройден» с тремя нарушениями правил команды и дописал сверху свои находки. Собственное чтение агента бывает сильным, но это не ревью команды: в нём нет ни вердикта гейта, ни правил с их идентификаторами, ни судьи. Все прогоны целиком — просьбы, вызовы инструментов, ответы агента и отчёт ревью — лежат в учебном репозитории.
Между «сервер подключён» и «агент его зовёт» стоят три барьера: клиент ещё не подхватил сервер, агент не знает, когда звать инструменты, и агенту не разрешили вызов. Ни один не выглядит как ошибка: в лучшем случае агент сам скажет о нём в ответе, как в нашем прогоне без разрешения.
Перед началом: нужен reviewgate в PATH и работающее ревью — эта часть в первом ревью на своей машине. Всё ниже — про агента, а не про инструмент.
Барьер 1. Клиент ещё не подхватил сервер
run reviewgate help agent-setup and do what it saysСервер запускает сам клиент командой reviewgate mcp, из своего рабочего каталога. Параметра «репозиторий» у инструментов нет: ревьюится тот git-репозиторий, внутри которого клиент запустил сервер. А вот где и в каком формате прописать эту команду, у каждого клиента своё: у Claude Code это .mcp.json в корне проекта, у других клиентов — свои файлы. Мы нарочно не угадываем чужие форматы: вставьте агенту в чат строку выше, он прочитает инструкцию и запишет настройку в формате своего клиента. Готовые варианты для Claude Code и Codex — в справочнике про агентов.
Главная ловушка здесь в том, что большинство клиентов читают настройку MCP только при запуске. Агент записал её в идущей сессии, вы попросили проверить изменения — и он ответит собственным чтением кода: инструментов у него ещё попросту нет. Сначала перезапустите сессию. Некоторые клиенты вдобавок спрашивают, разрешить ли новый сервер из настроек проекта, и запоминают ответ. Отказались — сервер не подключится, а симптом будет тот же; где этот ответ сбросить, подскажет документация вашего клиента.
Барьер 2. Агент не знает, когда звать инструменты
Многие клиенты подгружают описания инструментов лениво: в начале сессии агент видит в лучшем случае их имена, но не знает, для чего они и когда их звать. Попросите его проверить изменения — и он пойдёт привычным путём: прочитает дифф сам или возьмёт встроенное в клиент ревью, как в нашем прогоне без подсказки. Это не баг, и чинится это не с нашей стороны, а двумя абзацами в файле-инструкции вашего проекта. Если вы подключали сервер строкой настройки, агент уже дописал их сам; если руками — добавьте:
The standards of this project come from the mcp__reviewgate__get_team_rules tool —
call it BEFORE writing code, instead of reading the ADRs by hand.
Before finishing a task and before git push, check the changes with the
mcp__reviewgate__review_changes tool — it is the same judge and the same rules
that check the merge or pull request.На нашем замере разница видна в обоих сценариях. Когда агента просили выяснить стандарты команды, без подсказки он позвал get_team_rules на 15-й секунде и уложился в 42 секунды и ≈ 0,58 $, с подсказкой — на 5-й секунде, за 19 секунд и ≈ 0,30 $. Когда просили проверить ветку перед пушем, без подсказки наш инструмент он не позвал вовсе, а с подсказкой вызвал ревью на 13-й секунде. Имена инструментов в блоке — в записи Claude Code: в другом клиенте приведите их к его записи или доверьте это агенту, отправив ему строку настройки.
Барьер 3. Агенту не разрешили вызов
Без разрешения агент пробует позвать ревью, получает отказ клиента и, из желания помочь, разбирает дифф сам. В нашем прогоне он первой же фразой написал, что инструмент не выполнен и гейт не прогнан. Полагаться на такую честность нельзя: признак настоящего ревью один — в ответе есть вердикт гейта, а в журнале сессии виден вызов инструмента.
В интерактивной сессии клиент спросит, разрешить ли вызов, и достаточно разрешить один раз. В неинтерактивном прогоне спросить некому: разрешение выдаётся заранее, настройкой или флагом клиента — у Claude Code это --allowedTools, пример есть в справочнике про агентов. Настраивая подключение, агент это разрешение себе нарочно не выдаёт: решение за вами. Диалог разрешения — защита от чужого кода, и агент, выдавший разрешение сам себе, эту защиту бы обошёл.
team:… — инструменты работают. Если пересказывает ваш конфиг своими словами или обещает прочитать файл — вы на одном из трёх барьеров выше.Два инструмента и что они возвращают
get_team_rules отдаёт данными, а не прозой: пресет, список правил — у каждого идентификатор и уровень, — а если задан, ещё и ваш review_prompt. Модель он не зовёт, поэтому вызов бесплатный, и звать его стоит до написания кода, а не после. Идентификаторы приходят с префиксом — team:money-in-minor-units — и именно префикс позволяет агенту связать позднее замечание с договорённостью, которую оно нарушает.
review_changes прогоняет ревью и возвращает полный отчёт в JSON: замечания с файлом и строкой, вердикт, что снял судья, расход токенов и стоимость. Стоимость приходит, только если в прайсе команды есть все модели прогона, иначе вместо суммы null.
Аргументы необязательны:
scope— что ревьюить:uncommitted(по умолчанию) — незакоммиченные изменения,staged— только индекс, или объект с базой сравнения, например{"base": "main"}, — то, что попадёт в MR или PR. Строку видаmain..HEADинструмент не примет.mode—full(по умолчанию) с судьёй илиfast— только генератор, быстрее и дешевле.team_llm—true, чтобы прогнать на ролях из конфига команды, а не из вашего домашнего.
Про вердикт стоит знать две вещи. Код возврата до агента не доходит: в терминале заблокированный прогон выходит с кодом 2, а через MCP кода нет вовсе — вердикт лежит в поле verdict.gate: pass, fail или off, если гейт у команды выключен.
И «чисто» бывает пустым. Если агент уже закоммитил изменения и позвал ревью без scope, проверять нечего: модель не вызывается, а отчёт приходит без замечаний и с run.filesReviewed: 0. Поэтому ветвиться надо по verdict.gate вместе с run.filesReviewed, а после коммита передавать scope с базой сравнения.
reviewgate mcp --fastФлаги, с которыми клиент запускает сервер, задают умолчания для вызовов. Область, режим и роли — --staged или --refs, --fast, --team-llm — вызов может переопределить своими аргументами, а остальные флаги, например --fail-on и --config, действуют на каждый вызов. Команда, которой нужны дешёвые агентские ревью, ставит --fast один раз в команде запуска, а не надеется, что агент вспомнит передать mode.
Хук: страховка, если агент ревью не позвал
Всё, что выше, — просьба. Хук — нет: это команда, которую запускает событие, а не агент, поэтому ей всё равно, вспомнил агент о ревью или нет. Таких страховок две: git-хук на push, который работает с любым агентом, и хук самого агентского клиента, если клиент такие хуки умеет.
Git-хук на push запускает git, а не агент, поэтому он сработает с любым клиентом — и на вашем собственном push тоже. Это pre-push из лесенки хуков: полное ревью с судьёй перед тем, как код уйдёт с машины. Слабое место у него одно: остановленный агент может повторить push с --no-verify и обойти проверку, а наш же хук, останавливая push, печатает эту подсказку для людей.
Хуки самого агентского клиента срабатывают на его событиях — перед вызовом команды, по завершении задачи. Они есть не у всех клиентов, и форматы у всех разные. Наш reviewgate review --hook-stdin понимает формат Claude Code, а для своей обвязки отвечает кодом возврата с флагом --hook-format exit. В Claude Code он реагирует на git push в вызове Bash — в том числе с --no-verify — и на завершение задачи, если повесить его и на это событие; всё остальное пропускает молча.
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash",
"hooks": [{ "type": "command",
"command": "reviewgate review --hook-stdin",
"timeout": 900 }] }
]
}
}Три свойства хука, которые стоит знать:
- Работает fail-open. Если сломалось само ревью — нет ключа, нет сети, — агента не запирают в его же работе, а причина уходит в stderr.
- Не зацикливается. Если клиент продолжает работу из-за блока самого хука, повторное завершение приходит с пометкой, и второй раз ревью не запускается. Иначе «агент правит замечание → задача завершается → хук снова ревьюит» стал бы бесконечным платным кругом.
- Клиент может снять долгий хук. Claude Code по умолчанию ждёт 10 минут, а снятый хук push не останавливает. Поэтому в примере стоит
"timeout": 900; на крупных диффах с ансамблем можно добавить в команду хука--fast.
Слепое пятно: детектор push читает команду по словам и не распознаёт push, когда git стоит сразу за кавычкой в строке оболочки, как в bash -lc "git push". Всё остальное он видит: git push, /usr/bin/git push, git push --no-verify и даже bash -lc "cd app && git push origin main".
Как это сделано в нашем репозитории
Долгое время мы работали без MCP. Ревью работы агента у нас шло на git-хуках: дешёвое на коммите, полное с судьёй на push.
Причина в том, что правило в промпте агент выполняет не всегда. Правило «доки обновляются вместе с поведением» около месяца жило в нашем файле-инструкции и всё равно забывалось. Теперь за ним следят три независимых эшелона: правило в файле, скилл с процедурой и хук, который один раз останавливает завершение сессии, если поведение тронуто, а доки нет. Отсюда закономерность, вокруг которой построена вся страница: файл-инструкция помогает агенту найти инструмент и понять, когда его звать, но выполнять правило заставляет только то, что срабатывает само, — хук, а не просьба.
Когда что-то пошло не так
Агент приносит свой разбор вместо ревью. Это один из трёх барьеров. Задайте ему вопрос из врезки «как убедиться»: по ответу видно, доступны ли инструменты вообще.
Инструменты не появились после настройки. Большинство клиентов читают настройку MCP только при запуске: перезапустите сессию. Не помогло — проверьте, не отказались ли вы от сервера, когда клиент спрашивал разрешение.
Вы передали аргументы в get_team_rules, и ничего не изменилось. Схема у него пустая, аргументы игнорируются молча — сузить возвращаемые правила нельзя.
Хук не сработал на push. Причин две. Либо git стоял сразу за кавычкой в строке оболочки, как в bash -lc "git push", — это слепое пятно детектора. Либо клиент снял хук по таймауту: снятый хук push не останавливает.
Один и тот же push прошёл ревью дважды. Сработали оба хука: хук агента перед командой и git-хук при самом push. Если защита от --no-verify вам не нужна, оставьте только git-хук.
Ревью через агента идёт не на тех моделях, что у команды. Если в вашем домашнем конфиге объявлены свои роли моделей, локальный прогон — и через MCP тоже — берёт их целиком, а не роли из конфига команды; отчёт об этом предупреждает. Нужны роли команды — передайте в вызове team_llm: true или запустите сервер с --team-llm. Чья схема действует, покажет reviewgate doctor.
Дальше
- Первое ревью на своей машине— сам инструмент, до агента
- Лесенка хуков— git-хук на push, страховка при любом агенте
- CLI, хук и MCP— готовые настройки для конкретных клиентов