AI / LLM
Tool calls: построй устойчивый цикл tool calling
Читать про галлюцинированные id и runaway-циклы — не то же самое, что построить цикл, который их переживает. Собери реальный tool-calling-агент против tools, которые лгут, виснут и падают — и докажи, что он остаётся корректным, ограниченным и дешёвым, с доказательствами на каждом шаге.
Преврати ментальную модель юнита в переиспользуемый каркас: цикл tool use, который валидирует по схеме и авторизует каждый аргумент, тайм-боксит и ретраит каждый tool, ограничивает итерации и ловит повторы, и возвращает каждый сбой как tool_result, из которого модель может восстановиться.
Построй цикл tool calling production-уровня вокруг любой чат-модели с tool use (Claude или OpenAI-совместимый function-calling API). Он должен исполнять многошаговую задачу против минимум трёх tools — включая один мутирующий, гейтящийся авторизацией tool — и оставаться корректным, ограниченным и осознающим стоимость, когда tools возвращают галлюцинированные аргументы, виснут или падают.
- Тест, где модели скармливают (или провоцируют на) галлюцинированный order_id: цикл отвергает его на проверке авторизации/существования, возвращает tool_result с ошибкой, и модель восстанавливается — мутирующий эндпоинт ни разу не срабатывает на плохом id. Покажи логи.
- Тест, где один tool виснет: per-tool timeout срабатывает, возвращает tool_result с ошибкой, и цикл продолжается или изящно выходит — ход никогда не стопорится бесконечно.
- Тест, где модель застревает, повторяя один падающий вызов: cap итераций и/или repeat-detection останавливает её в пределах MAX_STEPS и возвращает изящный отказ пользователю — зафиксированная стоимость остаётся ограниченной.
- Измерение латентности до/после для двух независимых вызовов, показывающее, что параллельный путь быстрее последовательного, с корректно сопоставленными id у tool_result.
- Короткий разбор: три слоя валидации, где живёт каждый guard, политика ретраев (и почему мутирующий tool исключён), и потокеновые числа/число вызовов за ход.
- Добавь on-call runbook: как читать логи цикла (вызовов модели за ход, токены, какой guard сработал), топ режимов сбоя (галлюцинированный аргумент, зависание, runaway) и фикс для каждого.
- Добавь режим structured output: форсируй один именованный tool (tool_choice: tool), чтобы извлечь JSON гарантированной формы, и сопоставь его надёжность с парсингом свободной прозы.
- Добавь prompt caching на блок tools и измерь реальное снижение входной стоимости и time-to-first-token на многошаговом прогоне.
- Добавь budget guard, прерывающий ход, когда суммарные токены или вызовы модели превышают потолок на запрос, возвращая изящный частичный результат — оборона против токенового DoS вроде allocation-атаки.
Это цикл, который ты будешь гонять в каждом реальном агенте: управляй им по stop_reason, считай каждый аргумент tool недоверенным входом (валидируй по схеме, затем authorize и existence-check до любой мутации), возвращай все сбои как tool_result, чтобы модель само-исправлялась, тайм-боксь и выборочно ретраь tools, и ограничь всё это capом итераций и repeat-detection. Параллель независимые вызовы, кэшируй статичный блок tools и логируй вызовы и токены. Построив это однажды против tools, которые лгут, виснут и падают, ты делаешь production-версию мышечной памятью.