Разработчик смотрит ответ агента: «отгрузка невозможна, заказ в карантине». В журнале вызовов в том же шаге стоит успешный ship_order. Фраза звучит как отказ, но действие уже произошло.
Текст ответа и вызов функции идут разными путями. Запрет, записанный прозой в описании товара или заказа, агент читает как фон: он может назвать препятствие и всё равно подобрать обход. Пока запрет не попал в схему инструмента готовым значением, модели приходится его выводить.
Учебный пример. Функция чтения возвращает заказ только с полем description: «товар по этой позиции на карантине, отгрузка не проводится до решения кладовщика». Агент пишет «отгрузить нельзя» и вызывает ship_order.
Лучше вернуть те же данные плюс готовые поля, которые не надо интерпретировать:
{"status": "blocked", "can_ship": false, "block_reason": "товар на карантине"}Такой ответ снимает рассуждение: can_ship=false уже стоит в разметке. Но одного поля мало — перед вызовом ship_order нужна проверка на сервере, которая отклонит действие при can_ship=false. Иначе агент может вызвать функцию по другой причине.
Проверять отказ по тексту ответа — ошибка. Прогоните сценарий, где вызов неправомерен, и сверьте журнал вызовов со снимком состояния заказа до и после шага. Срыв засчитан, если вызов прошёл при can_ship=false, что бы агент ни написал.
Разбор