Почему один агент на всё — плохая идея
Первый сценарий работы с ИИ всегда одинаковый: один диалог, в нём вы формулируете задачу, агент пишет код, вы говорите «хорошо, применяй». Работает — до определённого масштаба.
Ломается это в трёх местах, и все три я прошёл лично.
Агент не может проверить сам себя. Он написал код, исходя из своего понимания задачи. Проверять он будет ровно то же понимание. Если оно было неверным, проверка это не поймает — она подтвердит, что код делает то, что автор задумал. У меня был случай: агент завёл элементы справочника, его собственная проверка честно ответила «созданы, существуют», а в интерфейсе их не было. Проверка проверяла существование, а не пригодность.
Расплывчатая задача даёт расплывчатый результат. «Сделай лучше», «перепиши по-нормальному», «как в соседнем проекте» — на такой вход агент выдаёт что угодно, и спорить потом не о чем: критерия не было.
Один контекст на всё переполняется. Агент, который держит в голове и постановку, и код, и историю обсуждения, и правила проекта, начинает терять детали. Первыми теряются ограничения — именно то, что важнее всего.
Решение — разделить роли. Не ради моды на мультиагентность, а потому что каждая из трёх проблем лечится именно разделением.
Три роли
Координатор. Превращает пожелание в спецификацию, выбирает исполнителя, принимает работу. Держит в голове проект целиком, но не пишет код.
Исполнитель. Получает спеку, пишет код, возвращает результат. Проекта целиком не знает и знать не должен — у него есть задача с границами.
Приёмщик. Читает дифф по фиксированному списку. Задачу видит через спеку, а не через объяснения автора.
Роли могут исполняться разными моделями, разными сессиями одной модели или человеком в роли координатора. Принципиально другое: приёмщик не должен быть тем же, кто писал. Это не про недоверие к модели, а про то, что проверка собственной работы структурно бесполезна.
Спецификация: что обязано быть
Главный вывод за год: качество результата определяется спекой, а не моделью. Хороший бриф вытягивает средний инструмент, плохой топит лучший.
Список полей, без которых задачу не отдаю:
Цель одной строкой и критерий готовности. Критерий обязан быть проверяемым. Не «работает корректно», а «метод возвращает 200 и поле balance при валидном токене, 401 при просроченном».
Репозиторий и хост. Указать явно, где истина. У меня боевой код Rust-бэкенда живёт на сервере, а локальная копия отстаёт — если этого не написать, агент честно поправит локальную и отчитается об успехе.
Файлы, которые трогать — и которые нельзя. Второй список важнее первого. Без него агент «заодно причешет» соседний модуль, и дифф разбухнет вчетверо.
Контракт, если это API. Авторизация, формат запроса и ответа, коды ошибок, ограничение частоты. Всё, что не описано, будет придумано.
Пограничные случаи списком. Именно списком. «Учти крайние случаи» — это не требование, это пожелание. «Пустой список, отрицательная сумма, повторный запрос с тем же идентификатором, истёкший токен» — требование.
Правило проверки спеки перед отправкой: прочитайте её как человек, который не участвовал в обсуждении. Если остаются вопросы — их задаст и агент, только молча, ответив на них по-своему.
Антипаттерны брифа
Формулировки, которые гарантированно дают плохой результат:
- «Сделай лучше» — критерия нет, любой результат формально подходит;
- «Как в соседнем проекте» — агент не знает, что именно вы имеете в виду, и скопирует не то. Отдельно опасно, когда проекты принадлежат разным организациям: чужая бизнес-логика переезжает вместе с кодом;
- «Перепиши по-человечески» — оценочное суждение вместо требования;
- «Оптимизируй» — без метрики и целевого значения это приглашение к произвольным изменениям;
- «Заодно поправь всё остальное» — гарантия того, что дифф станет нечитаемым, а вместе с полезными правками приедут вредные.
Общее у всех: отсутствие проверяемого критерия. Если по формулировке нельзя однозначно сказать «сделано» или «не сделано» — это не задача.
Выбор исполнителя
Разные инструменты сильны в разном. У меня сложилось грубое разделение: одна модель лучше держит длинные архитектурные рассуждения и работу с системным кодом, другая — визуальную часть и интерфейсы, третья хороша на массовых механических правках.
Единственное правило, которое я тут держу жёстко: выбирать по качеству под задачу, а не по цене. Экономия на исполнителе для правки, которая пойдёт в боевую базу с кассами, — ложная. Стоимость разбора последствий превышает разницу в цене на порядки.
Отдельный вопрос — специализация по слоям. Правки бэкенда, интерфейса и учётной системы требуют разного контекста и разных правил. Смешивать их в одной задаче — верный способ получить работу, наполовину сделанную не по правилам.
Приёмка: фиксированный список
Здесь ключевая мысль всей статьи: приёмка работает, только когда список стоп-факторов написан заранее.
Если оценивать каждый дифф «на глаз», вы будете принимать решения в контексте усталости, спешки и симпатии к красивому решению. Фиксированный список снимает это: вы не оцениваете, вы сверяетесь.
Мой список, общий для любого диффа:
- расходится со спекой, планом или журналом проекта — не принимать, независимо от качества кода;
- секреты в коде или в логах — стоп;
- внутренние данные утекли в клиентский API — закупочные цены, себестоимость, чужие идентификаторы — стоп;
TODO, «потом доделаю», выкинутые тесты, отключённые проверки — стоп;- правки не в том репозитории или не на том хосте — стоп.
Специфичные для слоя данных и денег:
- финансовая операция не в одной транзакции — стоп;
- списание с баланса сделано чтением с последующей записью вместо атомарного условного обновления — стоп, это гонка;
- нет уникального ограничения там, где возможен повтор внешнего запроса — стоп;
- нет сверки владельца ресурса с токеном — это межтенантный доступ к чужим данным.
Для учётной системы:
- правка расширения без бэкапа — стоп;
- применение без гейта компиляции — стоп;
- проведение документов или движение денег без явного подтверждения — стоп.
Список короткий, проверяется за минуты, и главное его свойство — он не обсуждается в момент приёмки. Обсуждается он в спокойное время, когда вы его пишете.
Почему нельзя принимать по отчёту
Отдельно, потому что это самая частая ошибка.
Агент возвращает «готово, всё работает, проверил». Соблазн принять велик, особенно когда задач много.
Проблема в том, что отчёт не врёт, но описывает не то. «Проверил» означает «выполнил проверку, которую сам придумал, исходя из своего понимания задачи». Если понимание было неполным, проверка это подтвердит.
У меня показательный случай: программная проверка сообщала, что объекты созданы и находятся поиском. Всё правда. При этом форма выбора их не показывала, потому что не были заполнены обязательные реквизиты, которые заполняются интерактивно. Обнаружилось это только по скриншоту от владельца бизнеса, который просто открыл список и не увидел записей.
Вывод: финальную проверку делает тот, кто смотрит на результат снаружи, а не изнутри логики автора. Для учётной системы это часто означает «глазами человека в интерфейсе», и заменить это ничем нельзя.
Стоп-кран поверх всех ролей
Над всей конструкцией стоит отдельный контур: список необратимых операций, перед которыми любой участник обязан остановиться и спросить.
Удаление и массовое изменение данных, движение денег, проведение документов, применение изменений без бэкапа, принудительная перезапись истории репозитория, ротация секретов, выкладка в сторы. Формат вопроса зафиксирован: что за команда, что она сломает, как откатывать.
Важная деталь: этот контур не зависит от роли. Координатор, исполнитель и приёмщик подчиняются ему одинаково. Иначе получается дыра: исполнитель спрашивает разрешения, а координатор, «который лучше понимает контекст», сам себе разрешает.
Второй контур — изоляция. Если организаций несколько, каждая задача начинается с явного указания, в чьём контуре она выполняется. Ошибка «применил в соседнюю базу» дороже плохого кода: вы вносите чужую логику в чужой учёт.
Чего эта схема не даёт
Честно про ограничения, потому что мультиагентность сейчас переоценена.
Она не делает результат правильным по бизнесу. Ни один агент не знает, должна ли персональная скидка складываться со статусной или заменять её. Это решение владельца бизнеса, и его надо получить до постановки задачи, а не после выката.
Она не заменяет проверку в интерфейсе. Формы, обязательные реквизиты, поведение рабочего места кассира — всё это проверяется открытием и просмотром.
Она не бесплатна по времени. Написать нормальную спеку — это двадцать минут. На простой правке дешевле сделать самому. Схема начинает окупаться на задачах от нескольких часов и на всём, что касается денег.
Она не отменяет знания предметной области. Агент найдёт регистр и напишет запрос, но поймёт ли он, что расход по подарочному сертификату пишет отчёт о розничных продажах, а не чек, — зависит от того, написали ли вы это в журнале проекта.
Выводы
1. Разделяйте написание и приёмку. Не из недоверия, а потому что автор проверяет своё понимание задачи, а не задачу.
2. Качество определяется спекой. Проверяемый критерий готовности, явные границы файлов, пограничные случаи списком. Без этого модель не важна.
3. Список стоп-факторов пишется заранее. В момент приёмки вы сверяетесь, а не рассуждаете. Рассуждать вы будете в пользу красивого решения.
4. Отчёт «готово» — не основание. Читайте дифф. Для учётной системы — смотрите результат в интерфейсе глазами.
5. Стоп-кран и изоляция контура — над ролями, а не внутри них. Иначе координатор сам себе разрешит то, чего не разрешил бы исполнителю.
Схема выглядит бюрократично, но по сути это обычное разделение труда, которое в командах разработки существует давно: постановка, реализация, ревью. Агенты не изобрели тут ничего нового — они просто сделали цену отсутствия этого разделения заметной сразу, а не через полгода.
Опыт годовой работы с ИИ-агентами над боевыми базами УТ 11.5, Rust-бэкендом и мобильным приложением розничной сети.
Вступайте в нашу телеграмм-группу Инфостарт