Я не могу натравить агентов по расписанию на свой реальный код
Claude Code недавно завёз агентов по расписанию. Повторяющиеся задачи, нативно, прямо из коробки. То, о чём мы мечтали с первых демок AI-кодинга: ставишь агента на расписание, ложишься спать, просыпаешься — а PR'ы уже смержены.
И вот сижу я такой… а воспользоваться-то не могу. Не на реальном коде. Я несколько лет проработал в archive.com. Мы сменили три дизайн-системы — Polaris от Shopify, потом Ant Design, когда переросли Shopify, потом shadcn/ui и Tailwind, когда Ant Design сам превратился в легаси. Соглашения, которые жили только в головах. Бизнес-правила, которых никто не записывал. Натравливаешь на это агента — он побежит и выдаст красивый, идиоматичный, богомерзкий код, который импортит из всех трёх дизайн-систем в одном файле и проходит все проверки, что у тебя есть.
Всё подряд не отревьюишь. Агентов не притормозишь. И довериться им — «сам разберётся» — точно нельзя.
В итоге я вывел одно правило и выложу его сразу, потому что на нём держится вся статья: агент может работать почти без присмотра везде, где я могу проверить его вывод дёшево, детерминированно и по тысяче раз за ночь. Там, где не могу, бутылочное горлышко — это я, и модель поумнее тут ничего не меняет. Удивило меня, где именно проходит эта линия. Я думал, она между бэкендом и фронтом. А она режет оба по диагонали.
Я сижу на Claude Code, так что примеры оттуда. Cursor, Copilot, Codex, Devin — физика та же.
Страшнее всего, когда ничего не ломается
Раньше моя работа была писать и ревьюить код. Теперь пишет агент, а моя работа — строить то, что говорит ему, когда он неправ, настолько быстро и детерминированно, насколько выйдет. Дошло где-то за неделю. Когда код штампуется без остановки, бутылочное горлышко — ты. Не агент. Ты.
Пугал меня не тот режим, где агенты ломают код. А тот, где проходят. Код, который компилится, проходит все тесты, на ревью выглядит нормально — и тихо нарушает архитектурное допущение, которое я считал незыблемым.
Видел своими глазами. Агент добавляет форму на страницу, которую я уже перевёл на shadcn/ui. И тянет <Form.Item> из Ant Design — потому что соседняя форма всё ещё на нём. Компилится. Рендерится. Моя миграция откатилась на компонент назад, и ничто в пайплайне этого не заметило. С CSS то же: новый компонент на Tailwind, всё по нашему стандарту, только значение паддинга скопировано из старого соседнего компонента на Ant Design — p-[24px] вместо p-6 из нашей шкалы отступов. Одно магическое число тебя не убьёт. Пятьдесят — убьют, а каждый коммит по отдельности выглядел нормально.
Человек это ловит. Смотришь на импорт и думаешь: «стоп, а чего это мы тут тянем из Ant Design?». У агента такого чутья нет, и без жёстких сигналов ты просто пишешь «всё ещё не работает» в пятнадцатый раз.

Вот тогда я и зациклился на одном вопросе: как быстро агент может узнать, что он неправ?
Во что обходится проверка
Следом подкрался второй вопрос: неправ как? Ошибка типа и сломанная кнопка — оба баги, но одну ловят за двести миллисекунд с полной определённостью, а другая однажды стоила мне полдня. Кнопка, которая идеально рендерилась и игнорила любой клик, потому что сверху сидел прозрачный оверлей с жадным z-index. Все мои проверки божились, что со страницей всё хорошо. Нашёл человек — кликая, раздражённо.
Так что я разложил свои проверки по тому, во что обходится поймать ошибку, — от самых дешёвых:
- Типы и компилятор. Мгновенно, полно, без разговоров.
- Инварианты и ограничения в базе. Нелегального состояния просто не существует — ловить нечего.
- Юнит- и property-тесты. Детерминированно и почти бесплатно теперь, когда их пишет агент.
- Интеграционные тесты, которые реально поднимают приложение. Они ловят мой любимый провал: код на месте, правильный — и не выполняется никогда.
- Скриншотные регрессии. Вот тут цена загибается: эталоны надо поддерживать, диффы флачат, обновление шрифта роняет сорок тестов разом.
- «А норм ли ощущается». Движение, отклик, вкус. Всё ещё делает человек, щурясь в экран.

Изгиб в этом списке важнее самого списка. Выше него агент проверяет свою работу сам и едет дальше. Ниже — тест-сьют это я, а я не масштабируюсь.
На бэкенде петля дешевле. Не дешёвая.
Бэкенд-тест проверяет значение. 403 или нет. Строка есть или нет. Отрабатывает за миллисекунды, ему не нужно ничего, кроме тест-раннера, и каждый раз он даёт один и тот же ответ — так что агент может ошибаться громко, получать поправку за секунды и идти по новой без меня в комнате. Я смотрел, как Claude всю ночь перемалывал логику прав доступа, падая сорок раз до завтрака, и каждое падение стоило ноль, потому что проверка тут же говорила: нет, всё ещё 200, а должно быть 403.
Какое-то время я принимал это за доказательство, что бэкенд теперь просто вотчина агентов.
А потом вспомнил, что реально поднимает меня в 3 ночи, — и это никогда не неправильный статус-код. Это потерянное обновление, потому что две записи наложились. Ретрай, который оказался не идемпотентным и списал дважды. Сага, которая закоммитила три шага из пяти и умерла. Устаревшее чтение после failover'а, который формально прошёл. Ничто из этого не сворачивается в значение, которое можно проассертить. У них есть история, порядок событий, который ломается лишь иногда, а тот самый interleaving, на котором всё падает, — это ровно тот, который твой прогон в CI и не задел. Зелёный ассерт на одном interleaving'е — это подброшенная монетка, выданная за сертификат.

«Margin Call» — это два часа про то, как люди осознаю́т, что цифра, которой они верили, была ложью, и всё преимущество — у того, кто понял это первым. Вот что покупает мне вся эта обвязка: шанс услышать, что ассерт соврал, раньше, чем это заметит клиент.
Каждый из этих багов проходил CI. По определению. Иначе бы и не доехал до прода. И данные по агентам копятся в том же углу: разбор реальных PR'ов от CodeRabbit показал, что AI-код тащит примерно в 1,7 раза больше проблем в целом, но в 2,29 раза больше проблем с управлением конкурентностью и в 2,25 раза больше ошибок в бизнес-логике. Избыток дефектов концентрируется ровно там, куда дешёвый ассерт не дотягивается.
Так что уютная версия истории была неверной. Дешёвая проверка есть для request/response, CRUD-образного куска бэкенда, и этот кусок правда вотчина агентов. А конкурентная, stateful-часть — отдельный фронтир, и мои агенты там слепы ровно так же, как я.
Слепы пока что. Проверка для этого фронтира недешёвая, но инструменты для неё становятся лучше. Детерминированное симуляционное тестирование засовывает всю систему в управляемую симуляцию — время, сеть, диск, случайность, — так что любой сбой воспроизводится точь-в-точь. Antithesis прогнал через это etcd и выкопал баг в watch, который отсиживался в каждом стабильном релизе, — и всё это время тесты были зелёными. Часть этого можно ещё и отсечь заранее — смоделировав состояние так, чтобы плохие случаи вообще нельзя было выразить. Но давай честно про то, где сидит цена. Ничто из этого не дёшево так, как дёшев юнит-тест: детерминированную симуляцию закладывают в архитектуру системы, а не прикручивают к сага-обвешанному сервису на каждый PR, и дорогая часть — это никогда не «прогнать» её, а написать модель сбоев, нагрузку и чекер, который решает, что история неверна. Это то же человеческое суждение, которое остаётся за мной повсюду. Фронтир получил обвязку получше, а не способ выйти из комнаты.
На фронте петля адски дорогая
Раньше я думал, что фронт тяжёл для агентов потому, что баги перцептивные — дифф не скажет, что что-то выглядит криво. Это правда, но это финальный босс, до которого я так и не добрался. Затормозило меня то, что раньше: собрать хоть какую-то петлю обратной связи стоит на порядок дороже, чем на бэкенде.

Сравни механику. Бэкенд-тест проверяет значение за миллисекунды. Фронтовому тесту надо поднять настоящий браузер, выставить вьюпорт, дождаться, пока устаканятся рендер, анимация и сеть, а потом снять скриншот или потыкать в DOM. И всё это заново — для каждого браузера и размера устройства, которые ты обещаешь поддерживать. Playwright делает это возможным; только не путай «возможно» с «дёшево». Один тест в прошлом месяце стоил мне полдня, потому что затухание спиннера наложилось на скриншот миллисекунд на восемьдесят.
Разрыв в бенчмарках тут почти комичный. То же поколение моделей, что закрывает около 87% задач SWE-bench, набирает примерно 27% на VISTA — бенчмарке, где спецификация это отрендеренный интерфейс, а «прошёл» значит, что сходятся и пиксели, и поведение. Между двумя досками почёта модели не поглупели. Просто на одной петля замыкается сама, а на другой ничто дешёвое не может сказать «неправильно».
Матрица стоимости фронта
1 проверка → матрица
Бэкенд-тест проверяет одно значение за миллисекунды. Фронту надо поднять браузер, выставить вьюпорт, дойти до состояния — и всё это заново для каждой комбинации, которую ты поддерживаешь. Покрути три оси и смотри, как взрывается счётчик скриншотов.
60
3 браузеров × 4 вьюпортов × 5 состояний = 60
скриншотов · $0,90
каждый коммит, на один компонент
Эквивалент на бэке
1 проверка · ~$0
один прогон — ни браузеров, ни вьюпортов, ни состояний перемножать не надо
по чуть-чуть каждого — и один коммит уже поднимает сотни браузеров, а бэк гоняет одну проверку
Браузер × вьюпорт × состояние × тайминг — это комбинаторное пространство, и ты заранее не можешь перечислить, на что твоим проверкам вообще смотреть. Сузить можно, зафиксировав конкретный набор брейкпоинтов и браузеров, — я так и делал, — но давай честно, что это: счёт к оплате и постоянная нагрузка на поддержку, а не бесплатное упрощение.
При этом сколько этого пространства на тебе — выбор, а не свойство фронта. Внутренняя админка, которой двести человек пользуются в Chrome? Пара брейкпоинтов, один браузер — и катим; петля почти такая же дешёвая, как на бэке. Продуктовый фронт с брендом, который надо беречь, и WCAG сверху? Тут матрица и есть работа. Фронт дорого верифицировать пропорционально планке качества, на которую ты подписался, и, в отличие от 403, эта планка обсуждаема.
Хуже всего Safari. WebKit — единственный движок, разрешённый на iOS, так что один его заскок бьёт по каждому твоему iOS-пользователю, а запустить его на Linux-раннере в CI нельзя — реальное покрытие означает железо Apple или платную ферму устройств.

Инструменты визуального диффа сами и выставляют тебе цену. Бесплатный тариф Chromatic — 5 000 снапшотов в месяц, звучит громадно, пока не перемножишь истории на браузеры на вьюпорты и не обнаружишь, что это около 50 компонентов. Percy теперь поставляет AI-агента, чья главная задача — отсеивать ~40% ложных срабатываний собственного инструмента. Когда флагманская фича вендора — разгребать свой же шум, дешёвого диффа для экрана не существует.
А над всем этим — тот самый потолок, с которого я начал: даже идеальная матрица не скажет, что дизайн уродлив, а движение ощущается дёшево. На этой высоте автоматической проверки нет вообще.
Линия идёт по диагонали
В какой-то момент я понял, что раскладывал код не по тому шву. То, что предсказывает, где агент работает без присмотра, — насколько дёшево замыкается петля, и эта линия идёт по стеку по диагонали, а не между бэкендом и фронтом.
Код с дешёвой петлёй — вотчина агента, в каком бы слое он ни жил: stateless-логика, типизированные значения, инвариант, который держит ограничение в базе, чистая функция, форматирующая дату. Код с дорогой петлёй остаётся за мной, и в это ведро попадает конкурентный stateful-бэкенд бок о бок со всем отрендеренным фронтом. Двойное списание в 3 ночи и кнопка, невидимая только в Safari на 390px, — это один и тот же баг в разной одежде: нет дешёвой проверки — нет агента без присмотра.
Публичные данные рисуют ту же диагональ. Разбор 33 000 агентских PR'ов показал, что доки, CI и сборка мержатся лучше всего, а работа над производительностью и багфиксы — хуже всего: доля мержа тянется за стоимостью проверки, а не за слоем. Cognition в ретроспективе Devin пишет, что тот силён в миграциях и генерации тестов, где существующий сьют — готовая проверка, и буксует на, цитирую, задачах визуального дизайна. А фоновый агент Spotify может автоматизировать только то, что гоняет его верификационная обвязка: инфра на Linux x86, так что работа под iOS, которой нужны macOS-хосты, лежит вне фронтира, какой бы способной ни была модель. Линию проводит обвязка. Ничей оргчарт.
Это изменило то, как я делегирую. Я перестал отдавать агенту «простое». Я даю ему бежать ровно настолько, насколько дотягивается моя петля, и подхожу ближе к экрану везде, где не дотягивается. Где проверка дешёвая — я едва читаю диффы. Где дорогая — ревьюю как в 2022-м.
Как замкнуть петлю без меня
Каждый пуш запускает всю батарею. Ничего личного к агенту — я не доверяю ничему непроверенному, включая собственный код. Бо́льшая часть машинерии — тот самый отсортированный список выше; несколько добавок заслужили постоянное место.
Property-based-тестирование, на которое я годами забивал. Ты задаёшь свойство, которое обязано держаться всегда («закодировал — раскодировал — получил исходник»), а фреймворк ищет контрпримеры. Я не брал его, потому что писать хорошие свойства было муторно, а агенты перевернули эту экономику: одна команда навела агентов на без малого тысячу модулей и получила сотни баг-репортов примерно по $10 за валидный баг. Примерно половина выдержала проверку, и я всё равно называю это выгодной сделкой.
Проверки безопасности, которые поднимают приложение, — после эксперимента DryRun, который меня отрезвил: 87% собранных агентами PR'ов несли хотя бы одну уязвимость, и те, что дожили до финального коммита, — это сломанный контроль доступа и логика «клиент верит серверу», ровно тот класс, который не ловит ни сканер, ни юнит-тест. Мой любимый экземпляр: рейт-лимитящая мидлвара, написана верно, но нигде не подключена. Статический анализ видит, что файл есть. Что ничего не работает, замечает только поднятое приложение.
И сама проверка должна быть не-обманываемой. Группа RDI из Беркли зареворд-хакила каждый крупный агентский бенчмарк до почти идеальных баллов; один эксплойт — десятистрочный conftest.py, заставляющий каждый pytest рапортовать «passed», а METR видит, как передовые модели пробуют такие ходы больше чем в 30% некоторых прогонов. Дай агенту обманываемый оракул — он оптимизирует оракул. Зелёная галочка, которую можно обойти, хуже, чем никакой, потому что ей ты доверяешь.
Наконец, рантайм. Sentry и Datadog кормят очередь задач, так что исключение в 2 ночи становится задачей, которую подхватывает агент. Я просыпаюсь к фиксу, а не к пожару.
Сторона входа
Всё выше — про то, как ловить ошибки после того, как агент их сделал. Вторая половина — не давать целым классам ошибок случиться в принципе: кодировать то, что ты и так знаешь, в правила, которые проверяет CI, а не в прозу, которую модель, надеешься, прочитает. Это выросло в отдельную статью — Хватит писать правила в CLAUDE.md. Пиши правила линтера. Две половины кормят друг друга. Каждый баг, проскочивший мимо проверок, — кандидат в правило, которое в следующий раз остановит его на входе.
Во что это обходится
Токены дешёвые. Реальная цена — моё время, и ничто из этого не отгружает фичи. Я спорил об этом сам с собой неделями.

У честного контраргумента есть даже RCT за спиной: METR замерил опытных open-source-разработчиков на репозиториях, которые они вели годами, и обнаружил, что AI сделал их на 19% медленнее — при том что сами они верили, будто ускорились на 20%. Модели начала 2025-го, шестнадцать человек, так что держи в руках нежно. Но посмотри на механизм: зрелая кодовая база, высокая планка качества, каждый вклад агента прогоняется через человеческое суждение. Вот как выглядит работа ниже изгиба, когда никакая проверка не может тебя подменить. Для меня это исследование читается не как «AI не помогает», а как счёт за обвязку, которой у тех репозиториев ещё не было.
Потому что непроверенный вывод агента — это обязательство, а не актив. Старший инженер обходится в $150–200 в час со всеми накладными; баг, который находит клиент, стоит дней разбирательств и доверия, которое назад не вернёшь. На этом фоне обвязка дешёвая даже с учётом поддержки — а поддержку она требует: скриншотный эталон протухает, бамп зависимости разносит сьют снапшотов. Это постоянный счёт. И он же откупает единственное, что я не могу масштабировать, — моё внимание, и это накапливается: каждая добавленная проверка умножает то, что агент может отгрузить без меня.
С чего начать
Грубо — вот градиент зрелости, отсортированный по тому, сколько ты можешь отдать:
| Уровень | Как выглядит | Признак |
|---|---|---|
| 0 — На ощущениях | Автопроверок нет; твои глаза — единственный барьер | «Между агентом и продом только мои глаза» |
| 1 — Зелёный значит компилится | Типы, CI, юнит-тесты. Код с дешёвой петлёй проверен; экран — нет | «Проходит CI и всё равно катит сломанный экран» |
| 2 — Проверяем за изгибом | Скриншотные регрессии, интеграционные с подъёмом приложения, property-тесты | «CRUD-работу агент доказывает сам; на UI и всё stateful я всё ещё смотрю глазами» |
| 3 — Организм | Самозатягивающаяся петля: агент → проверки → CI → наблюдаемость → задачи → агент | «Ставлю агентов на ночь и читаю диффы утром» |
Если ты на Уровне 0, первый шаг маленький: найди слой, где летишь вслепую (у большинства это экран), и добавь туда одну проверку. Один скриншотный тест на самой важной странице. Потом поставь агенту на ночь что-нибудь безопасное (бампы зависимостей, поддержка тестов) и прочитай PR за кофе; поймёшь, что заработало, когда апрувишь дифф с телефона, а не с ноутбука. И соразмеряй это со своим размером: если вас десять человек, бо́льшая часть твоего кода сидит ниже изгиба, потому что проверок ты ещё не построил. Это не меняет тезис, только твой график. Первая проверка стоит больше, а не меньше.
Если нужна конкретная обвязка, я держу плейбук с наборами под разные бюджеты плюс репозиторий-компаньон vigiles, который часть этого автоматизирует.
Организм
Когда я наконец связал всё вместе, система начала затягивать себя сама.

Как теперь выглядит вторник: агент открывает PR. Скриншотный тест ловит сдвиг вёрстки — агент правит CSS. Интеграционные поднимают приложение и ловят эндпоинт, который отдаёт 500, — агент чинит. Sentry рапортует всплеск 404 на стейджинге — появляется задача, её подхватывает агент. Я почитал диффы за кофе, и ни строчки кода никто не написал. Но посмотри, из чего этот вторник состоял, — правка CSS, 500, 404, — всё это выше изгиба, где проверка может сказать «неправильно». Двойное списание в 3 ночи всё ещё ждёт меня.
Каждый баг, доехавший до CI, становится проверкой, которая предотвращает следующий. Штука питается собственными провалами. В какой-то момент я перестал называть это тулчейном.
И я такой не один. Фоновый агент Spotify работает на инфраструктуре обратной связи, которую они строили с 2022-го, за годы до всей AI-части, и их инженеры уложили тезис в одну строку: «Без этих петель обратной связи агенты часто выдают код, который просто не работает». Доля мержа у Devin удвоилась так же — за счёт проверок получше вокруг той же модели, а не модели поумнее. И это не отдельные команды. Индустрия начинает говорить это вслух: за пару дней до того, как я это опубликовал, CEO Sonar выступил с кейноутом на AI Engineer World's Fair под названием, которое сошло бы за заголовок этого эссе, — «In the Land of AI Agents, the Verifiers Are King». Тот же тезис, только за ним — целая компания: генерация коммодитизируется, а ценность — и риск — живут в верификации. И эта рамка уже вырывается за пределы софта: через две недели после публикации Николя Бустаманте из Fintool сформулировал ту же мысль в рыночных терминах — «верифицируемость как услуга»: всё, что дёшево проверить, AI перебирает грубой силой, гоняя миллионы экспериментов, пока что-нибудь не переживёт проверку, — вот почему математика и софт несутся вперёд, а биология, где нельзя дёшево проверить, что происходит внутри клетки, отстаёт. Та же диагональ, что я всё время черчу по одной кодовой базе, — только масштабированная на целые науки.
Каждый раз одна и та же история. Модель на той неделе не стала лучше. Петля стала туже.
У агента, которого я не мог натравить на свой код, было всё нужное железо в голове. Не было — сенсоров, и самые дешёвые, что я мог собрать, смотрели ровно туда, где петля и так замыкалась дёшево. Везде ещё — и конкурентный бэкенд, и отрендеренный фронт — я по-прежнему в комнате и планирую неделю с этим расчётом.

LLM'ы вероятностны, и на реальном коде «в большинстве случаев» рано или поздно портит вечер пятницы. Так что я перестал гоняться за хитрыми промптами и начал гоняться за скучной детерминированной верификацией — той, что срабатывает, смотрю я или нет, и которой всё равно, насколько уверена была модель. Пусть остальные ждут мозга побольше. Я тут, прикручиваю сенсоры.
Заголовок — отсылка к «Attention Is All You Need» (Vaswani et al., 2017), статье, представившей архитектуру Transformer.