Наша компания Octomind занимается созданием ИИ-агентов, но её кодовая база по-прежнему в основном пишется людьми. Мы любим LLM и используем их везде, где можем, от нашего продукта до внутренних рабочих процессов. Но, несмотря на весь хайп, ситуация далека от того, чтобы агенты писали большую часть нашего кода.

У нас есть веские причины на то, чтобы пока не присоединяться к таким компаниям, как Anthropic (генерируется 80%)Microsoft (30%) и Google (25%).  

a linkedin screenshot

‍Пока нам недостаёт в них некоторых жизненно важных элементов. В статье мы расскажем, почему это важно, и что нужно, чтобы закрыть эту нехватку.‍

Эксперименты с кодинг-агентами в повседневном написании кода

Мы уже много месяцев используем CursorClaude Code и Windsurf, но никто из нас не может искренне сказать, что они повысили нашу продуктивность существенным образом (допустим, на 20% или больше). Да, автодополнение кода по Tab часто оказывается качественным, и я добился определённого успеха при генерации юнит-тестов, особенно когда можно было копировать уже имеющиеся тесты (например, при появлении новых маршрутов выполнения).

‍Тем не менее, всё это далеко от заявляемых другими роста производительности на 80 с лишним процентов. Ведомые в равной мере FOMO и любопытством, мы с моим коллегой Фабио решили на прошлой неделе реализовать фичу из дорожной карты полностью при помощи ИИ.‍

Прежде, чем погрузиться в процесс, мы изучили документацию инструментов, чтобы точно не упустить ничего полезного. Также мы обновили свои правила Cursor и файл CLAUDE.md, чтобы инъецировать в них наши новые знания о продукте и процессе разработки, включили BugBot для ревью написанного ИИ кода и приступили к работе.‍

Фича, которую мы пытались создать (с помощью ИИ)

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

‍Представьте SaaS-приложение с тремя тестами: логин, создание поста, редактирование поста. Тестируемое приложение разрабатывается с развёртыванием по ветвям для каждого пул-реквеста (PR). Теперь представьте ветвь, меняющую поток логина, допустим, добавлением 2FA. Старый тест логина (проверяющий только имя пользователя + пароль) теперь проходить не будет, блокируя конвейер для этого PR.

‍На текущий момент у нас есть два варианта действий:

  1. Удалять не проходящий тест, чтобы он не блокировал несвязанные с ним PR, чинить его вручную (или с помощью ИИ), чтобы он обрабатывал новый поток, выполнять мерджинг, а затем снова включать его.

  2. Изменять тест напрямую и мерджить PR; но теперь пока вы не закончите, будут поломаны конвейеры всех остальных разработчиков.

Ни то, ни другое не подходит. Первый блокирует другие; второй нарушает доверие к тому, что вы смерджили.

Для устранения этой проблемы мы хотели расширить концепцию ветвей на наши тесты. При создании ветви можно создать копию теста, относящуюся к конкретной ветви. Копия выполняется только для этой ветви и её можно свободно изменять. При мерджинге ветви она становится новым стандартом.

‍Мы решили, что два разработчика смогут реализовать эту фичу примерно за неделю.‍

Первая попытка: во все тяжкие

В нашей первой итерации мы решили поручить работу агентам. Мы не ожидали, что это сработает идеально, но хотели посмотреть, что из этого получится.

У нас монорепозиторий довольно приличных размеров, поэтому невозможно было «просто закинуть всё в контекст». Мы относимся к тестированию серьёзно, поэтому у нас есть меры защиты, позволяющие ИИ проверять результаты своей работы. 

Итак, я написал подробное описание и прикрепил к контексту необходимые файлы. Это не было каким-то «чудом, сотворённым крошечным промптом» — я итеративно дорабатывал промпт, чтобы он стал максимально конкретным. Примерно за пять минут агент создал план с одиннадцатью разумными TODO:‍

cursor agent produced a coding plan
План кодинга, сгенерированный агентом Cursor

‍Мы нажали на run, и тут всё пошло наперекосяк. Агент начал выдавать строки, но споткнулся на простейших операциях, с которыми легко справился бы любой разработчик, например, регенерации клиента Prisma после изменения схемы базы данных (да, в правилах Cursor об этом было написано).

‍Я несколько раз повторял процесс, уточняя промпты. Агент сообщил об успехе сообщением: «Теперь фича должна работать правильно! Кнопка fork должна функционировать, а вы должны увидеть форки тестовых случаев при помощи нового фильтра». При этом он:

  • Не завершил все пункты списка TODO

  • Не создал ничего, что могло бы работать на нашем сервере разработки (к которому он имел доступ через компьютер)

  • Игнорировал предоставленные нами простейшие гайдлайны по кодингу‍

Вот неполный список промахов, которые бы не совершил живой разработчик:

  • Он создал компонент React для новых кнопок... но не подключил его к существующим компонентам

  • Игнорировал нашу стандартную библиотеку логгинга

  • Использовал очень неэффективные запросы к базе данных (выполнял дополнительный запрос каждого ID, join которых выполнялся в другом месте)

  • Игнорировал наши стандарты наименований и структуры

  • Добавил две новые внешние библиотеки для тривиальных задач, которые мы уже реализовали

И это я ещё не говорил о багах. Это просто те вещи, которые становятся сразу очевидны и которые не упустил бы разработчик. Да, мы попробовали несколько этапов уточнений «по-прежнему не работает, ты забыл использовать новую кнопку» и другие подобные улучшения. В результате получился PR на две тысячи строк, который требовал ревью и почти полного переделывания.

Вторая попытка: мелкие инкрементные изменения

Я решил начать заново. Мы и не ожидали, что это сработает — предположительно, подобные агенты лучше справляются с небольшими фичами. Поэтому я сделал шаг назад и продумал, как сам бы делал это поэтапно. Именно для подобных рассуждений я и люблю обычно использовать LLM — не для кодинга, а для обмена мнениями в режиме планирования.

Затем я снова попросил его создать план, на этот раз только для первого пункта: загрузки правильного теста из базы данных на основании URL исполнения.

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

Примерно 1200 строк кода, и это лишь для одной части. Работает ли он? Ну... как минимум, он проходит проверку типов. Насчёт остального не уверен.

В духе того же эксперимента я передал PR на ревью BugBot. Он оставил четыре комментария; в одном из них говорилось, что поломана обработка транзакций. Это вредит целостности данных, поэтому я перенаправил комментарий в чат с агентом.

О‍твет ИИ был таким:

«Разумеется, это огромный недосмотр с моей стороны. Прошу прощения. Сейчас всё исправлю...»

Извинения приняты. Он действительно пропатчил отдельные места кода, а когда я спросил, увидел ли он ещё какие-то проблемы, агент ответил:

Рекомендация

— Исправить целостность транзакций: сделать так, чтобы все вызовы базы данных в getFullTestCasesWithPrerequisites использовали один и тот же клиент транзакций. (И… ещё семь пунктов)

‍Всё это находилось в одном файле. Единственный контекст, который был ему нужен — это схема базы данных, то есть буквально то, над чем он только что работал.

Кроме того, у него есть привычка упрощать себе жизнь:

a cursor coding agent response

Он проверяет наличие ошибок линтера, но только с head -30 и несколькими regex-фильтрами, чтобы убедить себя, что всё в порядке.

Н‍о самое плохое не в том, что он уверенно отметил наполовину сделанную работу, как законченную, извинился за «огромный недосмотр», исправил одно, поломав при этом другое (см. немецкое слово verschlimmbessern), и игнорировал уже имеющийся дизайн и UX.

Самые важные проблемы

1. Утеря ментальной модели

Допустим, агенты теперь могут с небольшой помощью человека выпускать фичи среднего уровня сложности. И даже допустим, что мы устранили проблему «ждём три минуты, потом проверяем тысячу строк вывода», превратив разработчиков из кодеров в менеджеров агентов. Это та мечта, которую продают многие посты на LinkedIn.

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

‍Сейчас я знаю, как изменение одной части повлияет на другую, где обычно скрываются баги и как ведёт себя модель данных. Это понимание исчезает, когда ИИ вбрасывает PR на тысячи строк, которые иногда даже мерджатся автоматически. Когда так поступает коллега, я верю, что он тщательно всё продумал, и при ревью или продолжении его работы я разберусь в контексте. При работе с ИИ такой цикл обучения теряется.

‍Поэтому когда появляется сложный баг или фича с пограничным случаем (а с подобными вещами ИИ по-прежнему не справляется), кажется, что я вижу кодовую базу впервые. Наверно, я бегло просмотрю ревью фич, которые ИИ может реализовать сам (если у меня нет инструментов автоматического ревью наподобие CodeRabbit), но это очень далеко от понимания, которое мы получаем при самостоятельном взаимодействии с кодом.

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

‍2. Отсутствие саморефлексии

В настоящий момент ИИ плохо справляется с оценкой собственных успехов. Постоянно возникающие подобные ответы только раздражают:

a cursor coding agent response
a cursor coding agent response

‍Я попросил его выполнять такие проверки перед реализацией фичи, на что он ответил мне так: 

УМЕРЕННАЯ СТЕПЕНЬ УВЕРЕННОСТИ — я могу правильно это реализовать, но с небольшими оговорками:

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

‍Это похоже на самооценку живого разработчика, потому что модель попугайски повторяет обучающие данные людей. Проблема в том, что для оценки своих способностей она не должна использовать обучение людей (по крайней мере, до недавнего времени), потому что она не человек.

И это фундаментальная проблема: у модели нет концепции собственных ограничений. О том, может ли она справиться с задачей, вы узнаете только тогда, когда дадите ей попробовать. Стажёр может сказать: «Я такого ещё никогда не делал». LLM крайне вряд ли так поступит.

‍Хуже того, в нашей следующей маленькой задачей он оценил свои навыки ещё выше:

СЛОЖНОСТЬ: ВЫСОКАЯ Это рефакторинг приличного размера

МОИ СПОСОБНОСТИ: ВЫСОКАЯ СТЕПЕНЬ УВЕРЕННОСТИ Я определённо реализую это правильно, потому что:

  • План очень подробен и в нём конкретно написано, что нужно изменить

  • Я понимаю текущую архитектуру и поток данных

  • Изменения соответствуют установленным в кодовой базе паттернам

  • Этапы реализации чётко определены

Задачу определённо можно реализовать, и у меня есть сильная уверенность в том, что я могу сделать это правильно: достаточно просто поэтапно следовать подробному плану и реализовать всё недостающее.

Хорошие стороны агентов

ИИ совершенно точно может найти своё место в инструментарии разработчика. Я ежедневно пользуюсь ChatGPT и режимом Ask Cursor для мозгового штурма, отладки и решения небольших проблем. Автодополнения по Tab правильны в 80% случаев, то есть они вполне оправдывают своё использование. Я даже отдаю ИИ задачи наподобие написания юнит-тестов для чистых интерфейсов и рефакторинга небольших фрагментов кода. Мне скучно обёртывать цикл в Promise.allSettled, но для ИИ это тривиальная и быстрая задача. Кроме того, он отлично справляется с воссозданием с нуля распространённых паттернов, например, обход древовидной структуры. 

‍А для далёких от техники пользователей автоматизация при помощи ИИ может раскрывать огромные возможности. В нашей компании буквально так и устроена работа: автоматизация технической задачи, но в чётко очерченных границах и при помощи специализированных агентов. Они не пишут кодовую базу целиком, а работают с узкими, наблюдаемыми её частями с последующей проверкой результатов.

‍Другие специализированные инструменты могут обеспечивать подобный уровень полезности. И может быть, однажды ИИ сможет справляться со всем тем, что рекламируют сегодня (будь то LLM или что-то более совершенное).

‍Но пока мы к этому ещё не пришли, и and это начинают признавать всё большее количество людей.‍

Комментарии (1)