К содержанию
Владимир Павлунин

Почему Coding Agent мало одного репозитория: 3 прогона — 3 разные цены

Разбор эксперимента: Coding Agent получил задачу и репозиторий и 3 раза написал аккуратный код с зелёными тестами — и каждый раз сам придумал цену, поля API, флаг выкатки и правило возврата. Почему это не ошибка кода и чего агенту не хватает.

· опубликовано

Короткий ответ

Почему Coding Agent, которому дали только задачу и репозиторий, пишет правильный код, но неправильное решение?

Репозиторий показывает, как система устроена, но почти не объясняет, почему, и совсем не содержит решений, которые бизнес принял вне кода: цену, контракт с клиентскими приложениями, правила выкатки, историю инцидентов. Когда этих знаний нет, агент не останавливается — он заполняет пробел правдоподобной догадкой и закрепляет её тестами. В моём эксперименте 3 прогона на одной задаче дали 3 разные цены самовывоза (199, 0 и 150 ₽ вместо 99 ₽), ни в одном не было выключенного флага выкатки и верного правила возврата, при этом все тесты были зелёными. Это не дефект кода и не слабость модели, а отсутствие инженерного контекста.

Главное

  • Coding Agent с одним репозиторием пишет код хорошего уровня: соблюдает слои, повторяет стиль проекта, находит готовую таблицу в миграциях и не ходит в сеть.
  • Бизнес-решения, которых нет в коде, агент придумывает: 3 прогона — 3 цены (199, 0 и 150 ₽), ни одна не совпала с утверждённой 99 ₽ и порогом бесплатной доставки от 3000 ₽.
  • Правила, которые живут в ADR, контракте и разборе инцидента, в условии A не выполнены ни разу: флаг выкатки выключен — 0 из 3, правило возврата верное — 0 из 3, общий лимит 15 кг — 0 из 3.
  • Там, где в коде есть образец, агент сходится; там, где образца нет, он угадывает — и угадывает по-разному от запуска к запуску.
  • Зелёные тесты не спасают: агент пишет тесты по своему пониманию задачи и закрепляет в них собственные догадки.
  • Проблема не в агенте и не в ревьюере, а в том, где живут знания. Если их нет в контексте, их не получит ни агент, ни новый сотрудник.

Coding Agent получил обычную бизнес-задачу и репозиторий. За 4–7 минут он написал аккуратный код, прогнал тесты — все зелёные. Я повторил это 3 раза. И 3 раза агент сам назначил цену новой услуги: 199 рублей, бесплатно и 150 рублей. Бизнес утвердил 99 рублей с бесплатной доставкой от 3000.

Ниже — подробный разбор условия A из моего эксперимента для выпуска «От Coding Agent к AI Development Platform»: что агент сделал хорошо, что он придумал сам и почему это не ошибка кода. Общая картина — в основной статье о платформе, здесь только условие «задача + репозиторий».

Короткий ответ

Репозиторий — это не вся система. В нём лежат код, тесты, зависимости и конфиги. Но решения, по которым этот код должен быть написан, живут в других местах: требования у продакта, контракт API в соседнем репозитории, решение о выкатке в ADR, урок из инцидента — в разборе инцидента или просто в чьей-то памяти.

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

Условия эксперимента

Чтобы спорить не на уровне мнений, я собрал небольшой синтетический сервис доставки интернет-магазина — shipline. Ничего корпоративного: код, 9 тестов, слои api → application → domain, адаптеры, миграции, модуль возвратов — всё создано специально для выпуска.

Задача — одна, в стиле реального тикета:

PROD-2291 · Самовывоз из пунктов выдачи

Добавить новый способ доставки — самовывоз из пунктов выдачи партнёра.
Клиент при оформлении заказа должен видеть этот вариант, выбрать пункт
выдачи и увидеть стоимость и срок.

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

Два условия:

  • A — задача и репозиторий. Так чаще всего и работают с агентами.
  • B — то же самое плюс 8 коротких документов инженерного контекста: архитектура, 2 ADR, контракт API, требования, инженерные правила, политика безопасности и разбор инцидента. Всего 522 слова.

Модель одна — claude-sonnet-5, агент — Claude Code в headless-режиме с одинаковым списком разрешённых команд, стартовое состояние кода одинаковое. Каждое условие я прогнал 3 раза. Проверки написал заранее, до прогонов. Про условие B подробно — в статье о context engineering; здесь только A.

Что агент сделал хорошо

Сначала честно: код хороший. Если бы я получил такой pull request от человека, я бы не стал его разворачивать с порога.

В 2 прогонах из 3 агент начинал с того, что запускал вспомогательного агента на разведку: тот обходил репозиторий и возвращал короткую карту проекта. Потом основной агент перечитывал ключевые файлы, формулировал план и только после этого писал код.

Все 3 раза он:

  • нашёл миграцию 004_partner_pickup_points.sql с таблицей пунктов выдачи, которая нигде не использовалась, и подключил её, а не изобрёл своё хранилище;
  • добавил способ доставки классом в домене, репозиторий пунктов — в адаптерах (в памяти для тестов и поверх таблицы из миграции), сборку — в точке сборки приложения;
  • не нарушил слои: домен не импортирует адаптеры, API и слой приложения;
  • не добавил ни одного сетевого вызова;
  • посчитал деньги в копейках через Money, как принято в проекте;
  • добавил новый способ в словарь правил возврата и тест на возврат — без этой записи refund_amount падал бы с KeyError, и в прогоне A2 агент прямо объясняет это в отчёте.

Последний пункт особенно показателен: не каждый разработчик вспомнил бы о возвратах. Прогон A2 занял 262 секунды, 46 ходов и стоил 0,80 доллара.

Итог по собственным тестам агента:

            прогон    тестов   зелёные   время    стоимость
условие A   a1        22       да        346 c    $1,13
            a2        20       да        262 c    $0,80
            a3        19       да        434 c    $0,88

Вот здесь обычно заканчиваются демонстрации: код написан, тесты прошли. Но эксперимент только начинается.

Что агент придумал сам

Цена: 3 прогона — 3 цены

a1   PRICE = Money.rub(199)    всегда, без порога
a2   PRICE = Money(0)          бесплатно всегда
a3   PRICE = Money.rub(150)    всегда, без порога

PRD  99 ₽, бесплатно при сумме товаров от 3000 ₽

Ни одна цена не совпала с утверждённой. Интересно, что образец порога в коде был: курьер стоит 350 рублей и бесплатен от 5000. Но какая цена у самовывоза и есть ли у него порог, из кода не следует никак. В отчёте прогона A2 агент прямо пишет, что способ даёт «free/2-day delivery», — то есть он принял бизнес-решение и честно его описал.

Агент не ошибся в коде. Он принял решение, которое не имел права принимать, просто потому, что информации не было.

Контракт API: имена, удобные агенту

Контракт delivery-options.openapi.yaml, согласованный с командами web и mobile, требует:

code:           pickup_point
список пунктов: pickup_points[] { pickup_point_id, address, hours }
выбор пункта:   pickup_point_id
ошибки 422:     pickup_point_required, pickup_point_unavailable

Что получилось в условии A:

a1   code = partner_pickup;  список "points" с ключом "id"
a2   code = pickup_point;    список "points" с ключом "id"; выбор по "point_id"
a3   code = pickup_point;    список "pickup_points", но ключ "id"

Контрактных кодов ошибок pickup_point_required и pickup_point_unavailable нет ни в одном прогоне: вместо них общий delivery_not_available, а в A1 выбор без пункта вообще проходил. Различать «пункт не передан» и «пункт недоступен» агент не стал, потому что не знал, что клиенты это различают.

Любопытная деталь из отчёта прогона A2: агент пишет, что обработчики API менять не пришлось — они и так передают дополнительные поля как есть, поэтому список пунктов появится в ответе автоматически. Инженерно это правда. Но именно поэтому поле называется так, как было удобно внутри, — points, а не так, как договорились с клиентами. Код переиспользован идеально, контракт нарушен незаметно. Мобильное приложение ждёт pickup_points и pickup_point_id, получает points и point_id — и клиент видит способ доставки, но не может выбрать пункт.

Флаг выкатки: нет или включён сразу

В репозитории есть флаги функциональности, и экспресс-доставка стоит за флагом express_delivery, который включён. Почему флаги вообще появились, в коде не написано. А в ADR-011 написано: после запуска экспресса каждый новый способ доставки выходит за флагом delivery_<code>, по умолчанию выключенным, и включается по регионам после проверки на стенде.

a1   FLAGS["partner_pickup"] = True
a2   флага нет, способ включён всегда
a3   FLAGS["pickup_point_delivery"] = True

ADR  FLAGS["delivery_pickup_point"] = False

Агент увидел образец (express_delivery: True) и повторил его. В итоге выкатка происходит в момент мержа, сразу на всех: без стенда, без поэтапного включения, поддержка ничего не знает.

Возвраты: «возвращать» во всех 3 прогонах

Агент молодец, что вспомнил о словаре DELIVERY_FEE_REFUNDABLE. Но по требованиям стоимость доставки при возврате из пункта выдачи не возвращается. Во всех 3 прогонах агент поставил True — «возвращать». Это деньги компании: каждый невыкупленный заказ превращается в возврат стоимости доставки, который компания возвращать не собиралась.

Правило «у каждого нового способа должно быть правило возврата» пришло из инцидента INC-2025-031: экспресс запустили без записи в этом словаре, и возвраты падали двое суток. Агент повторил правильное действие из этого урока, но значение выбрал сам.

15 килограммов: расхождение, которое я нашёл позже

В требованиях есть общий лимит — 15 килограммов на заказ, и не больше лимита конкретного пункта. Во всех 3 прогонах A агент проверяет только лимит пункта max_weight_g из таблицы. Если у пункта лимит 25 килограммов, заказ на 20 уйдёт в самовывоз. Независимый валидатор в прогоне A2 проверил ровно этот сценарий: заказ 20 кг при пункте с лимитом 25 кг получил вариант самовывоза.

Этот пример мне нравится больше всего, потому что я сам его сначала не заметил. Лимит пункта агент нашёл в миграции и учёл аккуратно. Общего лимита в коде нет — значит, его нет и в решении.

Итог проверок условия A

Я заранее записал 7 детерминированных проверок того, что следует из контракта, ADR, политики безопасности и истории инцидентов, но чего нет в тексте задачи:

проверка                              a1   a2   a3   итог
тесты зелёные                         да   да   да   3 из 3
слои не нарушены (ADR-003)            да   да   да   3 из 3
нет сети в пути запроса               да   да   да   3 из 3
code = pickup_point (контракт)        нет  да   да   2 из 3
поле pickup_point_id (контракт)       да   нет  да   2 из 3
флаг выключен по умолчанию (ADR-011)  нет  нет  нет  0 из 3
доставка не возвращается (PRD п.6)    нет  нет  нет  0 из 3
всего                                 4/7  4/7  5/7

Отдельный агент-валидатор, который не видел, как писался код, написал приёмочные тесты по требованиям, контракту и ADR. Из 10 его проверок прогоны A прошли от 2 до 4. Во всех 3 прогонах провалены цена, общий лимит веса, правило возврата, формат списка пунктов, коды ошибок и флаг выкатки. Подробно про эту часть — в статье о том, почему зелёные тесты ещё не доказательство.

Картина складывается простая:

ЕСТЬ ОБРАЗЕЦ В КОДЕ                 НЕТ ОБРАЗЦА В КОДЕ
слои, порты, адаптеры     ✓ 3/3      цена и порог            ✗ 0/3
деньги в копейках         ✓ 3/3      флаг выключен           ✗ 0/3
без сетевых вызовов       ✓ 3/3      доставка не возвращ.    ✗ 0/3
                                     общий лимит 15 кг       ✗ 0/3
                                     поля по контракту       ~ то да, то нет

Там, где у агента есть образец, он сходится. Там, где образца нет, он угадывает — и каждый раз по-разному. Срок 2 дня агент, кстати, угадал во всех 3 прогонах, хотя его нет ни в задаче, ни в коде. Это удачное совпадение, а не решение: на него так же нельзя опереться, как на цену.

Почему это не ошибка кода

Важно разделить два вида дефектов.

Дефект кода — это когда код не делает того, что задумано: падает, считает неверно, нарушает инварианты. Такие вещи находят тесты, линтеры и ревью, и в условии A их почти нет. Одно честное исключение: в прогоне A1 выбор самовывоза без пункта выдачи возвращал 200 и оформлял доставку. Это следует из самой задачи («выбрать пункт»), и тут агент действительно недоработал — его собственные тесты проверяли только несуществующий пункт, но не отсутствующий.

Дефект решения — это когда код безупречно делает то, что никто не решал. Цена 0 рублей реализована корректно. Флаг partner_pickup: True работает. Правило возврата True работает. Всё это исполнено идеально — просто не то.

Второй вид дефектов нельзя исправить «лучшей моделью» или «более внимательным агентом». Цены 99 рублей нет в репозитории, её нельзя вычислить из кода. Более сильная модель угадает убедительнее, но утверждённое число не появится из интеллекта.

И это не про ИИ. Очень похоже на очень быстрого и очень старательного новичка в команде. Он отлично пишет код и читает проект. Но он не был на встрече, где договорились о цене, не читал решение про флаги и не знает, что было с экспрессом.

РЕПОЗИТОРИЙ                    ИНЖЕНЕРНЫЙ КОНТЕКСТ
код                            требования и бизнес-правила
тесты                          контракты API с другими командами
зависимости                    ADR: почему устроено именно так
конфиги                        политика безопасности
                               инциденты и выводы из них
                               стандарты команды

как система устроена           почему и по каким правилам

Почему ревью это пропустит

Справедливый вопрос: а ревьюер-человек это поймал бы? Если у ревьюера тот же контекст, что у агента, — скорее всего, нет. Код чистый, тесты есть, стиль соблюдён. Такой pull request одобряют быстро.

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

Для проверки я дал отдельному агенту-ревьюеру diff прогона A2 и тот же пакет контекста, без права что-либо менять. За 81 секунду и 25 центов он нашёл 3 блокера (цена, флаг, поля контракта), 3 серьёзных замечания и вынес вердикт «мержить нельзя». Разница между ним и автором — не в модели, а в том, что ревьюер видел требования.

Stack Overflow в опросе 2025 года фиксирует похожее ощущение у разработчиков: 66% называют главной проблемой ИИ-инструментов решения, которые «почти правильные, но не совсем». Эксперимент показывает один из механизмов этого «почти»: код правильный, а решение нет.

Что изменилось в условии B

Коротко, чтобы замкнуть историю. Та же задача, тот же репозиторий, та же модель плюс 8 документов на 522 слова. Все 3 прогона B поставили цену 99 рублей с порогом 3000, лимит 15 кг, флаг delivery_pickup_point выключенным, правило «доставка не возвращается» — и прошли 7 из 7 проверок по контексту и 10 из 10 приёмочных. Быстрее агент при этом не стал: прогоны B заняли от 275 до 547 секунд и стоили от 1,03 до 1,85 доллара. Контекст меняет не скорость написания кода, а то, насколько код соответствует задаче.

Ограничения

Чтобы не выдавать это за исследование:

  • 6 прогонов (3 в условии A и 3 в условии B), один синтетический репозиторий, одна модель;
  • проверки писал я сам и зафиксировал до прогонов; приёмочные тесты писал отдельный агент, по одной проверке на пункт требований;
  • задача специально содержит решения, которых нет в коде, — в реальной задаче их может быть больше или меньше;
  • агент работал в headless-режиме и не мог задать вопрос человеку.

Это демонстрация механизма, а не бенчмарк. Но механизм воспроизводился в каждом прогоне: если знания нет в контексте, агент его придумает — уверенно и правдоподобно.

Что делать

  1. Не считать тикет полной постановкой. Перед тем как отдать задачу агенту, спросите: какие решения по ней уже приняты вне кода? Цена, контракт, выкатка, возвраты, лимиты — всё это кандидаты в контекст.
  2. Собрать пакет контекста под задачу. Не всю вики, а требования, контракт, релевантные ADR и связанный инцидент. Для самовывоза это меньше 2 страниц. Как отбирать — в статье о context engineering.
  3. Держать постоянные правила рядом с кодом. Правила проекта в CLAUDE.md или AGENTS.md — полезный первый шаг, но это общий файл для всех задач, а не контекст конкретной задачи. Где он заканчивается — в разборе ограничений CLAUDE.md.
  4. Проверять независимо. Приёмочные тесты из требований и ревью с контекстом ловят дефекты решения, которые тесты автора закрепляют.
  5. Думать о масштабе. Пакет для эксперимента я собрал руками. Для тысяч задач нужна система, которая делает это сама, — context platform.

Если хотите разобрать, где у вас живут знания, которые агенты сейчас угадывают, — это как раз то, с чего я начинаю оценку AI-разработки в команде.

Источники

  • Эксперимент автора «От Coding Agent к AI Development Platform», 6 прогонов Claude Code (claude-sonnet-5) на синтетическом репозитории shipline, 2026.
  • 2025 Stack Overflow Developer Survey — AI. Stack Overflow, 2025.

Вопросы и ответы

Может быть, агент просто плохо написал код?

Нет. Код во всех 3 прогонах аккуратный: домен не импортирует инфраструктуру, деньги считаются в копейках, данные о пунктах берутся из существующей таблицы, сетевых вызовов нет, тесты проходят. Расхождения — в решениях, которые из кода вывести нельзя: цена, названия полей по контракту, флаг выкатки, правило возврата, общий лимит веса.

Почему агент не спросил, какая должна быть цена?

В headless-режиме ему некого спросить, но и в интерактивном режиме модель чаще заполняет пробел, чем останавливается: в задаче есть всё, чтобы написать работающий код, и ничто не говорит, что цена где-то уже утверждена. Агент не знает, чего он не знает. Поэтому вопрос «есть ли решение по цене» должен закрывать контекст задачи, а не надежда на вопрос от модели.

Более сильная модель решит эту проблему?

Не решит. Цены 99 ₽ нет в репозитории, её нельзя вычислить из кода. Более сильная модель напишет ещё более аккуратный код и угадает ещё убедительнее, но утверждённое бизнесом число не появится из интеллекта.

Поймал бы это ревьюер-человек?

Если у ревьюера тот же контекст, что у агента, — скорее всего, нет: код чистый, тесты есть, стиль соблюдён. Поймает тот, кто помнит договорённость о цене, знает контракт с мобильной командой и был на разборе инцидента. Отдельный агент-ревьюер, которому дали diff и пакет контекста, нашёл 3 блокера за 81 секунду и 25 центов.

Насколько этому эксперименту можно доверять?

Это демонстрация механизма, а не бенчмарк: 6 прогонов (3 без контекста и 3 с контекстом), один синтетический репозиторий, одна модель, проверки писал я сам и зафиксировал до прогонов. Но механизм воспроизводился в каждом прогоне: если знания нет в контексте, агент его придумывает.

Что нужно дать агенту, чтобы получить правильное решение?

Не всю вики, а небольшой пакет под задачу: требования, контракт API, релевантные ADR, инженерные правила, политику безопасности и разбор связанного инцидента. В эксперименте это 8 документов на 522 слова, и с ними все 3 прогона прошли 7 из 7 проверок по контексту и 10 из 10 независимых приёмочных проверок.

Читать дальше

СтатьяAI Development От Coding Agent к AI Development Platform: почему быстро написать код недостаточно Эксперимент на 6 прогонах: агент пишет код за минуты, но без контекста, прав и проверок решает не ту задачу. Из чего состоит AI Development Platform. 1 октября 2026 Читать → СтатьяAI Development Context Engineering для Coding Agents: почему доступа к репозиторию недостаточно Что такое Context Engineering для Coding Agents: правильный контекст под задачу, приёмы Anthropic и эксперимент, где 520 слов контекста дали 7 из 7 проверок. обновлено 5 октября 2026 Читать → СтатьяAI Development AI написал код и тесты, всё зелёное — почему задача всё ещё не решена Coding Agent написал код и 20 тестов, все зелёные, — а независимая приёмка по требованиям прошла 4 из 10. Разбираем на реальном эксперименте, почему тесты автора закрепляют его догадки, как устроить независимую приёмку и ревью и почему отчёт агента — не доказательство. 13 октября 2026 Читать → СтатьяCoding Agents CLAUDE.md: что он решает для Coding Agent и где заканчивается CLAUDE.md — инструкции проекта для Claude Code: контекст, а не принудительная конфигурация. Что в него писать и что вынести в права и контекст задачи. 9 октября 2026 Читать →