Constraint Decay: The Fragility of LLM Agents in Back End Code Generation

25.05.2026 · 5 мин

Я недавно наткнулся на исследование, которое заставило меня пересмотреть всё, что я думал о надёжности LLM-агентов (AI-модели, которые могут выполнять задачи автономно, обдумывая каждый шаг). Суть простая: когда задача становится сложнее, эти агенты начинают… терять голову. Не метафорически — буквально. Они забывают про ограничения, косячат в слое данных и в итоге выдают код, который работает «где-то примерно».

Называется это constraint decay — постепенный распад следования ограничениям. И если вы думаете, что это проблема только слабых моделей, — нет. Исследование показало падение на 30 баллов в assertion pass rates (процент успешно пройденных проверок — какая доля тестов показала, что код работает правильно) даже у сильных конфигураций. От бейслайна (исходный уровень, с которым сравнивают результаты — базовая версия без оптимизаций) до полностью специфицированной задачи.

Давайте разберёмся, почему так происходит и что с этим делать.

Что такое распад ограничений

Представьте: вы даёте агенту задачу написать бэкенд на FastAPI. Однофайловый хелло-ворлд — без проблем. Добавляете требования: REST-маршруты (адреса API — например `/users`, `/orders`, через которые приложение принимает запросы), модель базы данных, ORM-маппинг (Object-Relational Mapping — прослойка, которая превращает записи из базы данных в объекты в коде, чтобы программист работал не с таблицами, а с привычными структурами), миграции (скрипты, которые меняют структуру базы данных — добавляют таблицы, колонки, индексы), тесты — и начинается магия.

Constraint decay — это феномен, при котором агент по мере накопления структурных требований всё хуже следует ограничениям. Не потому что он тупой. А потому что каждый новый слой ограничений — это дополнительная нагрузка на контекст (в данном случае — вся информация, которую модель «держит в голове» во время работы), дополнительные правила, которые нужно удерживать.

РАСПАД ОГРАНИЧЕНИЙ ПО МЕРЕ РОСТА ЗАДАЧИ
─────────────────────────────────────────
Простое задание          ██████████  95% точность
+ Архитектура            ███████░░░  80%
+ База данных            █████░░░░░  65%
+ ORM + миграции         ███░░░░░░░  45%
+ Тесты + интеграции     ██░░░░░░░░  30%

Каждый слой = -15-20% точности
Как падает точность с добавлением структурных требований

Исследователи измерили это на 80 задачах генерации с нуля и 20 задачах реализации фич. Восемь веб-фреймворков, единый API-контракт, двойная оценка: поведенческие тесты и статические верификаторы (инструменты, которые автоматически проверяют код: соответствует ли он правилам, нет ли ошибок в стиле, нарушена ли схема).

Где именно ломаются агенты

Самое интересное — где агенты косячат больше всего. Не в логике, не в алгоритмах. В слое данных.

Три главные проблемы:

1. Неправильная композиция запросов. Агент генерирует SQL или ORM-запрос, который выглядит разумно, но содержит ошибку: неправильное условие JOIN, отсутствующий фильтр, некорректный агрегат.

2. ORM runtime violations. Нарушения времени выполнения — попытка сохранить объект без обязательного поля, нарушение внешнего ключа, неправильный тип данных.

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

ЦЕПОЧКА ОШИБОК В МНОГОШАГОВОЙ ЗАДАЧЕ
──────────────────────────────────────
Шаг 1:  Модель User     ✓ Схема соблюдена
Шаг 2:  Роут /users     ✓ REST-конвенция
Шаг 3:  CRUD-сервис     ✓ Логика ОК
        (Create, Read, Update, Delete —
         сервис, который умеет создавать,
         читать, изменять и удалять данные)
Шаг 4:  Миграция        ⚠ Мелкое отклонение
Шаг 5:  Тесты           ✗ Ограничения забыты
Шаг 6:  Интеграция      ✗ Контекст потерян

На шаге 5-6 агент "забывает" про ранние ограничения
Как отклонения накапливаются с каждым шагом

Отдельно забавно про фреймворки. Flask — минималистичный, явный, мало магии — работает отлично. FastAPI и Django — конвенционально нагруженные (фреймворки с большим количеством встроенных правил и «магии», которую нужно знать), со своими правилами, скрытыми зависимостями — результаты заметно хуже. Агент хорошо справляется, когда всё написано руками. Когда нужно следовать «магическим» конвенциям фреймворка — начинаются проблемы.

Почему это важно для практики

Я вижу три категории людей, которых это касается напрямую.

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

Тимлиды и архитекторы, которые планируют внедрение AI-агентов в процессы. Исследование показывает: функционально корректный код — это ещё не production-ready код. Агенты хорошо справляются с «работает», но косячат на «правильно структурировано».

Авторы инструментов — если вы делаете что-то для AI-ассистированной разработки, учитывайте: статические верификаторы важнее, чем кажется. Поведенческие тесты покажут, что код работает. Верификаторы покажут, что он следует ограничениям.

Как снизить риск

Исследование не только описывает проблему — авторы дают направления. Вот что имеет смысл делать практически:

Разбивать задачи на короткие шаги. Вместо «напиши мне бэкенд» — «создай модель», «добавь роут», «напиши тесты». Каждый шаг — отдельный запрос с чёткими ограничениями.

Валидировать каждый шаг. Тесты, линтеры, статические анализаторы (программы, которые изучают код без его запуска и находят проблемы — от опечаток до серьёзных багов) — запускать после каждого сгенерированного файла, а не в конце.

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

Использовать явные фреймворки. Если выбираете между Flask и Django для AI-генерируемого кода — Flask проще. Меньше магии, больше явных правил.

Коротко

LLM-агенты отлично справляются с изолированными задачами. Проблема начинается, когда задача обрастает ограничениями: архитектурой, базой данных, ORM, тестами, интеграциями. Каждый новый слой требований — это минус к точности.

Constraint decay — не баг конкретной модели, а системная проблема накопления. Решение: дробить задачи, валидировать часто, фиксировать ограничения явно.

Если вы используете AI для генерации бэкенда — не расслабляйтесь. Функционально корректный код и production-ready код — это разные вещи. Исследование это подтверждает цифрами.

Ссылки

Дмитрий Полухин — продуктовый дизайнер. Пишу про разработку, AI и дизайн интерфейсов. Обо мне, контакты и профили.