Надоело не понимать, что происходит внутри вайбкод-проектов

Как я отдал агенту четыре репозитория и увидел то, что в коде не видно в принципе.
Хайп AI-кодинга не обошёл никого. Если ты не используешь AI-инструменты в работе и в жизни — твои навыки устаревают с каждой неделей и с каждым выходом новой модели. А заодно этот хайп заполонил интернет толпами SaaS-решений, под капот которых страшно заглядывать.
И дело тут не в низкой квалификации тех, кто эти проекты делает — технический бэкграунд у ребят часто более чем приличный. Дело в скорости: темп релизов и решений тянет за собой тонны недодуманного, потому что в этой гонке надо успеть откусить свой кусок пирога.
Концепция при этом не меняется: сначала по-быстрому слепить MVP из того, что есть, зарелизить, получить обратную связь. Пройти самый важный этап — от пустоты до чего-то осязаемого — как можно быстрее. А вот если проект заработает, тогда уже и переписывать под все потребности: на нужные технологии, с нужными подходами и паттернами.
Да закидают меня палками солюшн-архитекторы :)
И кто же будет всё это переписывать? У кого будет контекст огромного навайбкоженного проекта? Люди, конечно. Которые тоже будут использовать AI — но уже с пониманием контекста и существующих проблем.
Начнётся реверс-инжиниринг всего навайбкоженного: документирование, описание потоков данных, куча разных диаграмм — чтобы спроектировать всё так, как нужно.
И чем понятнее эти диаграммы, композиция и структура, тем проще и быстрее переписать всё на нужные рельсы.
Представим: есть у нас навайбкоженный за пару часов SaaS, который превращает подкасты и видео в наборы клипов для соцсетей.
Сделали, зарелизили — и проект действительно залетел. Поперли первые пользователи, начался хайп. И тут же начинается другое: гора багов, обращения пользователей, проблемы с утилизацией ресурсов, у людей всё отваливается. Мы кидаемся чинить баги агентами — появляются новые баги. И так по кругу.
И контекста всей системы не хватает ни агентам, ни нам — техническим специалистам, которые этими агентами управляют.
Дальше я проверил это на живом проекте: собрал такой SaaS из четырёх репозиториев, отдал агенту восстановить архитектуру, а потом переписал ядро с Node на Java по всем правилам — со слоями, типами, JPA и DTO. Спойлер: кода стало в разы больше и он стал объективно лучше, а все пять архитектурных проблем остались на месте. Одна из них при переписывании даже закрепилась в коде явно. Увидеть это получилось только на диаграмме.
Подопытный: ClipCast
Чтобы не махать руками в воздухе, я собрал такой проект по-настоящему. Знакомьтесь — ClipCast: SaaS, который принимает подкаст или видео и нарезает из него клипы для соцсетей.
Четыре отдельных репозитория, ровно так, как это обычно и выглядит:
clipcast-web- Веб-студия: логин, воркспейсы, проекты, клипы, комментарии. React + TypeScript (Vite)clipcast-api- Ядро: авторизация, воркспейсы, проекты, загрузка медиа, API-токены. Java 21 + Spring Bootclipcast-transcriber- Воркер: медиа → транскрипт. Pythonclipcast-clipper- Воркер: транскрипт → клипы, вызов внешнего AI. Node.js
Плюс Postgres и Redis, всё поднимается одной командой:
docker compose up --build
docker-compose.yml.Открой любой из четырёх репозиториев по отдельности — и всё выглядит нормально.
Открываешь
clipcast-api— отличный Spring Boot, всё по канону.Открываешь
clipcast-transcriber— маленький аккуратный Python-воркер на 50 строк.Открываешь
clipcast-clipper— такой же маленький Node-воркер.Открываешь
clipcast-web— типизированный React.
А вот вопросы, на которые ни один из этих репозиториев не отвечает:
Кто вообще пишет в таблицу
clips? (Спойлер: не то, что вы думаете.)Сколько сервисов держат подключение к одной и той же базе?
Что произойдёт, если поменять схему
transcripts?Какие эндпоинты api не защищены авторизацией?
Какие эндпоинты вообще никто не вызывает?
Держать это в голове на четырёх репозиториях ещё можно. На двенадцати — уже нет. А агенту, который чинит очередной баг, этот контекст не достаётся вообще: он видит один репозиторий и свой промпт.
Дальше — ровно тот эксперимент, ради которого всё затевалось.
Шаг 1. Получаем токен в Viaduct
Viaduct — это полностью бесплатный инструмент, в котором я держу архитектуру: C4-модель (системы → контейнеры → компоненты), HTTP-контракты, брокерские каналы, ER-схемы, PlantUML-последовательности и Magic flows (проигрываемые потоки данных через всю систему).
Ключевое для этой статьи: у него есть MCP-сервер. То есть агент может не просто «посмотреть картинку», а читать и писать модель инструментами.
Создаём API-токен:

Создаем токен и далее копируем конфиг для агента с ним и просим агента настроить себе MCP коннект.
Шаг 2. Подключаем MCP-сервер к агенту
Я работаю в Claude Code, поэтому команда такая:
claude mcp add --transport http viaduct https://c4.quietgridlabs.com/api/mcp \
--header "Authorization: Bearer $VIADUCT_TOKEN"Проверяем, что агент действительно достучался — самый простой вызов:
c4_whoamiЕсли в ответ приходит твой пользователь — всё, агент подключён к архитектуре.


Далее выполняем:
claude mcp list

Полный набор инструментов, который получает агент, — это примерно то, чем пользуется живой архитектор:
чтение:
c4_project_context,c4_search,c4_get_element,c4_list_docs,c4_list_technologiesзапись модели:
c4_create_element,c4_update_element,c4_upsert_connectionдокументация и потоки:
c4_upsert_doc,c4_upsert_sequence,c4_upsert_data_flow
Отдельно отмечу мелочь, которая оказалась важной: у Viaduct есть скилл (viaduct-architect) — набор правил, как именно моделировать. Что эндпоинт — это kind=endpoint с методом и контрактом, а топик — это kind=channel под брокером, а не «ещё один эндпоинт». Что связи бывают только между элементами одного уровня C4. Что technology — это id из каталога, а не «Redis» строкой.
Без этих правил агент рисует кашу из «Сервис А общается с Сервисом Б». С ними — получается модель, которую не стыдно показать команде.
Шаг 3. Просим агента задокументировать проект
Дальше самое интересное. Промпт, по сути, один:
Просканируй код в ~/clipcast-demo (4 репозитория: clipcast-web, clipcast-api,
clipcast-transcriber, clipcast-clipper) и задокументируй архитектуру в Viaduct:
создай системы под каждый сервис, эндпоинты, брокерские каналы, связи между сервисами — включая скрытые.
Отметь скрытую связность отдельно, она должна быть заметна на диаграмме.И агент уходит работать: читает pom.xml и контроллеры, worker.py и worker.js, schema.sql, docker-compose.yml, package.json — и параллельно выкладывает это в модель.


Ждем пока агент все создаст в проекте.
Спустя 12 минут агент полностью задокументировал все репозитории.

Что получилось
В Viaduct появилось:
1 Актор - Пользователь студии
5 Систем, 1 из которых внешняя OpenAI API
16 эндпоинтов на api — с методами, путями, телами запросов и всеми статусами ответов, а не только счастливым
2 брокерских канала под Redis:
media.uploadedиtranscript.ready— со схемами сообщений9 таблиц в Postgres с колонками и типами
документация на систему и на каждый значимый контейнер
PlantUML-диаграмма последовательности для основного сценария
Magic flow «Upload → Clips pipeline» из 9 шагов — весь путь файла от загрузки до готового клипа




А теперь то, ради чего всё затевалось
Когда модель собралась, на диаграмме стало видно то, что в коде размазано по четырём репозиториям.
1. В базу пишут три сервиса, а не один
clipcast-api — вроде бы единственная точка входа к данным. Но clipcast-transcriber держит свой psycopg2-коннект к той же базе и делает INSERT INTO transcripts. А clipcast-clipper держит свой pg-пул и делает INSERT INTO clips.
В коде это два неприметных файла db.py и db.js по пять строк каждый. На диаграмме — три стрелки, сходящиеся в одну Postgres, и две из них подписаны «напрямую, в обход api».
Последствие, которое из кода не видно вообще: любая миграция схемы в Java-сервисе тихо ломает два других сервиса на других языках. Hibernate с ddl-auto: update при этом радостно поменяет схему сам.
2. Пайплайн наполовину на событиях, наполовину на HTTP
Вся цепочка построена на Redis pub/sub: media.uploaded → транскрипт → transcript.ready → клипы. А вот финализацию clipper отправляет прямым HTTP-вызовом POST /internal/clips/ready.
Когда-то это был быстрый фикс. В коде clipper'а это одна строчка fetch. На диаграмме это отдельная стрелка, которая ломает симметрию всего остального потока, — и её сразу хочется убрать.
3. Внутренний вебхук без авторизации
/internal/clips/ready не проверяет вообще ничего: ни авторизацию, ни то, что projectId принадлежит вызывающему. Любой, кто дотянется до порта, может пометить чужой проект как готовый.
4. Мёртвый код, который никто не решается удалить
GET /api/legacy/ping — старый health-check. Вызывающего кода нет ни в одном из четырёх репозиториев. Агент это пометил тегом dead-code.
5. Захардкоженный адрес API во фронте
const API_BASE = 'http://localhost:4000' — без переменных окружения.
Главная мысль
Ни один из пяти пунктов не является «плохим кодом». Каждый по отдельности — разумный компромисс, принятый в момент, когда надо было успеть. Проблема в том, что все вместе они существуют только между репозиториями, и увидеть их можно только на карте всей системы.

Что это даёт на практике
Теперь у меня есть карта системы, и она не в голове у одного человека.
Для меня как для технического специалиста: я вижу, за какие ниточки дёргать. Не «надо бы отрефакторить», а конкретно: убрать два прямых коннекта к базе, закрыть
/internal/*, заменить HTTP-уведомление на событие. Приоритеты стали видны.Для агентов: это тот самый недостающий контекст. Когда я даю агенту задачу «добавь эндпоинт для скачивания клипа», он может сначала прочитать модель и узнать, что таблицу
clipsпишет вообще другой сервис на другом языке. Без этого он бы просто дописалINSERTв Java-сервис и создал третьего писателя в ту же таблицу.
- Для новых людей в проекте: онбординг — это открыть диаграмму и проиграть Magic flow, а не читать четыре репозитория подряд.
___
Совет по промптам, который реально влияет на результат: не пишите «задокументируй проект». Просите документировать конкретные вещи — эндпоинты с контрактами, каналы, связи с БД — и отдельно просите подсветить то, что выглядит подозрительно. Разница между «нарисовал коробочки» и «нашёл три стрелки в одну базу» — ровно в этой фразе промпта.
___
Экстраординарные времена требуют экстраординарных решений. Вайбкодить дальше мы не перестанем — и не надо. Но если генерировать код в десять раз быстрее, чем раньше, то и карту этого кода придётся обновлять в десять раз быстрее. Руками так уже не получится.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.