Перейти к содержимому

ИИ-агент тупит: как инструкции и проверки влияют на качество разработки

"Агент тупит" - чаще всего это диагноз инструкции, а не модели

TL;DR

После года работы с ИИ-агентом в промышленной разработке я почти перестал использовать формулировку "модель поглупела". Большинство ошибок, которые выглядят как глупость, невнимательность или галлюцинация, обычно объясняются недостатками самой инструкции:

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

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

Откуда взялись эти выводы

Мы разрабатываем low-code-платформу "Интеграм" и создаём на её основе приложения для заказчиков. Основной репозиторий ideav/crm был создан 30 января 2026 года. На момент описания в нём находилось 6258 коммитов, 2310 тикетов и 2583 объединённых pull request.

Почти весь код пишет ИИ-агент. Работа строится через тикеты, а результат принимается по pull request. Инструкции хранятся в том же репозитории: основной файл CLAUDE.md находится в корне, база знаний по платформе - в docs/kb/, а описание полного цикла разработки приложений - в docs/integram-app-workflow.md.

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

Никаких магических промптов мы не нашли. На практике лучше всего работает гораздо более скучная система: правильная форма правила, правильное место для него и обязательная проверка результата.

Ошибка первая: правило написано как предупреждение

В нашей платформе есть два разных типа связей между таблицами:

- ссылка - обычный внешний ключ;
- подчинённая таблица - например, позиции заказа или контакты сотрудника.

Перепутать их дорого: ошибка меняет структуру данных и может потребовать переделки схемы.

Изначально в инструкции было написано:

> Для ссылки нельзя использовать сокращённую форму `dreq/{source} t=` без предварительного `dref`. Такая запись не создаёт внешний ключ, а формирует подчинённую таблицу.

Казалось бы, правило исчерпывающее: указаны неверная форма, причина и последствия. Однако агент снова превратил справочники в подчинённые таблицы.

Причина обнаружилась в самой формулировке. Инструкция объясняла только, чего делать не следует. Но агенту нужно было не просто исключить неправильный вариант, а выбрать правильный.

После замечания заказчика правило переписали по принципу: "Опиши, как надо, чтобы это можно было выполнить буквально". В разделе появились:

- четыре критерия выбора типа связи;
- таблица сравнения;
- описание жизненного цикла объектов;
- правила ввода в интерфейсе;
- критерии направления владения;
- самопроверка по метаданным;
- два отдельных шаблона создания.

Проверка по структуре стала простой: `ref/ref_id` означает ссылку, а `arr_id` без `ref` - подчинённую таблицу.

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

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

Ошибка вторая: правило есть, но оно написано не там

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

В документации обычно смешиваются требования разных уровней:

- общие правила проекта;
- ограничения конкретной платформы;
- инструкции для отдельного модуля;
- требования к тестированию;
- исторические пояснения;
- примеры старых решений.

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

Поэтому требования стоит размещать рядом с точкой, где принимается решение. Правило о типах связей должно находиться в инструкции по созданию связей, а не в отдельной главе о структуре базы данных. Требование к формату ответа должно быть рядом с шаблоном задачи. Условие безопасности - непосредственно перед операцией, которая может привести к опасному результату.

Полезно разделять документацию по назначению:

- короткие обязательные правила - в основном файле;
- подробные объяснения и примеры - в базе знаний;
- пошаговые сценарии - в рабочих инструкциях;
- автоматические ограничения - в тестах и проверяющих скриптах.

Так агент получает не только знания, но и правильный порядок их применения.

Ошибка третья: правило не проверяется

Самая дорогая иллюзия в разработке - фраза "все тесты зелёные". Зелёные тесты доказывают только то, что проверяемые сценарии не сломались. Они ничего не говорят о сценариях, которые никто не проверил.

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

Хорошая инструкция должна отвечать не только на вопрос "что делать", но и на вопрос "как доказать, что это сделано правильно".

Подходящая проверка может быть разной:

- unit-тест;
- интеграционный сценарий;
- проверка схемы базы;
- статический анализ;
- тест на метаданные;
- запрет определённой конструкции в коде;
- сценарий приёмки в pull request.

Если требование нельзя проверить автоматически, его следует хотя бы превратить в явный пункт чек-листа.

История с замороженным днём

Самый показательный случай связан с планированием производства. В системе существует замороженный день: после закрытия смены автоматика не должна вносить в него изменения.

Правило было согласовано с заказчиком, зафиксировано в техническом задании и несколько месяцев находилось в документации. Несмотря на это, за четыре дня оно трижды вернулось в виде новых задач:

- тикет #4347: задания были добавлены в замороженный день;
- тикет #4434: ошибки в кнопках "Упорядочить" и "Сгенерировать";
- тикет #4436: вопрос, почему система снова изменила закрытый день.

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

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

Решением стало перемещение проверки на уровень общей операции записи. Теперь любой путь изменения производственного плана проходит через один защитный слой. Дополнительно появились тесты на все публичные действия, способные изменить расписание.

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

Инструкция должна описывать границы системы

Отдельная категория проблем возникает, когда правило действует не всегда, а только при определённых условиях. Например:

- запрещено менять данные после закрытия смены;
- исключение разрешено только для администратора;
- операция допустима при ручном запуске, но не в автоматическом режиме;
- правило распространяется на один тип таблиц, но не на другой.

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

Поэтому для каждого важного правила полезно явно фиксировать:

1. объект, к которому оно относится;
2. момент, когда оно начинает действовать;
3. разрешённые исключения;
4. способ проверки;
5. поведение при нарушении.

Формула "нельзя изменять замороженный день" слабее, чем инструкция: "Любая запись в план производства после закрытия смены запрещена для автоматических операций. Ручное изменение доступно только пользователю с ролью администратора. Проверка выполняется в общем сервисе записи и покрывается интеграционным тестом".

Где агент может улучшать инструкцию сам

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

Если агент нарушил требование, разбор должен завершаться не только исправлением реализации, но и одним из следующих действий:

- уточнением формулировки;
- добавлением правильного примера;
- переносом правила в более заметное место;
- созданием автоматической проверки;
- объединением нескольких разрозненных ограничений в единый механизм.

Так появляется замкнутый контур:

1. агент выполняет задачу;
2. тест или ревью обнаруживает проблему;
3. выясняется, почему инструкция допустила ошибку;
4. правило переписывается;
5. добавляется проверка;
6. следующий аналогичный сценарий уже не повторяет прежнюю ошибку.

В такой системе агент постепенно получает более качественную среду выполнения. Он не "умнеет" в человеческом смысле, но пространство допустимых ошибок становится меньше.

Как составить рабочее правило для агента

Практичный шаблон можно свести к нескольким пунктам:

- Контекст: в какой ситуации применяется правило.
- Цель: какой результат требуется получить.
- Алгоритм: какие шаги нужно выполнить.
- Запрещённые варианты: какие решения исключены.
- Правильный пример: минимальный рабочий образец.
- Проверка: как убедиться, что результат корректен.
- Исключения: когда допускается отступление.
- Точка применения: где именно правило должно срабатывать.

Особенно важно не ограничиваться фразами "не делай так", "избегай", "будь внимательным" и "проверь корректность". Такие формулировки не задают алгоритм и оставляют слишком много пространства для интерпретации.

Лучше писать: "Если выполняется условие X, используй вариант Y; после этого проверь Z. Вариант A не применяй, потому что он приводит к результату B".

Чек-лист для аудита инструкций

Проверка документации занимает около часа, но часто позволяет найти источник повторяющихся ошибок:

- Есть ли в тексте конкретное действие, а не только запрет?
- Можно ли выполнить правило буквально, без догадок?
- Понятно ли, к какой части системы оно относится?
- Указаны ли исключения?
- Есть ли рабочий пример?
- Есть ли автоматическая проверка?
- Находится ли правило рядом с соответствующей операцией?
- Не противоречит ли оно другим документам?
- Не существует ли нескольких мест, где выполняется одна и та же критичная проверка?
- Можно ли превратить требование в тест или статическое ограничение?

Если на большинство вопросов ответ отрицательный, проблема, скорее всего, не в "тупой" модели, а в недостаточно определённом процессе.

Что изменилось после переработки

После перехода от описательных предупреждений к исполнимым правилам стало меньше:

- неверных типов связей;
- повторных исправлений одной и той же функции;
- изменений данных в запрещённых состояниях;
- разночтений между документацией и кодом;
- задач, где агент исправляет только один из нескольких путей;
- ручного объяснения очевидных, но неформализованных ограничений.

Я также перестал считать самые крупные и "умные" модели обязательным выбором. Если инструкция точная, контекст структурирован, а результат проверяется автоматически, более компактная модель часто справляется быстрее и дешевле.

Главный вывод прост: когда агент совершает очевидную глупость, сначала стоит проверить не его способности, а собственную инструкцию. Возможно, правило сформулировано прозой, спрятано не там, содержит только запрет или вообще не имеет проверки. Исправление этих дефектов обычно даёт больший эффект, чем смена модели или очередная попытка придумать идеальный промпт.

Прокрутить вверх