В цикле · S1E02 Жизненный цикл агента

Цикл вызова инструментов: как модель превращает намерение в действие

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

В цикле — Цикл вызова инструментов. Сезон 1, выпуск 2
Материал к выпуску S1E02 подкаста «В цикле». Открыть на YouTube YouTube подключится после нажатия и получит технические данные браузера. Подробнее

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

Во втором выпуске «В цикле» разбираем этот круг обмена. Он похож у разных провайдеров, но детали формата имеют значение: потерянный идентификатор или неполная история способны сломать даже правильно спроектированную бизнес-логику.

Модель просит, приложение исполняет

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

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

Это разделение полезно для безопасности и отладки. Решение модели можно прочитать отдельно от разрешения приложения, а выполнение — отдельно от итогового ответа пользователю.

Один ход на примере заказа

В учебном сценарии пользователь спрашивает, когда приедет заказ. Приложение уже знает его учётную запись. Модель запрашивает get_order_status, приложение проверяет доступ к указанному заказу и получает ответ системы доставки. Только после этого модель формулирует объяснение.

  1. Передать модели историю и определения доступных инструментов.
  2. Получить ответ и отделить текст от запросов на действия.
  3. Для каждого вызова проверить имя, аргументы, права и оставшийся бюджет.
  4. Исполнить разрешённые действия и сформировать результат для каждого вызова.
  5. Вернуть результаты вместе с нужным состоянием разговора и продолжить цикл.

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

Связывайте результат с вызовом, а не с порядком

Названия элементов в API
APIВызовРезультат и связь
Anthropic Messagestool_usetool_result с tool_use_id
OpenAI Responsesfunction_callfunction_call_output с call_id
OpenAI Chat Completionstool_callsСообщение роли tool с tool_call_id

При параллельном исполнении медленный первый вызов может завершиться последним. Идентификатор сохраняет связь независимо от очередности ответа. Собственный ID элемента в Responses и call_id — разные вещи: для результата нужен именно идентификатор вызова.

У Anthropic результаты клиентских вызовов идут непосредственно после сообщения ассистента с вызовами, блоками tool_result в пользовательском сообщении. У Responses это отдельные элементы входа. Обвязка должна сохранять и остальные необходимые элементы ответа, включая состояние рассуждения там, где этого требует API.

Параллельно — только независимое

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

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

Вызов инструмента — предложение выполнить действие. JSON Schema проверяет форму аргументов, но не право пользователя на заказ и не безопасность операции.

Ошибки должны помогать принять следующий шаг

Сообщение failed почти бесполезно. Лучше различать: объект не найден, доступ запрещён, сервис временно недоступен, превышен лимит. Модель тогда может попросить уточнение, сообщить об ограничении или продолжить другим разрешённым путём.

Не возвращайте внутренние стеки, токены и подробности инфраструктуры. Для исправимой ошибки достаточно безопасного кода и понятного описания. У Anthropic ошибка исполнения отмечается is_error; у других API формат результата определяет ваша обвязка.

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

Каркас цикла без привязки к SDK

пока не исчерпан общий бюджет:
    ответ = запросить модель(история, инструменты)
    сохранить все необходимые элементы ответа
    вызовы = извлечь клиентские вызовы(ответ)

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

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

если бюджет исчерпан:
    вернуть явное состояние незавершённой задачи

Это псевдокод, не готовый пример для конкретного API. В реальной реализации понадобятся отмена, общий дедлайн, журнал выполнения и раздельная обработка клиентских и серверных инструментов. Частично полученные аргументы при стриминге нельзя исполнять до завершения и проверки.

Что должно остаться в трейсе

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

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

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

Источники

Основа — глава 3 материалов «Жизненный цикл агента» и сценарий S1E02. Форматы сверяйте с документацией используемой версии API: