Что показывает корпус
Корпоративные отчёты об агентах в продакшене сходятся к узкому набору сбоев, и большинство из них — не сбои модели. Это сбои интерфейса. Одно и то же трение проявляется в остальном несвязанных развёртываниях:
- Инструменты возвращают неструктурированный успех. Ответ вроде
{"status": "ok"}или голый HTTP 200 с человекочитаемым телом оставляет агенту самому выводить, действительно ли произошёл предполагаемый эффект. - Частичный сбой скрыт. Пакетная операция, обработавшая одни элементы и пропустившая другие, сообщает об успехе, потому что транспорт succeeded.
- Одно намерение требует многошагового ритуала. Создание ресурса означает вызов эндпоинта создания, опрос эндпоинта статуса, затем вызов эндпоинта финализации. Каждый вызов — шанс остановиться на полпути, и промежуточные состояния нигде не смоделированы в описании инструмента.
- Повторы выполняются против эндпоинтов, которые никогда не сигнализируют терминальное состояние. Отчёты об инцидентах описывают агентов, зацикливающихся на вызове, который продолжает возвращать ошибку, выглядящую временной, потому что ничто в ответе не отличает «попробуй ещё раз» от «это никогда не сработает».
Паттерн последователен: поверхность инструмента просят нести семантику, которую она никогда не была предназначена выражать. Агент не столько ведёт себя неправильно, сколько завершает единственную интерпретацию, которую допускает интерфейс.
Заблуждение обёртки
Обёртывание существующего человеческого API в JSON-схему не создаёт поверхность инструмента. Оно создаёт удалённый вызов процедуры с тонким описанием. Схема говорит модели, какие поля отправлять; она почти ничего не говорит о том, что означает вызов, когда он допустим или что данный ответ подразумевает о мире.
Человеческие API рассчитаны на читателя, который может компенсировать недостающую информацию. Такой читатель может вывести намерение из окружающего контекста, спросить коллегу, что означает код состояния, или заметить, что результат выглядит устаревшим, и разобраться. Ни один из этих путей восстановления не существует для агента, работающего внутри цикла. Когда интерфейс неоднозначен, единственная доступная стратегия агента — угадывать, повторять или отказаться, и все три дорого стоят в продакшене.
Подход с обёрткой также импортирует предположения, которые не выживают при переводе. Человеческий API может рассматривать 200 с телом ошибки как соглашение, известное всем в команде. Он может рассматривать пустой список как либо «нет результатов», либо «запрос был некорректным», потому что человек проверил бы. Он может оставлять деструктивные операции неидемпотентными, потому что человек не нажал бы кнопку дважды. Каждое из этих решений разумно для человеческого вызывающего и является дефектом для машинного вызывающего.
Вместо этого агентам нужна поверхность с явными предусловиями, явными постусловиями и терминальной таксономией ошибок. Предусловие утверждает, что должно быть истинно до того, как вызов допустим. Постусловие утверждает, что будет истинно после успешного вызова. Терминальная таксономия ошибок утверждает, какие сбои можно повторить, какие являются постоянными и какие требуют совершенно другого вызова.
Один вызов инструмента — одно намерение

Вызов инструмента должен выражать одно намерение. Если для достижения одной цели требуется последовательность вызовов без возможности возобновления, поверхность провоцирует частичное завершение и неоднозначные повторы. Там, где многошаговый процесс неизбежен, моделируйте промежуточные состояния явно и делайте каждый переход полноценной операцией с собственными предусловиями, а не прячьте их за ритуалом, который вызывающий должен выполнить правильно.
Каждый ответ — одно из трёх
Каждый ответ должен классифицироваться как успех, повторяемый сбой или терминальный сбой. Четвёртого состояния нет. Неоднозначный ответ вынуждает вызывающего изобретать политику, и изобретённые политики — источник штормов повторов. Конкретно это означает конверт ответа с небольшим замкнутым набором видов исхода и правило, что неизвестные виды исхода рассматриваются как терминальные сбои, а не повторяются.
Полезный механизм — конверт ответа с явным дискриминантом исхода и ограниченной подсказкой повтора:
{
"outcome": "retryable_failure",
"reason": "upstream_unavailable",
"retry_after_ms": 2000,
"observed_state": null
}
Важно не конкретное имя поля, а то, что вызывающий может ветвиться без интерпретации. terminal_failure означает остановиться и вывести ошибку. retryable_failure означает повторить в указанной границе. success означает, что постусловие выполнено.
Деструктивные операции идемпотентны по ключу
Деструктивные операции должны быть идемпотентны по ключу, чтобы повторы были безопасны по построению. Вызывающий предоставляет стабильный ключ идемпотентности, производный от намерения, и поверхность возвращает тот же результат для повторного ключа, а не выполняет эффект дважды. Это устраняет необходимость для агента рассуждать о том, приземлилась ли предыдущая попытка, — именно в этом рассуждении он хуже всего.
Ответ должен возвращать наблюдаемое состояние вместе с заявленным исходом, чтобы вызывающий мог проверить, а не доверять. Если инструмент утверждает, что ресурс был создан, он должен вернуть текущее наблюдаемое состояние ресурса. Тогда проверка становится сравнением, которое агент может выполнить, а не убеждением, которое он должен держать. Это также делает обнаруживаемым успех с устаревшими данными: заявленный исход и наблюдаемое состояние расходятся.

Честные компромиссы
Эти правила не бесплатны. Явные конверты исходов делают ответы больше, что потребляет контекст и может вытолкнуть описание инструмента за точку, где модель надёжно его учитывает. Ключи идемпотентности требуют серверного состояния и окна хранения, что является операционными накладными расходами для команд, у которых их раньше не было. Разделение ритуала на явные возобновляемые операции порождает больше инструментов, а больше инструментов означает больше неоднозначности выбора для вызывающего. Вопрос проектирования не в том, платить ли эти издержки, а в том, где режим отказа хуже без них. В большинстве продакшен-систем неоднозначный повтор дороже большего ответа.
Последствия для оценки
Если проблема в поверхностях инструментов, то корректность вызова инструмента — неправильная метрика, если оценивать только завершение задачи. Прогон, который завершает задачу, повторяя через терминальный сбой, не является корректным прогоном; это прогон, которому повезло с поверхностью, которая не смогла сообщить. Оценка должна разделять два измерения:
- Отображение намерения в вызов. Выбрал ли агент правильный инструмент с правильными аргументами для заявленного намерения, включая случаи, когда правильное поведение — не вызывать ничего?
- Обработка класса сбоя. Для каждого класса сбоя, который поверхность может выдать, ответил ли агент правильной политикой: повторить в границе, остановиться и вывести или переключиться на другой вызов?
Это означает, что регрессионные наборы нуждаются в состязательных ответах инструментов как полноценных фикстурах, а не как случайных экспериментах с хаосом. Четыре, которые важнее всего: медленный успех, частичный успех, молчаливый сбой и успех с устаревшими данными. Каждый проверяет своё предположение:
- Медленный успех проверяет, различает ли политика тайм-аута агента задержку и сбой.
- Частичный успех проверяет, читает ли он наблюдаемое состояние, а не заявленный исход.
- Молчаливый сбой проверяет, проверяет ли он вообще постусловия.
- Успех с устаревшими данными проверяет, сравнивает ли он временные метки или версии вместо доверия к ответу.
Поверхность, которая не может выдать эти ответы в тестовом стенде, — это поверхность, чьи режимы отказа неизвестны, пока они не появятся в продакшене. Создание фикстур — часть создания интерфейса.
Заключение
Поверхности инструментов — это задача проектирования интерфейса. Подход с обёрткой рассматривает интерфейс как слой перевода поверх существующего человеческого API и наследует каждое предположение, которое этот API делал о читателе, способном компенсировать. Проектирование для машинного вызывающего означает сделать предусловия, постусловия и терминальную семантику ошибок явными и принять связанные с этим издержки. Альтернатива — система, чьи сбои неотличимы от её успехов, пока кто-нибудь не прочитает логи.
