Я всё меньше пишу первую версию кода сам.

Раньше backend‑задача чаще начиналась для меня с реализации. Сейчас я могу описать её Codex, получить diff и уже от него идти дальше: разбираться в коде, проверять поведение системы, находить недостающий контекст и отдавать задачу на следующую итерацию.

Недавно этот процесс хорошо проявился на интеграции между несколькими сервисами. Codex написал рабочий код, но end‑to‑end задача осталась незакрытой.

Что я отдал Codex

Данные приходили от внешнего источника и сохранялись во внутреннем сервисе. Дальше они должны были пройти через RabbitMQ по цепочке сервисов до конечного потребителя.

В flow использовались Outbox, publisher, consumer и Redis. Из Redis данные забирала другая команда.

Название компании, бизнес‑домен и внутренние имена сервисов я раскрывать не буду. Для этой истории они ничего не меняют.

Я попросил Codex написать publisher, consumer и связанный код для приёма, сохранения и дальнейшей публикации данных. Он подготовил реализацию.

Дальше началась моя часть работы.

Я посмотрел diff и руками прогнал flow. Publisher публикует сообщение в RabbitMQ. Consumer его получает. Данные сохраняются в нужном сервисе.

Всё работает.

На этом месте легко решить, что задача готова. Новый код делает именно то, что от него ожидали на изменённом участке.

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

Я продолжил проверку.

Где разорвалась цепочка

После сохранения данные должны были пройти ещё через один сервис, а затем попасть в другой компонент. Уже он записывал их в Redis для конечного потребителя.

Этого перехода в первой реализации не было.

Получился рабочий кусок системы. Publisher отправлял сообщение, consumer его принимал, сохранение проходило. Только конечного результата не было.

Я вернулся к Codex, объяснил недостающую часть цепочки и попросил переделать решение.

Вот здесь и проходит граница между готовым кодом и готовой задачей. Её легко не заметить, если проверять только изменённый сервис.

Это не история про «AI написал плохой код»

К самому реализованному участку у меня не было претензии: он работал. Codex написал тот кусок, для которого у него был контекст.

Проблема обнаружилась уровнем выше. Локальная реализация не закрывала весь путь данных.

Я и сам мог не учесть этот переход с первой попытки. Разработчики постоянно работают с контекстом, разбросанным между кодом, сервисами и знаниями других людей. AI здесь не создаёт новую проблему.

Зато он меняет момент, в который я с ней сталкиваюсь. Раньше я чаще начинал с того, что писал первую реализацию сам. Теперь могу получить готовый вариант ещё до того, как соберу в голове весь flow.

Поэтому мой рабочий цикл всё чаще выглядит так:

описал задачу → получил первую реализацию → изучил diff → проверил поведение системы → нашёл недостающий контекст → уточнил задачу → получил следующую версию

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

Почему одного review мало

Review хорошо отвечает на вопросы про конкретное изменение. Что добавилось? Как работает publisher? Правильно ли consumer обрабатывает сообщение? Куда сохраняются данные?

Но у интеграционной задачи есть продолжение за границами diff. Кто читает сохранённые данные? Как они попадут в следующий сервис? Где их ждёт конечный потребитель?

В моём случае ответы находились дальше по цепочке. Если бы я остановился на publisher и consumer, локально рабочая реализация так и не довела бы данные до Redis.

Для меня это и есть инженерная часть работы с AI. Не просто принять или отклонить сгенерированный код, а связать его с реальным поведением системы.

Мы делали это и до AI

В одном из прошлых проектов наша команда выделяла логику учёта из legacy‑монолита. Старую и новую реализации несколько недель запускали параллельно.

Мы сравнивали результаты. Каждое расхождение расследовали, после чего добавляли тест и вносили исправление. Только когда накопили достаточно уверенности, переключились на новую реализацию.

AI в этой истории не участвовал. Но принцип тот же: написанный код сам по себе не даёт оснований ему доверять.

В legacy‑миграции таким основанием были результаты parallel run. В недавней задаче я прошёл весь flow до Redis и увидел, что цепочка обрывается раньше.

Способ проверки зависит от задачи. Для небольшого изолированного изменения иногда хватит тестов вокруг одной функции. Для передачи данных между несколькими сервисами проверка одного consumer мало что говорит о конечном результате.

А AI не может проверить себя сам?

Может помогать. Codex можно использовать для написания тестов, поиска связанных участков кода и анализа цепочки вызовов.

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

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

Что меняется в роли разработчика

Я не перестал писать код. Но первую версию всё чаще пишет Codex.

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

Можно назвать это review или оркестрацией агента. Мне ближе старое слово «инженерия». Я всё так же отвечаю за изменение в системе, просто код для первой итерации теперь не обязательно пишу сам.

У меня нет замеров, насколько это удешевило конкретную задачу. Полная стоимость включает постановку, проверку, переделки и доставку, а сопоставимого замера без AI я не делал.

Зато изменение процесса уже видно без процентов.

Если вам близки такие разборы реальных production‑задач, я пишу о них в Telegram‑канале