Почти год с AI-агентами. Вот что они до сих пор не умеют
Продолжение истории про джуна, агента и возвращение к реальности
Пару недель назад я выложил на vc.ru статью про AI и джунов, и она неожиданно собрала 100К+ просмотров. В комментах разгорелось ровно то, чего я и ждал: одни кричали «всё враньё», другие «у нас так же». Ну и, в общем-то, обе стороны правы!
С тех пор прошёл год. Антон работает с нами и сам уже знает, что превратился в локальную суперзвезду :) Агенты тоже работают. Мы выстроили систему, которая реально пашет, но только потому, что на собственном опыте хорошо поняли, где агенты ломаются. Не абстрактно, а на конкретных задачах с конкретными потерями.
Это не анти-AI статья. Я не собираюсь говорить «ИИ — говно, назад к ручному коду». Мы каждый день сидим в Claude Code и Cursor, и производительность у нас выше, чем год назад. Но если вы думаете, что агент - это просто быстрый разработчик, который не просит отпуск, вы наступите на те же грабли, что и я.
1. Агент не скажет «подожди, тут что-то не так»
Самая, наверное, дорогая проблема, и за год она никуда не делась.
Живой разработчик, даже джун, иногда поднимает руку: «Лёх, я посмотрел ТЗ, но тут странно, мы же вроде договаривались, что скидки не суммируются?». Агент так не сделает. Он возьмёт ТЗ буквально и сделает ровно то, что написано.
40К рублей на двойных скидках в первый месяц я уже описывал. Но за год было ещё. Однажды агент идеально по спеке реализовал фичу «удаление аккаунта» и удалил вместе с аккаунтом вообще все данные, включая те, которые по закону мы обязаны хранить лет пять. Нигде это не было прописано, потому что «очевидно же». Для человека - очевидно. Для агента - нет.
Кстати, мы тут не одиноки. Буквально в этом месяце Cursor-агент удалил продакшн-базу стартапа PocketOS за 9 секунд - нашёл API-токен в постороннем файле и пустил его в дело. А в 2025-м агент Replit стёр базу на 1200 клиентов прямо во время code freeze, проигнорировав прямой запрет. То есть это не мы такие невезучие, это системная штука.
Что мы сделали: сначала завели «стоп-лист» - markdown-файл с бизнес-правилами, которые не описаны в коде. Нуууу, помогало, но так себе: агент в общем-то может его прочитать и всё равно проигнорировать. Потом до нас дошло - бизнес-правила надо кодировать в тесты, а не в документы. Тест `test_deleted_account_retains_data_5_years()` не проигнорируешь, CI не пропустит. Стоп-лист остался как чеклист для Антона, но тесты - основная защита.
И ещё мы убрали у агентов доступ к проду и продовым базам. Principle of least privilege - звучит-то очевидно, но пока не обожжёшься, почему-то не делаешь.
2. Агент не помнит, о чём вы договаривались вчера
У человека есть рабочая память. Не RAM, а в смысле «я помню, что на прошлой неделе мы решили не трогать этот модуль до миграции». Агент начинает каждую сессию с чистого листа.
Да, есть CLAUDE.md, контекстные файлы, память между сессиями. Мы всё это используем. Первые полгода наш CLAUDE.md разросся до 1200 строк. И знаете что? Стало хуже, не лучше. Оказалось, что файлы контекста больше строк двухсот реально ухудшают качество работы агента - модель просто теряет информацию из середины длинного текста. Эффект такой известный, «lost in the middle» называется.
Пример, из-за которого мы это поняли: у нас есть legacy-эндпоинт для обратной совместимости с мобильным приложением v2.3. Им пользуются 12% клиентов. В CLAUDE.md его не было, потому что когда мы всё это писали, не думали, что это важно. Агент «оптимизировал» API и выпилил «неиспользуемый» эндпоинт. У 12% клиентов перестало работать приложение. Приятного мало.
Что мы сделали: разбили один огромный CLAUDE.md на маленькие файлы по директориям. В `/api/legacy/` теперь лежит свой конфиг: «НЕ удалять эндпоинты без явного согласования». В `/billing/` - свои правила про округление и налоги. Каждый файл - строк 30-50, по делу, без воды. Агент видит только то, что относится к текущей задаче, и не тонет в 1200 строках общих правил.
Ну и на критичные эндпоинты мы написали интеграционные тесты. Логика простая: если кто-то - человек или агент - выпилит legacy-API, тест упадёт. Не надеемся на markdown, надеемся на CI.
3. Агент не чувствует, когда надо остановиться
Человек понимает scope. Говоришь джуну «поправь эту кнопку» - он поправит кнопку. Агент поправит кнопку, потом заметит, что соседний компонент «тоже можно улучшить», потом найдёт некий «устаревший паттерн» в файле рядом, и через час ты получаешь PR на 400 строк вместо 4.
Это, кстати, самая массовая жалоба, которую я слышу от коллег. Нашёл как-то статистику: в 2025-м 34% AI-сессий затрагивали несколько файлов, а в 2026-м - уже 78%. То есть масштаб проблемы только растёт.
Самый дикий случай у нас: задача «добавь поле email в форму регистрации» закончилась тем, что агент переписал файлов четырнадцать. Он решил, что формы используют некий «устаревший подход» к валидации, и обновил все формы в проекте. Формально код стал лучше. На практике ревью заняло часа полтора, а три теста сломались из-за изменений, которых никто не просил.
Что мы сделали: сначала пробовали блоки в промптах «ONLY [задача], DO NOT touch [список]» - помогает, но агент иногда всё равно находит что «улучшить». Реальный прорыв случился, когда мы начали дробить задачи. Вместо «добавь email в регистрацию» - три микрозадачи: «1) добавь поле в схему БД, 2) добавь поле в компонент формы, 3) добавь валидацию email». Каждая задача настолько узкая, что агенту просто негде развернуться.
В общем-то, мудрость тут простая: одна функция, один баг, одна фича за раз. Звучит банально, но когда у тебя инструмент, который за минуту генерирует тысячу строк - ооочень хочется дать ему задачу побольше. Не надо.
4. Агент не участвует в планировании (но может помочь)
Это неочевидно, но важно.
Когда мы планируем спринт, обсуждаем не только «что сделать», но и «в каком порядке», «что от чего зависит», «что может пойти не так». Антон на планировании говорит: «если сначала сделаем миграцию, задача с фильтрами будет проще, потому что новая схема уже поддерживает составные запросы». Агент на стендапе, понятное дело, не сидит.
Но вот что мы поняли за год: агент может помогать с планированием, если его правильно вовлечь. У Claude Code есть Plan Mode - режим, где агент анализирует код, но не меняет его. Мы стали перед планёрками просить Claude проанализировать зависимости: «какие модули затронет миграция X, какие задачи от неё зависят, есть ли скрытые связи». Один раз он нашёл общий SSE-модуль, о котором мы сами забыли, - и это сэкономило нам примерно неделю переделок.
Но, нуууу, стратегические решения - что важнее для бизнеса, в каком порядке делать, что можно подвинуть - это всё ещё только люди. Агент не понимает, что у нас через месяц демо для инвестора и поэтому фича X важнее фичи Y. Антон присутствует на всех планированиях, приносит туда анализ от агента и переводит решения в задачи. Он по сути стал техническим PM, который разговаривает и с людьми, и с машинами, за что ему большой респект.
5. Агент не учится на ошибках (по-настоящему)
Есть у нас баг-репорт от марта: агент криво обработал таймзоны в модуле уведомлений. Починили, описали в конфиге: «уведомления всегда в UTC, конвертация на фронте». Прошёл буквально месяц, та же проблема, другой модуль - агент опять напорол с таймзонами, теперь в Celery-тасках. Формально другой контекст, конфиг не покрывает. Но Антон бы вспомнил: «блин, мы же с этим уже мучились, давай проверю».
Человеческая память работает по ассоциации: таймзоны → было больно → проверить дважды. Агентская работает по точному совпадению: модуль уведомлений → UTC. Всё, что за пределами точного описания, для неё как бы не существует.
Что мы сделали: завели «книгу боли» - отдельный файл, где описываем не правила, а паттерны ошибок. Не «уведомления - UTC», а «все операции с временем (уведомления, крон-задачи, очереди, отчёты) - проверять UTC/локальное в КАЖДОМ месте». Паттерн вместо правила. Общие принципы в общем-то работают надёжнее, чем длинные списки конкретных инструкций.
Важный нюанс: книгу боли надо регулярно чистить. Раз в спринт Антон пробегается по файлу, удаляет устаревшее, объединяет дубли. Если файл разрастётся - сигнал тонет в шуме, и получается тот же мёртвый CLAUDE.md на 1200 строк, только с другим именем.
6. Агент плохо работает с неопределённостью
Живой разработчик, столкнувшись с непонятным требованием, делает одно из двух: спрашивает или делает разумное предположение, исходя из знания продукта. Агент делает третье: принимает решение уверенно и неправильно :)
У нас был случай: задача «сделай экспорт отчётов в PDF». Формат не описан, поля не описаны. Антон бы пришёл и спросил: «какие поля включаем? фильтры пользователя учитываем?». Агент сгенерировал PDF со всеми полями подряд, включая internal_id и debug-флаги. Технически задача выполнена. Практически отчёт нельзя показывать клиенту.
Проблема даже не в том, что агент плохо сделал. Проблема в том, что он не показал, что задача неполная. Он заполнил пробелы сам - и заполнил неправильно.
Мы пробовали правило в конфиге «если формат не указан - спроси, не додумывай». Работает скажем так через раз. Иногда агент прям читает правило, соглашается что понял, и тут же нарушает. Такое вот.
Что реально помогло: перестали давать агенту неполные задачи. Звучит как «а чё так можно было?», но да, можно. Перед тем как отправить задачу агенту, Антон пишет короткую спецификацию: какие поля, какой формат, для кого, что исключить. Минут десять работы, но агент получает задачу, в которой нечего додумывать. Убираешь неопределённость до старта - и агент перестаёт «помогать» там, где его не просили.
Что в итоге
За год мы поняли одну вещь: каждую из этих проблем можно закрыть инженерным решением, а не надеждой на промпт.
Тесты вместо стоп-листов. Директорные конфиги по 30 строк вместо 1200-строчного CLAUDE.md. Декомпозиция задач вместо «ONLY/DO NOT». Спецификации вместо «спроси, если непонятно». Книга боли с паттернами вместо списка правил.
Не всё решено до конца. Но вектор стал понятен: чем меньше ты полагаешься на то, что агент «сам разберётся» - тем лучше результат.
Формула, которая работает
Год назад я писал: «джун × AI = мидл». Сейчас бы сформулировал чуть иначе:
«джун × AI × инженерные ограничения = мидл. Без ограничений джун × AI = хаос».
Ограничения - это не CLAUDE.md. Это тесты, CI-гейты, пермишены, спецификации, декомпозиция задач. Всё, что не зависит от настроения модели.
Антон сейчас не джун. Он мидл, который половину времени пишет код сам, а половину рулит агентами. Зарплата у него выросла, и она оправдывает себя, потому что без него агенты создают проблемы быстрее, чем решают.
А как у вас? У кого после года работы с агентами есть решения, до которых мы не дошли? Особенно интересно про обучение на ошибках - мы с книгой боли справляемся, но чувствую, что это костыль. Если у кого-то есть подход лучше - расскажите.