﻿---
title: "Где ломается обвязка: шесть категорий сбоев"
description: Диагностическая таксономия поломок вокруг модели — оркестрация, ретраи, retrieval, описания инструментов, контекст, валидация вывода — и кейс дрейфа состояния на длинных задачах.
---

## Зачем нужна таксономия

Диагностика начинается не с чтения кода, а с вопроса: **к какому классу относится сбой**. В большинстве продакшен-систем, где агент «работает нестабильно», поломка попадает в одну из шести категорий ниже. Если сбой опознан, исправление стоит несколько часов инженерного времени, а не удвоенного счёта за инференс.

Таксономия не заменяет разбор конкретной системы: ландшафт сбоев меняется от проекта к проекту. Она задаёт порядок проверки гипотез.

## Шесть категорий

| Категория | Типичные проявления | Что проверить |
|---|---|---|
| **Оркестрация и поток управления** | Агент не знает, когда остановиться; рекурсия в вызовах инструментов | Терминальные условия, бюджет шагов, защита от повторного вызова |
| **Ретраи и обработка ошибок** | Тихие повторы; ретрай на неретраябельной операции; ошибка не доходит до модели | Разделение transient и структурных ошибок, логирование попыток |
| **Retrieval** | Не тот документ; мусор в top-k; контекст «плывёт» между ходами | Баланс релевантности и точности, чанки, реранкинг, изоляция ходов |
| **Описания инструментов** | Модель выбирает не тот инструмент или путает аргументы | Пересечение семантики, недоспецифицированные параметры, отсутствие примеров |
| **Управление контекстом** | Накопление шума, деградация к концу задачи, утечка между сессиями | Стратегия сжатия, размер окна, границы сессии |
| **Валидация вывода** | Битый JSON, тихое превращение ошибки в пустой результат | Проверка схемы, verbose-ошибки, возврат ошибки агенту |

Разберём каждую подробнее, потому что «проверить» в таблице легко сказать и трудно сделать.

### Оркестрация

Цикл агента должен иметь явное условие остановки и бюджет: максимум шагов, максимум стоимости, максимум повторов одного инструмента. Без этого рекурсия «вызвал инструмент → получил ошибку → вызвал его же» выглядит как работа, пока не закончится лимит или деньги.

Отдельный случай — отсутствие терминального состояния. Модель объявляет задачу выполненной, когда цель не достигнута: соединения не созданы, файл не записан, запись не обновлена. Это не проблема генерации, а проблема контракта «что считается завершением».

### Ретраи

Ретраи опасны тем, что делают сбой менее наблюдаемым. Ошибка уходит в лог обвязки, наружу возвращается успешный ответ с испорченным побочным эффектом.

- **Тихие ретраи** не информируют остальную систему: состояние изменилось, а агент об этом не знает.
- **Ретраи на неретраябельных операциях** — например, повторная отправка платежа после таймаута.
- **Нет различения ошибок.** Ошибка валидации требует исправления аргументов, а не повтора того же вызова; `permission denied` не пройдёт никогда.

### Retrieval

Самый частый источник «галлюцинаций»: модель отвечает по неверному контексту и делает это уверенно и логично. Типичные причины — перекос в сторону релевантности без точности, чанки, смешивающие несвязанный контент, отсутствие реранкинга и загрязнение контекста между ходами, когда результаты прошлого запроса попадают в следующий. Подробнее — [Поиск и reranking](https://wpcraft.ru/kb/ai/rag/retrieval.md).

### Описания инструментов

Описание — это контракт, который читает модель. Если два инструмента семантически пересекаются, выбор между ними становится лотереей. Если параметр недоспецифицирован (`date` вместо `date_iso_8601`), модель заполняет его правдоподобно, но неверно. Отсутствие примера использования усиливает обе проблемы.

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

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

### Валидация вывода

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

## Принцип: наблюдать, а не выводить

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

```text
плохо:  агент помнит, что сделал  → планирует по памяти
хорошо: обвязка читает состояние  → агент планирует по факту
```

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

## Кейс: дрейф состояния на длинных задачах

Агент генерировал визуальный код в Unreal Engine — Blueprint-графы, Material и Niagara. На задачах длиннее 15–20 операций над нодами completion rate обрушивался: агент пересоздавал уже созданные ноды, соединял пины несуществующих нод, объявлял задачу готовой без ключевых соединений.

**Первая гипотеза** — лимит контекста. Более длинное окно и суммаризация в середине задачи не сдвинули долю ошибок.

**Фактическая причина** — представление модели о графе было трассой вызовов инструментов, а не актуальным состоянием. Частично отработавший вызов, неожиданный побочный эффект, вмешательство ретрая — и расхождение накапливалось ход за ходом. К двадцатому ходу модель планировала по графу, которого уже не существовало. Более сильная модель не помогала: вход на каждом шаге был неверным.

**Исправление** — перед каждым ходом агенту передаётся актуальное структурированное состояние графа. Стоимость — около 330 дополнительных токенов на ход (медиана на задачах средней сложности во внутреннем бенчмарке).

**Результат** — completion rate на длинных задачах вырос с 26.3% до 87.9%; ошибки пересоздания нод и галлюцинации пинов упали почти до нуля; медианная длина решения сократилась с 30+ ходов до 7. Проценты взяты из внутренних прогонов и не обобщаются на другие системы; значим здесь механизм, а не цифры.

## Второй сбой того же класса: неформальный контракт типов

Инструмент соединения пинов принимал типы как произвольные строки. Модель выдавала «Boolean», «Bool», «bool» вперемежку. Все варианты проходили валидацию, а несовпадения типов всплывали только на ручном ревью.

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

## Как превратить это в проверку

Таксономия становится полезной, когда каждый класс сбоя получает повторяемую проверку:

- **state-consistency** — сравнение того, на что опирается агент, с фактическим состоянием после серии действий;
- **retry/error propagation** — искусственная инъекция `validation error`, `permission denied`, `not found` с проверкой поведения;
- **structured output** — прогон задач с ожидаемой схемой и обязательным видимым провалом парсера;
- **длинные сценарии** — отдельный набор задач на 20+ шагов, где деградация проявляется.

Готовый минимальный набор — в [Покомпонентных evals](https://wpcraft.ru/kb/ai/evals/component-evals.md).

## Что проверить в проекте

- **Есть ли бюджет шагов и стоимости.** Без него цикл не остановится сам.
- **Отличимы ли ретраи от успеха в трассе.** Если нет, сбой не диагностируется.
- **Тестируется ли retrieval отдельно от генерации.** Иначе причина «неверного ответа» неизвестна.
- **Однозначны ли описания инструментов.** Проверьте каждый контракт изолированно.
- **Передаётся ли агенту фактическое состояние.** Особенно там, где система stateful.

## Материалы и источники

- [Почему ломается ваш AI-агент — и почему смена модели обычно его не чинит](https://habr.com/ru/articles/1039292/) — Артем Тарасов, таксономия и кейс Kismet
- [Evals для чайников. Как тестировать AI-агента](https://habr.com/ru/articles/1042924/) — Артем Тарасов, state-consistency eval
- [Anthropic: Demystifying evals for AI agents](https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents)