
Эта статья, по сути, родилась как развёрнутая версия фрагмента комикса, который вы видите выше.
Честно говоря, я довольно долго не видела надобности в подобной статье. Если кто-то начинал говорить о генерации кода на основе спецификаций, то я просто показывала ему эту картинку, и обычно этого хватало.
Однако сегодня сторонники агентного программирования утверждают, что нашли способ победить гравитацию и генерировать код исключительно на основе спецификаций. Более того, они настолько замутили воду, что теперь к приведённому фрагменту комикса нужно давать дополнительное пояснение, почему их утверждения нереалистичны.
Все встреченные мной аргументы сторонников этой идеи обычно опираются на два распространённых заблуждения:
Заблуждение 1: техническая документация проще кода, который по ней создаётся.
На это утверждение ссылаются, когда рекламируют агентное программирование тем, кто считает его следующим поколением аутсорсинга. Эти люди мечтают, что разработчики превратятся в менеджеров, пишущих техническую документацию, которую потом можно отдавать команде агентов для реализации. Такое решение работает, только если определить необходимую работу дешевле, чем фактически её реализовать.
Заблуждение 2: написание документации должно быть более вдумчивым, чем написание кода.
На это заблуждение опираются, когда проповедуют агентное программирование скептикам, которые беспокоятся, что такой подход приведёт к размножению необслуживаемого слопа. Их аргументы сводятся к тому, что структурирование работы с помощью технической спецификации повысит качество и будет способствовать использованию эффективных практик разработки.
И ниже я на конкретных примерах распишу, почему считаю эти заявления заблуждениями.
Завуалированный код
Начну с проекта Symphony компании OpenAI, который преподносится как пример проекта, сгенерированного на основе технической документации.
Symphony — это оркестратор агентов, который по заявлениям его разработчиков был сам сгенерирован из «специцикации» (SPEC.md). Я специально взяла «спецификацию» в кавычки, так как представленный файл больше походит на псевдокод в Markdown. Если заглянуть в этот документ поглубже, то мы увидим, что он содержит, например, текстовое описание схемы базы данных:
4.1.6 Live-cессия (метаданные сеанса работы с агентом)
Состояние, отслеживаемое, когда запущен подпроцесс ИИ-агента.
Поля:
session_id(строка,<thread_id>-<turn_id>)
thread_id(строка)
turn_id(строка)
codex_app_server_pid(строка или null)
last_codex_event(строка/перечисление или null)
last_codex_timestamp(временная метка или null)
last_codex_message(краткое содержание)
codex_input_tokens(целое число)
codex_output_tokens(целое число)
codex_total_tokens(целое число)
last_reported_input_tokens(целое число)
last_reported_output_tokens(целое число)
last_reported_total_tokens(целое число)
turn_count(целое число)
Количество запусков агента за время работы текущего воркера.
…Или текстовое описание кода:
8.3 Управление многопоточностью
Глобальный лимит:
available_slots = max(max_concurrent_agents - running_count, 0)Лимит на состояние:
max_concurrent_agents_by_state[state]если есть (ключ состояния нормализован)в остальных случаях использовать глобальный лимит
Среда выполнения подсчитывает задачи по их текущему отслеживаемому состоянию в словаре
running.8.4 Повторные попытки и увеличение задержки
Создание записи о повторной попытке:
Сбросить существующий таймер повтора для той же задачи.
Сохранить попытку, идентификатор, ошибку,
due_at_msи дескриптор нового таймера.Формула использования задержки:
Обычные повторные попытки после корректного завершения воркера выполняются с фиксированной задержкой в 1 000 мс.
Повторные попытки, вызванные сбоем, выполняются с задержкой, вычисляемой по формуле
min(10000 * 2^(attempt - 1), agent.max_retry_backoff_ms).Максимальная задержка повтора ограничивается установленным значением (по умолчанию 300000 / 5 м).
Обработка поведения повторов:
Получение активных кандидатов-задач (не всех задач).
Поиск конкретной задачи по
issue_id.Если не найдена, освободить её.
Если найдена и всё ещё среди кандидатов:
При наличии доступных слотов запустить.
В противном случае вернуть в очередь с сообщением об отсутствии свободных слотов оркестратора.
Если найдена, но уже неактуальна, освободить.
… Или разделы, добавленные конкретно для тонкого контроля генерации кода моделью:
6.4 Список полей конфигурации (памятка)
Этот раздел намеренно расширен, чтобы агент мог быстро реализовать слой конфигурации.
tracker.kind: строка, обязательная, сейчасlinear.
tracker.endpoint: строка, по умолчанию https://api.linear.app/graphql, когдаtracker.kind=linear…
… Или непосредственно код1:
16. Образцы алгоритмов (безразличные к языку)
16.1 Запуск сервиса
function start_service(): configure_logging() start_observability_outputs() start_workflow_watch(on_change=reload_and_reapply_workflow) state = { poll_interval_ms: get_config_poll_interval_ms(), max_concurrent_agents: get_config_max_concurrent_agents(), running: {}, claimed: set(), retry_attempts: {}, completed: set(), codex_totals: {input_tokens: 0, output_tokens: 0, total_tokens: 0, seconds_running: 0}, codex_rate_limits: null } validation = validate_dispatch_config() if validation is not ok: log_validation_error(validation) fail_startup(validation) startup_terminal_workspace_cleanup() schedule_tick(delay_ms=0) event_loop(state)
Мне кажется, несправедливо позиционировать такой подход как альтернативу коду, когда по факту технический документ уже читается как код (а местами им и является).
Нет, я не хочу сказать, что в техническое описание не нужно включать псевдокод или образец реализации. Всё это вполне типично для спецификаций. Но нельзя утверждать, что эти документы являются заменой коду, когда они читаются как код.
Этот пример я привела, так как, на мой взгляд, Symphony хорошо отражает первое заблуждение:
Технические документы проще кода, который по ним создаётся
Если вы стремитесь сделать описание достаточно точным для надёжной генерации рабочей реализации, то вам неизбежно придётся превратить его в код или что-то очень похожее на код (например, используя чётко структурированное, формальное описание на английском).
Дейкстра писал, почему это неизбежно:
Теперь мы знаем, что выбор интерфейса — это не просто распределение (фиксированного объёма) труда, поскольку сюда необходимо прибавить работу, связанную с взаимодействием через этот интерфейс. Мы также поняли — и это развеяло наши иллюзии — что изменение интерфейса может легко увеличить объём работы с обеих сторон (и порой намного). Отсюда и предпочтение так называемых «узких интерфейсов». Поэтому перевод коммуникации между машиной и человеком на родной язык последнего мало того что приведёт к значительному увеличению нагрузки на первую, но и вовсе не гарантирует, что жизнь человека станет проще.
Если оглянуться на историю математики, то мы увидим обоснования для такого сомнения. Греческая математика зашла в тупик, потому что оставалась в рамках устного и начертательного подхода. Мусульманская «алгебра» после робкой попытки перейти к символике загнулась, вернувшись к риторическому стилю. А современный цивилизованный мир смог развиться — к худшему или лучшему — только когда Западная Европа освободилась от оков средневековой схоластики (тщетной попытки достичь точности с помощью слов.) Всё благодаря тщательным, или как минимум сознательно выстроенным системам символов, которыми мы обязаны таким фигурам, как Виета, Декарт, Лейбниц и позднее Буль.
Практикующие агентное программирование на своих граблях познают, что нельзя избежать «узких интерфейсов» (читай «кода»), которые необходимы в инженерной работе. Можно лишь трансформировать эту работу во что-то поверхностно отличное, но всё равно требующее такого же уровня точности.
Нестабильность
К тому же, генерация кода на основе спецификаций не гарантирует его надёжной работы! Я даже попробовала использовать подход, предложенный в README Symphony:
Попросите ИИ-агента создать Symphony на любом языке программирования:
Реализуй Symphony в соответствии со следующим техническим документом: https://github.com/openai/symphony/blob/main/SPEC.md
Я попросила Claude Code разработать Symphony на языке Haskell2, и ничего толкового не вышло. Результат можете посмотреть в моём репозитории Gabriella439/symphony-haskell repository.
В коде не только присутствовало множество багов (которые я потом просила Claude исправить, и все эти исправления есть в истории коммитов), но даже когда что-то «работало» (то есть не было сообщений об ошибках), агент просто молча, без какого-либо прогресса, зависал над следующим тикетом Linear:
Создай новый пустой репозиторий
Не нужно создавать проект GitHub. Просто создай пустой репозиторий git.
Иными словами, «тщетная попытка обеспечить словесную точность» (говоря словами Дейкстры) всё равно не приводит к надёжной генерации рабочей реализации.3
И эта проблема касается не только Symphony. Аналогичные сложности наблюдаются даже с известными спецификациями вроде YAML. Технический документ YAML крайне подробен, широко используется и включает набор тестов. Но подавляющее большинство итоговых реализаций YAML также не соответствуют исходной спецификации в полной мере.
Разработчики Symphony могли бы попробовать исправить эту нестабильность, расширив спецификацию, но она и без того длинная — примерно 1/6 от размера реализации на Elixir. Если продолжить её расширять, то получится как в истории Борхеса «О точности в науке»:
…В той империи искусство картографии достигло такой степени совершенства, что карта одной провинции получилась размером с целый город, а карта всей империи — размером с провинцию. Но и такие карты невообразимых масштабов показались картографам недостаточными. Тогда их гильдия составила карту всей империи, размером с саму империю и повторявшую её один-в-один. Будущие поколения картографов, которые не разделяли того же рвения к совершенству картографии, сочли столь огромную карту никчёмной и беспощадно бросили её на растерзание палящему солнцу и суровым зимам. Даже по сей день в пустынях Западных земель можно найти обрывки этой Карты, населённые животными и бездомными. Никакого другого наследия великой науки географии в той империи не осталось.
Слоп
Предполагается, что создание спецификации должно быть труднее, чем написание кода. Обычно технические документы составляются перед основной работой для того, чтобы можно было вдумчиво и критически оценить проект, так как после начала его реализации мы переходим в режим активного действия, и сделать это объективно становится труднее.
Тогда почему же я называю следующее утверждение заблуждением:
Создание спецификации должно быть более вдумчивым, чем написание кода
Проблема в том, что мы уже не можем считать такой вдумчивый подход само собой разумеющимся. Тенденции индустрии таковы, что технологические компании стремятся уменьшить и обесценить труд специалистов. Когда вы начинаете с предпосылки «Создание спецификации должно быть сложнее, чем написание кода», то обрекаете себя на провал. Вы никак не сможете проделывать сложную и неприятную работу, которой требует составление спецификации, если будете нацелены поскорее поставить продукт. Поэтому в итоге вы и получаете что-то вроде «спецификации» Symphony, которая снаружи выглядит как технический документ, но при внимательном рассмотрении рассыпается.
На деле спецификация Symphony читается как сгенерированный ИИ слоп. Особо ярким примером этого является Раздел 10.5. Вот его фрагмент:
Контракт расширения
linear_graphql:
Назначение: выполнить сырой GraphQL-запрос к Linear или мутацию, используя настроенную в Symphony авторизацию трекера для текущей сессии.
Доступность: имеет смысл, только когда
tracker.kind == "linear", и настроена валидная аутентификация Linear.Предпочтительная форма ввода:
{
"query": "single GraphQL query or mutation document",
"variables": {
"optional": "graphql variables object"
}
}
запрос должен быть непустой строкой.
запрос должен содержать ровно одну операцию GraphQL.
переменные необязательны, и при их наличии должны являться объектом JSON.
Реализации могут дополнительно принимать сырую строку GraphQL-запроса в качестве сокращённого ввода.
Выполнять по одной операции GraphQL за вызов инструментов.
Если переданный документ содержит несколько операций, отказать в вызове инструмента по причине недопустимого ввода.
Выбор
operationNameнамеренно вынесен за рамки этого расширения.Повторно использовать установленную конечную точку Linear и параметры аутентификации из активной конфигурации рабочего потока/среды выполнения Symphony; не требовать от агента считывания сырых токенов с диска.
Семантика результата инструмента:
успешный транспорт + отсутствие ошибок GraphQL верхнего уровня ->
success=trueприсутствуют ошибки GraphQL верхнего уровня ->
success=falseс сохранением тела ответа GraphQL для отладкинедопустимый ввод, нет авторизации или сбой при транспорте ->
success=falseс содержанием ошибкиВернуть ответ GraphQL или содержание ошибки в виде структурированного вывода инструмента, который модель сможет проанализировать в рамках сессии.
Вот вам сборная солянка из предложений «в виде спецификации», которая читается как продукт работы агента — никакой связности, цели и понимания общей картины.
Подобный документ обязательно будет слопом, даже если его написал человек, потому что здесь акцент на скорости поставки, а не связности и ясности. В текущих реалиях мира разработки мы уже не можем ожидать как данность спецификации, рождённые в результате внимательного обдумывания и взвешенных решений.
Заключение
Спецификации никогда не задумывались, как средство экономии времени. Если вы оптимизируете процесс под скорость поставки продукта, то лучше сразу писать код, минуя этап создания промежуточного технического документа.
Если говорить в более общем ключе, то здесь применяется известный принцип «мусор на входе — мусор на выходе» (garbage in, garbage out, GIGO). Просто нет такой реальности, где вы можете скормить агенту документ, в котором не хватает деталей и ясности, и ожидать от него качественного восполнения этих пробелов. Агенты не умеют читать наши мысли, и даже если научатся, этого будет недостаточно, когда в самой голове неразбериха.
Сноски
-
Я специально не стала форматировать этот фрагмент кода, чтобы сохранить Markdown-формат в стиле GitHub, в каком этот код приводится в оригинальном документе. Все подобные фрагменты оформляются как прямой текст (один из многих признаков, что они сгенерированы ИИ). По факту это является примером того, что модель воспринимает документ буквально, не улавливая суть изложенного запроса. Уверена, было как-то так: человек попросил ИИ преобразовать изначальный набросок проекта в текстовую спецификацию, и ИИ решил, что форматирование фрагментов кода в таком виде делает их более текстовыми. ↩
-
Мне многие пишут «результат был бы качественней, если бы ты попросила сгенерировать его на более популярном языке, а не Haskell». На что я отвечаю: «Если у агента сложности с генерацией кода на Haskell, это говорит о его неспособности уверенно обобщаться на данные, выходящие за рамки обучающей выборки». ↩
Если вам кажется, что я что-то сделала не так, можете повторить эксперимент сами. ↩
Комментарии (35)

Kot_na_klaviature
27.03.2026 09:29У меня было такое, что после генерации по подробному тз агент сделал не так, как в ТЗ. Я ему пишу - у тебя расхождения с ТЗ. Агент говорит "да точно" и исправляет тз.

Brazil
27.03.2026 09:29Спецификция или код, но даже Cloud Opus 4.6 редко выполняет все в точности, как написано.
Даже файл инструкций, где прям точно говорится какие операторы применять, а какие нет он часто игнорит. У моделей все еще плохое внимание и маленький контекст.
Говорить про инструкции как код явно рановато.
Kot_na_klaviature
27.03.2026 09:29Я бы даже сказал, что по большей части модели игнорируют правила. У меня в Мейн правиле написан абзац про то, что нельзя дублировать код и что делать, но агент каждый раз пишет лапшу с дубликатами.

NOnameSERVER
27.03.2026 09:29Я заметил, что инструкции а-ля "не делай X" работают для нейросеток отвратительно. Модель фокусируется на самом понятии X и с высокой вероятностью именно его и сгенерирует, как-то лучше работает если писать "делай Y"

Kot_na_klaviature
27.03.2026 09:29Ну если в чате пишешь "не дублируй код" с ссылкой на дубликат, то он исправляет. Там проблема в том, что правила теряются в контексте и внимание слабое. Отсюда все проекты вайбкодеров, которые видел - лапша из говнокода и дубликатов, хотя у них там базовые стандарты качества в правилах и mcp прописаны.

cross_join
27.03.2026 09:29

NOnameSERVER
27.03.2026 09:29Вся эта истерия с агентным программированием раздута производителями LLM для поднятия своей капитализации. Они продают сказку о волшебной кнопке "сделай мне ИТ-продукт", игнорируя фундаментальные законы инженерии программного обеспечения

orenty7
27.03.2026 09:29игнорируя фундаментальные законы инженерии программного обеспечения
Это какие?

Astrowalk
27.03.2026 09:29Закон сохранения сложности.

orenty7
27.03.2026 09:29В нём фундаментальности столько же, сколько в народных мудростях. Эмпирическое наблюдение людей разрабатывавших софт 50 лет назад это не “фундаментальный закон инженерии программного обеспечения”

SolidSnack
27.03.2026 09:29Как минимум устойчивость при сохранении изменчивости/возможности к расширению. Читали бы книги которые ругаете.
Безопасность ещё. В OWASP небезопасный дизайн входит в топ 10 уязвимостей.

SAWER
27.03.2026 09:29Т.е. ты считаешь, что Колмогоров и другие тысячи математиков ошибались? Или просто ничего об этом не знаешь?

orenty7
27.03.2026 09:29О, попытка давить авторитетом целых тысяч математиков. Сразу видно оппонент об этом всё знает. Жаль, только по контексту “эмипирическое наблюдение людей разрабатывавших софт” не догадался, что речь не о Колмогоровской сложности

AirLight
27.03.2026 09:29Могут ли они в одиночку что-то раздуть, если публика не будет хавать? Вполне тут прослеживаются соучастники.

oracle_schwerpunkte
27.03.2026 09:29Просто нет такой реальности, где вы можете скормить агенту документ, в котором не хватает деталей и ясности, и ожидать от него качественного восполнения этих пробелов.Да полно. Если проект можно составить из кусков имеющегося кода в интернете, то в 95% получится хороший результат. С "Клиент должен иметь возможность просмотра товаров в корзине" агент справляется прекрасно!

titan_pc
27.03.2026 09:29Весёлые картинки. Местами правдивые, но они не отражают обратную сторону медали.
Нож в руках домохозяйки не поможет ей какими бы спецификациями она там необложилась создать инженерный и зрелый продукт. Томлёную утку с соусом дорблю на 1000 человек за 8 часов.
Нож в руках мастера...
Я взял себе поиграться такой нож. И вывел новое понятие "Эспириенсофикация".
Это когда ты берёшь тупой нож и вытачиваешь его своим опытом в самурайский клинок. Это похоже на то, как мы раньше учили людей не умеющих писать код и строить крепкие масштабируемые системы - этому нелегкому ремеслу.
Только вместо человека теперь вот этот нож, несведущий в тонкости ремесла. Из плюсов он с тобой не спорит. Из минусов тоже самое. Но всё лечится правилами - достаточно сказать спорь со мной и он будет.
А что ещё можно вылечить?
Ну не понимает он Вашу кухню - так поясните в .md файл. Не знает он ваших киллерфич как написать код так, чтобы его пошла тестировать команда qa и такая - хм, сегодня опять багов нет - так покажите ему в .md
У вас 100% полно своих годами проверенных практик по разработке, оформленных в docx. И в виде кусков и может даже целых библиотек да подмодулей кода 100% работающего и универсальгого - так поясните ей как Вы это используете.
Поработайте так с этим тупым ножом месяц другой и тут случится немыслемое. Вы поймёте, что буквально прикрутили ему свою голову. И оно всё делает так - как Вы бы делали.
Да это огромное контекстное окно 150к токенов на старте. После глоссариев и тюнинга 50-100к токенов. Но чёрт возьми в моей голове 100млн + токенов опыта лежит. И осталось лишь их все переложить в текст.
И вот тогда говоришь сделай с кайфом корзину товаров - а там через 10 минут выйдет конфетка пушка. Можно ещё кнопку планировать нажать и оно там само спросит - авторизация где, стек какой, скок юзеров. Нам как обычно - лишь бы взлетело, а ибешку потом допилим? Может сразу? Там 50к токенов делов. Ну ты кожанный не спорь - давай захешируем пароли. В смысле ты собрался бесконечное имя хранить в базе? Наверное с похмелья.
И это новая реальность - только имея за плечами 10+ лет инженерного опфта можно и даже нужно его упаковать в sdd. Хотя я бы назвал это
Expirience to text и вот это модное в конце driven development. ExToTexDD
Пока ток ценник не радует) А так мощно вышло. Ушел с кухни, а нож за тебя пилит также как ты.
Ограничения - цена на токены. Ну и вы не сможете вложить опыт которого у Вас нет. Я не умею во фронтенд. И чушь получилась, как бы я не просил и не списывал чудо sdd.

whiteroller
27.03.2026 09:29Коллега, подписываюсь под каждым словом! Я работаю в АСУТП и тоже весь свой опыт упаковал в . md и протестировал - напиши мне учебный проект....llm написала все по правилам, и без замечаний от меня.

rukhi7
27.03.2026 09:29Тенденции индустрии таковы, что технологические компании стремятся уменьшить и обесценить труд специалистов.
и не поспоришь! И почему то никто не задумывается насколько это парадоксальная ситуация! Индустрия пытается отстранить от себя тех кто ее создал, тех кто является движущей силой ее развития, индустрия пытается заменить свое содержание суррогатом. Индустрия перерождается. Индустрия превращается в раковую опухоль. Она копит "эффективных" менеджеров, которыми затопит и заразит все остальные сферы человеческой деятельности когда лопнет.
Но это не впервые в человеческой истории, когда то власть над умами захватила схоластика и царствовала века, сжигая людей на кострах (вплоть до того что)! Развитие идет по спирали - прогресс сменяется регрессом, чтобы снова вернуться к прогрессу.

PPPeter
Очень тяжело понять, что вы имеете ввиду. По каким критериям можно сравнить мягкое vs зеленое?
И тогда принцип:
> «мусор на входе — мусор на выходе» (garbage in, garbage out, GIGO)
очень точен)
AdrianoVisoccini
по моему очень просто понять, что имеется ввиду
люди, которые так говорят, считают, что написать "человеческим" языком проще, чем написать код. Но когда ты пишешь модели человеческим языком у нее остается место для интерпретаций, на что говорят "надо просто писать точнее" и вот это "писать точнее" приводит в итоге к тому, что ты буквально пишешь код, но человеческим словами, но это все ещё код. И он получается сложнее чем код, требует больше письма чем код, а главное - результат можно будет в итоге привести обратно к коду.
CareDealer
Не помню уже откуда, но демонстрируется просто: попроси кого угодно написать документацию к созданию бутерброда или завязыванию шнурков текстом, пошагово и удивись как исполнитель может ее исказить и исполнить верно по пунктам, но на выходе не получить внятного результата. После такого становится ясно сколько всего остаётся за рамками документации и додумывается исполнителем самостоятельно)
CareDealer
И вот телефон меня подслушал и выдал шортс с этим видео спустя 2 суток. Кому интересно поделюсь ссылкой
https://www.youtube.com/watch?v=w7F80U-pPVk
не оригинал, но хотя бы полный перезалив