Разговоры ничего не стоят. Код тоже
Дата публикации: 2026-04-15В наше время известное изречение Линуса Торвальдса "Talk is cheap. Show me the code." можно переиначить в виде "Code is cheap. Show me the spec." Меня зовут Алекс Гусев и в этой публикации я постараюсь показать, почему я так считаю.
У меня есть несколько статей на Хабре, объединённых общей темой: ADSM (Agent Driven Software Management). По сути, это моя попытка формализовать свой личный опыт в Spec-Driven Development (SDD) в какое-то подобие методологии. Под катом я поделюсь результатами применения SDD-подхода (в его ADSM виде) к разработке простого приложения - помощника в создании плейлистов в Spotify (@flancer32/spotify-playlist). И покажу, что будет, если на базе одного и того же контекста (спецификации) сгенерировать код одним и тем же агентом (Codex, GPT-5.4) с разным уровнем reasoning'а (high, medium, low).
Предыстория
Нам для одного из семейных мероприятий понадобился плейлист на 4-5 часов на определённую тему. ChatGPT хорошо справился с задачей и выдал список из 100 музыкальных произведений с названиями и авторами. Оставалось сформировать плейлист для Spotify. Раньше мы делали это вручную и времени уходило порядком, но сейчас такие вещи легко поддаются автоматизации через ИИ-агентов.
Я уверен, что кто-то может навайбкодить подобное приложение за полчаса, а то и за десять минут. Но во-первых, я не умею вайбкодить, во-вторых, я умею SDDевелопить. Поэтому, на создание первой версии приложения у меня ушло 2 часа чистого времени.
История
До того, как я занялся реализацией этого проекта, я вообще был не в курсе о каких-либо возможностях интеграции Spotify с внешними приложениями. ChatGPT подсказал мне адрес https://developer.spotify.com/ и объяснил, что и где нужно прописать, чтобы зарегистрировать своё приложение.
Оказалось, что аутентифицироваться в Spotify нужно по протоколу OAuth. А для этого нужно иметь свой домен и TLS-сертификат. Домен у меня был, сертификат делается через Let's Encrypt. Я уже давно пишу только на JavaScript, поэтому выбор ЯП был безальтернативен. Как и выбор платформы - только TeqFW, только хардкор!
Создал приватный репозиторий на GitHub'е, склонировал на локалку. Добавил в контекст
( ./ctx/spec/ ) типовой код для nodejs-приложений на базе моей библиотеки
@teqfw/di. Где-то около часа с небольшим я в VSCode обсуждал в диалоге с
Codex-агентом детали будущей реализации - как запускать, как конфигурировать, какие
зависимости тянуть. Агент всё это аккуратно фиксировал в контексте проекта
(каталог ./ctx/docs/ ). Затем я попросил агента создать ./package.json,
bootstrap-файл ./bin/cli.mjs и головной скрипт приложения ./src/Main.mjs.
После чего попросил создать в две итерации: 1) интеграционные тесты и код для получения и
сохранения токена аутентификации через веб-сервер; 2) загрузку и парсинг текстового файла
с музыкальными композициями, поиск произведений в Spotify и формирование плейлиста
(тоже интеграционные тесты и исходники). Соответствие формата es6-модулей требованиям
своей платформы я верифицировал по скиллу
teq-esm-validator.
Я проверял работу приложения по частям (каркас - просто запуск; получение токена аутентификации; разбор файла и поиск композиций; создание плейлиста и добавление в него найденных композиций). Итого, чуть больше, чем через два часа чистого времени в моём Spotify этим приложением был создан новый плейлист из 80+ композиций. Остальные композиции из списка не были обнаружены в Spotify.
Последствия
Я время от времени вижу в комментах на Хабре, что коллеги высказывают мысль, что LLM-агенты не применимы в разработке, потому что от них нельзя получить детерминированный результат. Но для меня до сих пор программирование - это всё ещё отчасти искусство. Если бы Леонардо да Винчи рисовал свою Джоконду десять раз, то он бы нарисовал десять разных картин, на которых была бы изображена одна и та же женщина. Если любой программист десять раз реализует достаточно сложное приложение, то это будет десять разных приложений с одним и тем же, заданным, функционалом.
"детерминированность результата" != "детерминированность кода"
Для демонстрации этой идеи я опубликовал оригинальный код, созданный Codex-агентом
(GPT5.4, high reasoning) под версией 1.0.0. Только код, контекст я специально вырезал.
Затем я попросил Codex-агента (GPT-5.4, medium reasoning) удалить папки
./src/ & ./test/ и на основе того же самого, неизменённого
контекста из папки ./ctx/ создать с нуля тесты и исходники (для экономии я
оставил прежние package.json и boostrap-файл). Получилась версия
2.0.0. Затем то же самое проделал на GPT-5.4, low reasoning - версия 3.0.0.
Промпт для перегенерации исходников
Вот сводка по созданным исходникам, сделанная агентом:
Версия Файлы в src Каталоги в src Строк всего Код Комментарии Пустые
1.0.0 23 9 1546 983 404 159
2.0.0 18 10 1436 844 462 130
3.0.0 20 10 993 665 274 54
Можно зайти по ссылкам и посмотреть на получившийся код - он не идентичен. Можно установить любую из версий, получить токен аутентификации со Spotify и создать плейлисты - @flancer32/spotify-playlist работает одинаково.
Замечания
У меня ушло довольно много времени (месяцы) на создание спецификаций для моего стиля
разработки ( ./ctx/spec/code/platform/teqfw/ ) и я всё ещё продолжаю развитие
этой документации. Но это часть контекста, переиспользуемая между всеми моими проектами.
И мне потребовалось пару часов на описание продукта (создание документов в пространстве
./ctx/docs/). Но на генерацию тестов и кода каждой из версий у агента ушло в
районе 10 минут. И что интересно, вне зависимости от reasoning-уровня у меня ушло порядка
4% недельной квоты от plus-подписки на ChatGPT на генерацию каждой из версий.
Все три версии затупили с созданием плейлиста в Spotify. Dry-запуск они проходили и треки искались, но при попытке добавления треков в плейлист все три раза агент использовал устаревший API и приходилось ему каждый раз указывать на эту ошибку. Если бы я не старался делать более-менее чистый эксперимент, я бы внёс в когнитивный контекст требование использовать новый API от Spotify, но я специально выполнял генерацию кода на одном и том же контексте. Так что помимо детерминированности результирующего функционала также проявилась и детерминированность ошибок прочтения контекста агентом.
Третья версия, которая делалась low-reasoning агентом, не справилась с запуском веб-сервера. Вернее, справилась - веб-сервер стартовал, но приложение сразу же его глушило, не дожидаясь получения токена аутентификации от Spotify. На уровнях high & medium такой проблемы не возникло.
Для понимания соотношения объёма документов контекста (ctx) к результирующему коду (см. таблицу выше):
Файлы в ctx 53
Каталоги в ctx 27
Строк всего 5378
Пустых 1869
Что касается объёма в байтах, то сводка такая:
Файлы в ctx 152Kb
src v1 (high) 48Kb
src v2 (medium) 42Kb
src v3 (low) 36Kb
Да, это моя осознанная позиция: документы контекста по объёму должны быть в разы больше результирующего кода.
Скиллы
Отдельно нужно выделить скиллы. Моя платформа использует позднее связывание исходников в
момент выполнения. Все зависимости внедряются через конструктор. А это значит, что во всех
файлах из каталога ./src/ нет статических импортов. Ни одного. Это довольно
нетрадиционный подход к JS-кодированию и агенты очень плохо в него умеют.
Когда я столкнулся с упорным желанием агентов создавать классический исходный код
(с ранним связыванием кода при помощи статических импортов), мне пришлось сделать свой
скилл - teqesm-validator. Его, кстати, тоже делал Codex-агент по той же
методологии ADSM. После этого было достаточно в промпте указать, что нужно использовать
этот скилл для проверки исходников, и проблема со связыванием очень сильно уменьшилась.
По крайней мере, в этом проекте с помощью создания плейлистов в Spotify она не возникла ни разу.
Заключение
Я сравниваю поведение LLM-агентов при генерации кода с поведением дождевой воды, которая следуя изгибам рельефа, собирается в струйки, в ручьи, в реки и стремится к океану. Так же и агент генерирует код - следует по пути наименьшего сопротивления. Документы контекста в этой аналогии играют роль плотин и каналов, а скиллы и тесты я бы сравнил с насосами, забрасывающими воду на другой уровень (шлюзование). Оттуда вода опять может течь вниз, но уже по другому пути.
Основные затраты в таком подходе - это инфраструктура (те самые плотины, каналы, шлюзы). Но зато потом, после создания этой инфраструктуры, вода в большинстве случаев попадёт туда, куда было задумано строителями. Код в моём представлении - это не конечный артефакт, а производный. Результат взаимодействия когнитивного контекста и агента.
Именно исходя из этих соображений я и считаю, что контекст проекта (те самые 53 файла в
./ctx/), важнее самого кода (18-23 файла в ./src/). Ведь когда у
тебя есть контекст, агент тебе сделает нужный код в течение минут. Даже такой экзотический,
как TeqFW.
Вы можете свободно изучать код всех трёх версий - он дешёвый. Но если вы хотите увидеть контекст проекта - стучите в личку. Я дам контекст бесплатно, в обмен на обратную связь о возможности применимости данного подхода в ваших проектах.
P.S. И немножко прекрасного. ИИ-агенты спокойно вытягивают "бойлерплейт" и делают ненужными
множественные зависимости в ./node_modules/:
Им ничего не стоит захардкодить Web API и перехардкодить его в случае изменений. В моём приложении всего две зависимости для режима runtime (мои собственные библиотеки) и ещё две зависимости для dev-режима (разрешение типов Node.js).