Автономный AI-кодинг: что показали 10 недель в проде
За 4 недели автономный пайплайн закрыл 133 задачи в моём репозитории. 88% — с первой попытки, медиана от старта работы до мёрджа — 17 минут. Я не писал этот код и не делал ревью.
Это не демо и не маркетинг. Это рабочий pipeline, который крутится 24/7 и каждый день мёрджит код в ветку, в которую я сам коммичу. Статья — про архитектурные принципы, которые делают это надёжным, и про метрики, которые это доказывают. Названия конкретных продуктов я убрал — принципы универсальны.
Почему автономный кодинг обычно ломается
Идея старая: AI-агент берёт задачу из трекера, пишет код, прогоняет тесты, пушит ветку, создаёт pull request. Человек вне цикла. Реализаций десятки, но почти все спотыкаются об одно из трёх:
- Агент генерирует нерабочий код. Модель уверенно пишет то, что выглядит правильно, но не компилируется, не проходит тесты или ломает соседние модули. Без проверки — мусор льётся в main.
- Pipeline нестабилен. Параллельные воркеры конфликтуют, сессии падают, git worktrees ломают сборку. Один стабильный прогон на десять попыток.
- Человек всё равно в цикле. «Автономный» пайплайн создаёт PR, но человек обязан его провьюить — потому что нет доверия к качеству. Это не автономность, это автокомплит с лишними шагами.
Я столкнулся со всеми тремя. После нескольких итераций система заработала на метриках, которые я раньше считал недостижимыми для AI-генерации. Ниже — что именно починило каждое.
Принцип 1: Архитектура важнее промптов
Главный сдвиг: 90% надёжности даёт pipeline вокруг агента, а не сам промпт.
Все ищут «тот самый промпт» — правильную метафору, few-shot пример, тон голоса. Это даёт 5-10% прироста. Остальное — структура: кто что делает, где проверяется, что происходит при ошибке.
Мой pipeline выглядит так:
идея → AI-аналитик: интервью → спецификация → декомпозиция на задачи ↓задача в трекере (метка "ready") ← я ставлю метку после проверки ↓оркестратор: взять задачу → создать ветку → запустить сессию AI-агента ↓агент: пишет код → коммитит ↓детерминированный гейт: линтер + тесты + сборка ↓ зелёный ↓ красныйPR создан → CI green ошибки → обратно в ту же сессию→ авто-мёрдж (без человека) ↓ повтор (макс 5) → паузаВажный нюанс: задачи в трекер тоже пишет AI, а не я руками. Специализированный AI-аналитик проводит интервью, оформляет спецификацию и декомпозирует её на задачи с acceptance criteria, file maps, edge cases и зависимостями (методология SDD). Моя работа на этом этапе — дать направление, ответить на вопросы и поставить метку ready. Это часы, а не недели.
Каждый блок — точка, где можно сломаться, и каждая закрыта:
- Агент не закоммитил → гейт ловит «нет изменений» → rework.
- Тесты упали → вывод уходит в ту же сессию → агент видит контекст и чинит.
- Сессия умерла (API timeout, OOM) → задача возвращается в очередь → новая сессия.
- Агент зациклился (одинаковые ошибки подряд) → после двух одинаковых fingerprint → пауза.
Самое яркое доказательство — то, что я называю «Do Nothing Paradox». За 10 недель эксплуатации я собрал 7 рекомендаций по улучшению промпта агента: «читай файл перед edit», «проверяй существование файла перед write», «оборачивай долгий bash в timeout». Разумные, очевидные, безопасные правки. Ни одна не внедрена. А метрики за тот же период улучшились с 29% до 75% CI success rate.
Вывод: архитектура — линейный pipeline + deterministic gate + retry loop — вот что починило систему, а не патчи промпта. Когда фундамент работает, точечные улучшения промпта — оптимизация длинного хвоста. Риск внести регрессию в работающую систему выше, чем потенциальный выигрыш. Burden of proof is on the change, not on the status quo.
Принцип 2: Не доверяй AI проверять AI
Детерминированный гейт надёжнее AI-ревью. Нельзя просить модель оценить код другой модели — это замкнутая петля.
В ранней версии системы у меня был AI-review: отдельный агент читал PR и выносил вердикт «accept / request changes». Звучит логично — AI написал, AI и проверил. На практике это дало два эффекта:
- Ложноположительные: ревьюер одобрял код, который не компилировался.
- Ложноотрицательные: ревьюер отклонял рабочий код из-за стилистических предпочтений.
Обе ошибки проистекают из одного: модель не может надёжно оценить корректность кода по тексту. Она видит «правдоподобный» код и не отличает его от «правильного». Тесты и компилятор — отличают всегда.
Поэтому я заменил AI-review на детерминированный гейт:
Гейт прогоняет последовательно — все шаги blocking:1. Линтер (статический анализ + стиль)2. Статическая проверка типов и синтаксиса (go vet / tsc)3. Сборка всех затронутых пакетов4. Юнит-тесты с проверкой покрытия5. Спецпроверки (схемы БД, shell-скрипты, прото-файлы)Каждый шаг либо проходит, либо падает — без интерпретации. Гейт прогоняется на HEAD-коммите (не на рабочем каталоге), так что проверяется ровно то, что уйдёт в PR. Если что-то красное — ошибка с полным выводом уходит в ту же сессию агента, который только что писал код. Контекст сохранён, агент чинит не вслепую.
Тесты — обязательная часть кода, не опция. Агент пишет тесты вместе с реализацией. Гейт проверяет не только «тесты проходят», но и «coverage не упал ниже порога». Если агент добавил 100 строк кода без единой строки тестов — порог пробивается → rework. На новом проекте все проверки blocking с первого дня, включая стиль: это дешевле, чем разгребать накопленный долг потом.
Результат: за 4 недели стабильной работы только 7 из 133 мёрджей содержали code-quality failures на CI. Это 5% failure rate — детерминированный гейт ловит то, что важно, стабильно.
Принцип 3: Один процесс лучше параллелизма
Single-process, одна задача за раз оказался надёжнее и быстрее в долгую, чем параллельные воркеры.
Это контринтуитивно. Параллелизм = больше throughput, разве нет? В теории — да. На практике параллельные AI-агенты в одном репозитории создают каскад проблем:
| Проблема | Что происходило |
|---|---|
| Git worktree ломает сборку | workspace-файлы с относительными путями не работают в worktree → сборка падает |
| Конкуренция за зависимости | символические линки в каждый worktree → race condition при установке пакетов |
| Отмена CI-прогонов | каждый пуш отменяет чужой CI → cascade → waste до 60% compute |
| Конфликты изменений | два агента правят один файл → merge conflict → rework обоих |
В предыдущей версии я пробовал параллелизм: worker pool, изоляция через git worktrees, несколько одновременных задач. За неделю использования — ни одного стабильного production-прогона. Cancel cascade сжёг 60% CI-времени за неделю, квота исчерпалась, CI встал полностью.
В финальной версии я выбрал single-process: одна задача → один агент → одна ветка → одна сессия. Очередь обрабатывается строго последовательно. Звучит медленно, но:
- Cancel cascade исчез — нет параллельных пушей, нечего отменять. Waste с 60% упал до ~15%.
- Throughput оказался выше — нет overhead на изоляцию, cleanup, разрешение конфликтов.
- Проще дебажить — один лог, одна сессия, одна причина если что-то сломалось.
Параллелизм имеет смысл для распределённых команд из 10+ разработчиков. Для одного репозитория с одним мейнтейнером — sequential processing выигрывает по всем метрикам, включая скорость.
Из чего собрать такой pipeline
Принципы — это хорошо, но что конкретно нужно? Pipeline состоит из пяти компонентов. Первые два — готовые продукты, которые вы выбираете. Третий и четвёртый — ваш код. Пятый — отдельная конфигурация AI-агента.
Пять компонентов
| Компонент | Зачем | Критичные требования |
|---|---|---|
| Трекер задач | Хранит backlog, зависимости, PR | REST API: issues, labels, comments, PR, связи blocked_by между задачами |
| AI-агент кодинга | Пишет код, коммитит, пушит, создаёт PR | HTTP API для программного управления; инструменты read/write/bash/git; разрешение на push и создание PR |
| Оркестратор | Связывает всё: поллинг → git → сессия → гейт → PR | State machine, ~3000-5000 строк на любом языке (у меня Go) |
| Детерминированный гейт | Линт + тесты + сборка | Запускается на HEAD-коммите, диспетчеризация по расширениям файлов |
| AI-аналитик | Upstream: интервью → спецификация → декомпозиция на задачи | SDD-методология, отдельный промпт/агент — подробнее тут |
Контракты между компонентами
Трекер ←──REST──→ Оркестратор ──HTTP──→ AI-агент кодинга ↓ bash ↓ bash Git ←──────────────────┘ ↓ Гейт (bash: lint + test + build)- Трекер ↔ Оркестратор: REST API. Оркестратор опрашивает трекер каждые 30 секунд, забирает задачи с меткой
ready, уважает связиblocked_byмежду задачами (задача не берётся, пока не закрыты её блокеры — критично для фич из нескольких задач), закрывает задачу после мёрджа PR. - Оркестратор ↔ AI-агент: HTTP API агента. Создать сессию → отправить команду
work-on-task <slug>→ поллить статус каждые 2 секунды → при ошибке гейта отправить вывод обратно в ту же сессию (контекст сохранён). - Оркестратор ↔ Git: shell-команды. Создать ветку
ai/<slug>, checkout, pull —rebase, определить изменённые файлы черезgit diff --name-only main...HEAD. - AI-агент ↔ Git: shell-команды. Коммит в conventional-формате (
feat(scope): description), push в ветку задачи, создание PR через REST API трекера.
Критичное разрешение. Большинство AI-агентов кодинга по умолчанию запрещают git push и создание PR — «для безопасности». Вам нужно явно разрешить push в ветки ai/* и запретить в main. Без этого агент не сможет завершить цикл, и оркестратору придётся делать push за него — это лишний код и точка отказа.
Наблюдаемость через комментарии. Каждый переход состояния — взятие задачи, создание ветки, старт сессии, результат гейта, rework, создание PR — сопровождается комментарием в issue. Вся хронология видна в трекере, без доступа к логам демона. Это критично для доверия: открываете задачу и видите, что произошло, когда и почему. Гейт упал — комментарий содержит полный вывод ошибок. Сессия зависла — комментарий отмечает таймаут. Rework — номер попытки и причина. Без этого pipeline — чёрный ящик, в который страшно заглядывать.
Авто-мёрдж — что делает pipeline автономным. Когда CI на PR зелёный, оркестратор мёрджит через REST API трекера (squash merge). Между зелёным CI и мёрджем нет шага «человек нажал кнопку». Это и есть определение автономности: задача от спеки до кода в main — без единого ручного действия. Если CI красный — rework. Если CI красный 5 раз подряд — пауза, человек разбирается.
Lifecycle сессии и crash recovery. Сессия агента поллится каждые 2 секунды. Статусы: running → completed (агент закончил, гейт запускается) или error/timeout. Таймаут — 60 минут бездействия: если за это время не было новых сообщений, сессия убивается, задача возвращается в очередь. Состояние оркестратор хранит в памяти — при рестарте (краш, deploy) все in_progress задачи сбрасываются в ready и подхватываются заново. Ветвь уже существует, код на месте — продолжение без потери работы.
Гейт: главная деталь
Если вы сделаете правильно только одну вещь из статьи — сделайте гейт. Это единственный компонент, который нельзя заменить готовым решением.
1. Проверить: всё ли закоммичено (git status --porcelain) Нет → rework: «есть незакоммиченные изменения»2. git diff --name-only main...HEAD → какие файлы изменились3. По расширениям — диспетчим проверки: .go → golangci-lint, go vet, go build, go test -cover .ts → eslint, tsc --noEmit, vitest run --coverage .sql → проверки схем БД4. Все шаги — blocking: fail на любом → rework5. Coverage не должен упасть: новый код без тестов → порог пробит → rework6. Flaky rerun: до 3 попыток, любая green = шаг пройденГейт прогоняется на HEAD-коммите, не на рабочем каталоге. Сначала убеждаемся, что всё закоммичено, потом — что закоммиченное работает. Это гарантирует: то, что проверяет гейт = то, что уйдёт в PR. Никаких сюрпризов на CI.
Coverage должен расти, не падать. Порог покрытия — это не «минимум 50%», а защита от регрессии. Если до коммита агента coverage был 70%, а после — 68%, гейт должен это поймать. Новый код без тестов = красный гейт = rework. Это заставляет агента писать testable код сразу, а не откладывать «потом допишу тесты». Для контроля: сравнивайте coverage до и после (на main vs на HEAD), а не только абсолютное значение.
Гейт vs CI — в чём разница. Гейт запускается локально на HEAD перед созданием PR. CI запускается в чистом окружении после создания PR. Оба прогоняют линтер + тесты + сборку, но CI ловит то, что локальный гейт не может: отсутствующие зависимости, окружение-специфичные падения, интеграцию с сервисами, недоступными локально. Остаточные 5% CI-фейлов — это этот зазор.
Кастомные линтеры: архитектуру стандартными не проверить
Стандартные линтеры ловят синтаксис и стиль. Архитектуру — нет. golangci-lint найдёт неиспользуемую переменную, но не заметит, что сервис импортирует чужую библиотеку в обход ограничений, что интерфейс назван с префиксом I, или что репозиторий пишет сырой SQL вместо хранимой процедуры. Для человека эти нарушения очевидны. Для AI-агента — нет: он видит «работающий код» и не понимает, что нарушил принцип.
У меня 14 кастомных правил для Go и 5 для SQL. Ключевые из Go-набора:
| Правило | Что проверяет | Зачем нужно |
|---|---|---|
| Service boundaries | сервисы импортируют только stdlib + свои библиотеки | предотвращает спагетти-зависимости между сервисами |
| Context propagation | каждая функция с error вызывает сегментирование контекста (StartSegment + Complete) | трассируемость — каждый шаг логируется |
| No global state | запрет init() и package-level mutable vars | никаких скрытых сайд-эффектов |
| Interface naming | без I-префикса (Client, не IClient) | единый стиль API |
| Getter naming | без Get-префикса на геттерах без аргументов (ID(), не GetID()) | единый стиль API |
| Package naming | запрет util, common, helpers, base, misc | принуждает к осмысленной декомпозиции |
| No raw SQL в репозиториях | вся работа с БД — через хранимые процедуры | безопасность + консистентность |
SQL-чекер добавляет: запрет динамического SQL, проверка нейминга функций, требование get_v0 + get_batch_v0 для каждой таблицы.
Эти линтеры — часть гейта. Нарушение архитектуры = красный гейт = rework. Без них агент за неделю создаст код, который «работает», но не поддерживается — типичная спагетти-ситуация, только быстрее.
Навыки + линтеры: двухуровневый контроль
Линтеры — детективный слой: ловят нарушения после факта. Но лучше предотвращать до. Для этого AI-агент загружает файлы навыков (SKILL.md) с описанием конвенций — naming, структура пакетов, паттерны проектирования — до того, как начнёт писать код.
- Навык объясняет «как надо» (preventive): «интерфейсы определяются в consumer-пакете, не в implementation», «ошибки оборачиваются через
fmt.Errorf("pkg: op: %w", err)», «конфиг через functional options». - Линтер проверяет «как сделано» (detective): если правило нарушено — гейт красный.
Навыки снижают количество нарушений на входе — агент реже ошибается, потому что знает правила. Линтеры ловят остаток. Одно без другого работает хуже: только линтеры — агент бьётся об одни и те же правила в цикле rework; только навыки — иногда игнорируются, и нарушение уходит в прод.
Метрики: 10 недель в проде
Абстрактные принципы — это хорошо, но числа честнее. Ниже — реальные метрики за 10 недель (апрель–июнь 2026), собранные через API трекера задач и CI-системы. Период покрывает две архитектуры: раннюю (нестабильную) и финальную (single-process + deterministic gate).
Headline метрики
| Метрика | Значение |
|---|---|
| Период наблюдения | 10 недель |
| Всего PR от автономного пайплайна | 166 (из них ~147 в финальной архитектуре, rest — ранняя) |
| Merge rate (финальная архитектура) | 90% |
| First-try success | 88% (130 из 147 задач — 1 PR → merged) |
| Медиана время до мёрджа | 17 минут |
| P90 время до мёрджа | ~10 часов |
| Закрыто задач за 4 недели | 133 |
| Throughput | 4.4 мёрджа в день |
| Code-failure rate на CI | 5% (7 из 133) |
Разрыв между медианой (17 минут) и P90 (~10 часов) — 35×. Это бимодальное распределение: большинство задач пролетают за минуты, но длинный хвост (сложная кодогенерация, интеграционные тесты) тянет P90 на часы. Это не баг — это отражение сложности задач.
Для контекста — ручные PR за тот же период: 206 штук, merge rate 50%. Но это apples-to-oranges: ручные PR включают эксперименты, WIP, исследовательские ветки, которые пайплайн никогда бы не попытался. Сравнение не в том, что «AI стабильнее человека», а в том, что для хорошо специфицированных рутинных задач пайплайн надёжен.
Динамика по неделям
| Фаза | Недели | CI success | Merge rate | Что происходило |
|---|---|---|---|---|
| Phase 0: до архитектуры | 16-21 | 29-86% | 27-85% | Ручная разработка + ранняя архитектура с параллельными воркерами. Cancel cascade, квота, нестабильность |
| Phase 1: переход | 22 | 43% | 27% | Первые PR новой архитектуры, миграция |
| Phase 2: финал в проде | 23-26 | 75% | 91% | Стабильный autonomous pipeline, 4.4 PR/день |
Архитектурный сдвиг виден на CI success rate как разрыв: с 29% до 75% за одну неделю. Это не постепенная оптимизация — это смена фундамента. Все 7 точечных улучшений промпта, предложенных за этот период, не внедрены. Метрики выросли на одной архитектуре.
Где AI всё-таки ошибается
Не всё идеально. Из 147 уникальных задач за 4 недели:
- 130 (88%) — решены с 1 PR, мёрдж с первой попытки.
- 3 (2%) — потребовали rework (2-8 попыток), но в итоге мёрджнулись.
- 9 (6%) — 1 PR, но дискарднут (агент не справился, PR отброшен).
- 5 (3%) — rework исчерпан (5 попыток), задача поставлена на паузу.
Итого: 133 мёрджнуты (90%), 14 отброшены (10%). Полная сверка: 147 попытано → 133 закрыто + 14 discarded.
Rework концентрируется в двух категориях: сложная кодогенерация (генерация указателей, линтеры) и кросс-сервисные интеграционные тесты. Это «длинный хвост» сложности — не системная проблема, а закономерное ограничение текущих моделей на задачах с большой контекстной нагрузкой.
Максимум — одна задача потребовала 8 попыток за 29 часов (аннотации для кодогенерации указателей). Это boundary case, не норма. Остальные rework-задачи уложились в 2-3 попытки.
Где человек всё ещё нужен
Автономность — не всесильность. Человек нужен в трёх местах, и заменить их пока нельзя.
1. Направление и валидация. У меня есть идея — «нужна фича X» или «починить проблему Y». Дальше включается AI-системный аналитик: проводит интервью, пишет спецификацию, декомпозирует её на задачи с acceptance criteria, file maps, edge cases и формализованными зависимостями (blocked_by). Я не пишу спеки руками — моя работа на этом этапе ответить на вопросы аналитика и поставить метку ready после проверки. Без этого шага системе нечего делать. Но это часы работы, не недели. Подробнее о том, как устроен AI-аналитик — в статье про проектирование через спецификацию.
2. Длинный хвост. 6% задач, требующих rework, часто заканчиваются паузой после 5 попыток. Это сигнал: либо задача плохо описана, либо она слишком сложна для текущей модели. Я читаю gate-вывод, дописываю контекст в спеку, перезапускаю. Десять минут моего времени — и задача уходит в работу.
3. Контроль направления. Пайплайн делает то, что ему дали. Он не решает, нужна ли эта фича, какой должен быть архитектурный подход, стоит ли переписать модуль. Это работа человека — стратегия, приоритеты, дизайн системы.
Чего человеку делать не нужно — так это писать рутинный код, гонять тесты, чинить мелкие баги, создавать PR, мёрджить ревёрты. Эти 80% времени разработчика теперь делает пайплайн, пока я занимаюсь тем, что машина делать не умеет.
Вывод
Автономный AI-кодинг — это не фантастика и не «через 5 лет». Это рабочий production в 2026. Не у всех, не для всех задач — но для хорошо специфицированной рутинной разработки уже сейчас.
Три принципа, которые сделали это рабочим:
- Архитектура важнее промптов — pipeline, retry, deterministic gate дают 90% надёжности. Промпт — последние 10%.
- Не доверяй AI проверять AI — детерминированные тесты и сборка надёжнее AI-ревью. Компилятор не имеет мнений.
- Один процесс лучше параллелизма — простота и стабильность важнее иллюзии throughput. Один агент, одна ветка, одна задача.
Метрики говорят сами: 90% merge rate, 17 минут медиана, 133 задачи за месяц — без единой строчки ручного код-ревью с моей стороны.
Если вы сейчас строите или оцениваете автономный AI-кодинг — проверьте свою систему против этих трёх принципов. Чаще всего узкое место не в модели и не в промпте. Оно в pipeline вокруг неё.
FAQ
Сколько стоит запуск такого пайплайна в месяц?
Основная статья расходов — токены LLM. У меня благодаря кешированию контекста (cache hit rate 97%) стоимость оказалась близка к нулю на free-тарифе провайдера. Без кеширования — считайте по формуле: средний контекст на задачу × количество задач × цена за токен. Для моих объёмов (200K input tokens/сессия, 4 задачи/день) это единицы долларов в день на платном тарифе.
Какие задачи подходят для автономного кодинга, а какие — нет?
Хорошо идут: изолированные фичи с чёткими acceptance criteria (CRUD, эндпоинты, тесты, рефакторинг модуля, багфиксы с репро). Плохо идут: задачи, требующие архитектурных решений (дизайн новой системы), кросс-командные изменения, задачи с размытыми требованиями («сделай хорошо»). Простое правило: если вы можете написать спеку, по которой другой разработчик сделает задачу без вопросов — агент тоже сделает.
Нужно ли отдельное железо для оркестратора?
Нет. Мой оркестратор — это один Go-бинарник, который крутится на той же VM, где живёт AI-агент. Потребление ресурсов минимальное: основная нагрузка — это HTTP-поллинг трекера и запуск git-команд. Вся тяжёлая работа (генерация кода) — на стороне LLM-провайдера.
Что делать, если агент застрял на задаче?
Пайплайн сам ставит паузу после 5 неудачных попыток и пишет комментарий с причиной. Я читаю gate-вывод (какие тесты упали, какой шаг красный), уточняю спеку — обычно добавляю конкретики в edge cases или file map — и перезапускаю. Как правило, вторая итерация проходит с первого раза. Если нет — задача слишком сложна для текущего подхода, и её надо декомпозировать.
Можно ли это повторить без команды инженеров?
Да, я делал это соло. В секции «Из чего собрать такой pipeline» перечислены пять компонентов и контракты между ними. Из них два — готовые продукты (трекер и AI-агент), которые вы выбираете под свои предпочтения. Оркестратор и гейт — ваш код (~3000-5000 строк), но это state machine с предсказуемым поведением, а не research project. AI-аналитик — отдельный промпт. Основная сложность не в коде, а в дисциплине: настроить deterministic gate правильно (advisory vs blocking — критично), не поддаваться желанию «помочь» агенту руками в процессе, и писать спецификации качества на входе.