3,583 papers
arXiv:2610.23342 76 16 окт. 2026 г. FREE

SchemaShield-Lite: починка сломанных вызовов инструментов через структурированный отчёт об ошибках

КЛЮЧЕВАЯ СУТЬ
Переименовали поля, переписали описания инструментов, а агент почти не заметил. Зато один новый похожий инструмент в каталоге ломает вызовы: точность в тестах падала, например, с 0,79 до 0,58. Метод SchemaShield-Lite позволяет автоматически чинить сломанные вызовы функций у агента: пустой вызов, забытое поле, не названный инструмент. Код проверяет вызов по схеме и выдаёт модели точный список ошибок, а модель переделывает вызов один раз. Простой повтор запроса даёт лишь +1–2 пункта точности. Короткая «карточка инструмента» в промпте поднимает точность с 0,64 до 0,81 ещё до всякого ремонта.
Адаптировать под запрос
⚡

TL;DR

SchemaShield-Lite — это слой проверки и ремонта вокруг агента с инструментами (function calling, когда модель сама выбирает функцию и заполняет её аргументы). Код проверяет вызов модели по схеме. Если вызов битый, модель получает точный список ошибок и один раз переделывает вызов. Если она не назвала инструмент, ей сначала показывают список доступных и просят выбрать, и только потом чинят аргументы.

Главная боль: после запуска агента интерфейс инструментов меняется. Переименовали параметры, переписали описания, добавили в каталог ещё один похожий инструмент. Точность агента падает, например с 0,79 до 0,58 на тестовом наборе, и модель то не называет инструмент, то забывает обязательные поля. Просто повторить запрос почти не помогает: модель получает тот же вход и делает ту же ошибку. Лучше всего чинит конкретная обратная связь вида «в вызове нет поля X, инструмент Y не выбран». Самый неожиданный вывод: переименования и переписанные описания почти не вредят. Главный вред приносят инструменты-двойники с похожим описанием, то есть разрастание каталога.

Метод двухшаговый. Шаг 1 — валидатор проверяет вызов и формирует отчёт об ошибках. Шаг 2 — модель получает задачу, битый вызов и отчёт и переделывает вызов, причём для ровно того инструмента, который уже выбран.


🔬

Схема метода

ШАГ 0 (профилактика): Компактная «карточка инструмента» в промпте → имя, описание, обязательные поля, типы
ШАГ 1: Модель делает вызов → валидатор (код) проверяет имя, обязательные поля, структуру → отчёт об ошибках
ШАГ 2а: Если имя инструмента не названо → повторный запрос со списком ВИДИМЫХ инструментов → конкретный вызов
ШАГ 2б: Ремонт: задача + битый вызов + отчёт ошибок → модель переделывает вызов для выбранного инструмента (один раз)

Ремонт срабатывает только при невалидном вызове. Это отдельные запросы, а не один промпт.


🚀

Пример применения

Метод сильнее всего там, где вызов инструмента сломан формально: нет имени, нет обязательного поля, не тот тип. Он слабее там, где вызов валидный, но смысл неверный.

Задача: Вы настроили в n8n Telegram-ассистента для интернет-магазина. У него есть инструменты amoCRM: создать_сделку, найти_контакт, добавить_комментарий. Через месяц коллега добавил создать_заявку с почти тем же описанием, а в создать_сделку переименовали поле телефон в phone_number. Агент стал присылать пустые вызовы или путаться между «сделкой» и «заявкой».

Промпт ремонтного шага. Его n8n отправляет модели после того, как проверка (узел IF/Code) нашла ошибку:

Ты исправляешь вызов инструмента для ассистента интернет-магазина.

<Задача>
Диалог с клиентом:
Клиент: «Хочу заказать чехол на iPhone 15, черный, 2 штуки. Меня зовут Игорь, телефон 8-916-555-01-23, доставка в Казань».


<КарточкаИнструмента>
Имя: создать_сделку
Описание: создаёт сделку в amoCRM по подтверждённому заказу клиента
Обязательные поля:
- name (строка) — имя клиента
- phone_number (строка) — телефон клиента
- product (строка) — название товара
- quantity (целое число) — количество
- city (строка) — город доставки


<НевалидныйВызов>
{"tool": "создать_сделку", "arguments": {"name": "Игорь", "телефон": "8-916-555-01-23", "quantity": "две"}}


<ОшибкиВалидации>
1. Отсутствует обязательное поле: phone_number
2. Отсутствует обязательное поле: product
3. Отсутствует обязательное поле: city
4. Поле quantity: ожидается целое число, получена строка «две»
5. Неизвестное поле: «телефон»


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

Результат: модель вернёт один исправленный JSON-вызов для создать_сделку с полями из карточки. Значения она возьмёт из диалога, а число запишет цифрой. Разбора и пояснений не будет, потому что промпт просит только JSON. Если ошибка осталась, следующий узел должен отправить диалог человеку, а не крутить цикл дальше.


🧠

Почему это работает

Слабость. Модель выбирает инструмент и заполняет аргументы только по тексту: описаниям, схемам, списку кандидатов. Когда текст меняется (старые названия полей в примерах, новый похожий инструмент), модель частично опирается на привычный образ. Отсюда пустой вызов, забытое поле, не тот инструмент. Если просто повторить запрос, она получает тот же вход и делает ту же ошибку. Повтор дал лишь +1–2 пункта точности.

Сильная сторона. Если сказать модели, что именно не так, исправить это ей легко. Она хорошо работает по чёткому списку замечаний и умеет достать нужные значения из диалога. Авторы проверили: «ты ошибся, вот список инструментов» (без самих ошибок) тоже слабо помогает. Тянет вперёд структурированный отчёт об ошибках, а не просто знание, что было неверно.

Как метод это использует. Проверка делается детерминированно, без LLM-судьи, и выдаёт конкретику. Ремонт идёт для одного уже выбранного инструмента, поэтому путаница между похожими инструментами не возвращается. А шаг «сначала выбери инструмент из видимого списка» закрывает самый частый сбой, когда имя не названо.

Рычаги управления: - Карточка инструмента в первом запросе работает как профилактика. На BFCL она подняла точность с 0,64 до 0,81 уже без ремонта. В ремонтном промпте её можно убрать: качество ремонта не падает. - Инструкция «выведи все поля из диалога, даже если вызов пуст» критична, когда агент присылает пустой вызов. - Бюджет токенов на ремонт должен быть больше, чем на первый ответ. Авторы подняли его до 512 токенов, потому что на длинных диалогах ремонтный вывод обрезался. - Один ремонт, не цикл. Больше одного круга авторы не проверяли.


📋

Шаблон промпта

Два промпта, как в оригинале: сначала повтор выбора инструмента (если имя не названо), затем ремонт.

Промпт 1. Повтор выбора инструмента (если имя не названо):

<Роль>
Ты выбираешь инструмент для выполнения задачи пользователя.


<Задача>
{диалог_или_запрос}


<ДоступныеИнструменты>
{список_инструментов_с_именем_и_кратким_описанием}


В предыдущем ответе ты не указал имя инструмента. Выбери ОДИН инструмент из списка выше и сформируй конкретный вызов с аргументами. Не придумывай инструменты, которых нет в списке.

Промпт 2. Ремонт вызова:

<Роль>
Ты исправляешь невалидный вызов инструмента.


<Задача>
{диалог_или_запрос}


<КарточкаИнструмента>
Имя: {имя_инструмента}
Описание: {описание}
Обязательные поля и типы:
{список_полей_с_типами}


<НевалидныйВызов>
{исходный_вызов_модели}


<ОшибкиВалидации>
{нумерованный_список_ошибок_валидатора}


Исправь вызов. Выведи ВСЕ обязательные поля из диалога, даже если невалидный вызов был пустым. Используй только поля из карточки. Верни только исправленный вызов в формате {формат_вывода}.

Что подставлять: - {диалог_или_запрос} — исходный контекст без изменений. - {список_инструментов_...} — только те инструменты, которые агент видит сейчас, не весь каталог компании. - {список_полей_с_типами} — из схемы инструмента, только актуальные имена полей. - {нумерованный_список_ошибок_валидатора} — текст ошибок, которые выдаёт проверка: «нет поля X», «поле Y должно быть числом». Не пишите «ошибка в вызове». - {формат_вывода} — JSON или то, что принимает ваша автоматизация.

🚀 Быстрый старт — вставьте в чат:

Вот шаблон ремонта вызова инструмента (SchemaShield-Lite). Адаптируй под мою задачу: [опиши агента и его инструменты].
Задавай вопросы, чтобы заполнить поля.

[вставить шаблон выше]

LLM спросит, какие у агента инструменты, какие у них обязательные поля и как выглядит типичная ошибка. Эти данные нужны, чтобы собрать карточку инструмента и список ошибок валидации. Дальше она возьмёт структуру из шаблона и соберёт готовые промпты под вашу автоматизацию.


⚠️

Ограничения

⚠️ Нужна проверка в коде или автоматизации: сам метод держится на валидаторе, который проверяет имя инструмента и обязательные поля. Без него отчёта об ошибках не будет. В n8n, Make и подобных системах это узел с условием, но его надо собрать.

⚠️ Валидные, но неверные вызовы метод не ловит: если вызов формально корректен, а значение неправильное (не тот товар, не та дата), ремонт не запускается. В тестах таких было мало, но в реальных задачах их может быть больше.

⚠️ Цена в токенах и времени: ремонт добавил примерно треть токенов на одном наборе и почти половину на другом. Ещё около 3,5 с задержки на запрос в среднем. Платишь только при срабатывании проверки, но это 16–32% запросов.

⚠️ Сбои исходного стенда: дрейф в тестах синтетический, придуман авторами. Основные результаты получены на одной небольшой открытой модели (Qwen3.5-9B) с репликой на другой модели того же семейства. Проверки на GPT, Claude, Gemini нет.

⚠️ Не всё чинится: часть случаев остаётся нерешённой, особенно когда модель так и не называет инструмент или упорно не заполняет поля.


🔍

Как исследовали

Авторы взяли два набора тестов для вызова функций: диалоговый DICE-BENCH (300 примеров) и разнородный BFCL (200 примеров). В каждый вносили три вида «дрейфа»: устаревшие примеры в описании, переименованные параметры и лишние инструменты-двойники в списке. Для каждого примера мерили точность три раза: на исходном интерфейсе, на изменённом и после ремонта.

Центральный контроль: а не помогает ли просто вторая попытка? Авторы сравнили ремонт с «повторить тот же запрос» и с «сказать, что вызов неверный, и перечислить инструменты». Точность на DICE: повтор 0,727, список инструментов 0,753, SchemaShield-Lite 0,813. На BFCL: 0,610, 0,625 и 0,795. Вывод: помогает именно отчёт об ошибках, а не сам факт повторной попытки.

Любопытный результат даёт разбор по типам дрейфа. Старые примеры в описании снижали точность всего на 0,013, переименование параметров на 0,007. А один добавленный инструмент-двойник дал падение 0,047, почти весь итоговый ущерб (0,050). Авторы сами называют это уточнением к привычному мнению, что виноваты правки описаний.

Ещё один неожиданный итог: карточка инструмента не нужна на этапе ремонта. Вариант без неё иногда ремонтировал даже лучше (на BFCL 0,820 против 0,795). Зато в первом запросе она работает как профилактика. Ремонт срабатывал без вреда: ни одного исходно правильного вызова он не сломал. Результаты на BFCL: с 0,580 до 0,805, на DICE: с 0,717 до 0,813.


💡

Адаптации и экстраполяции

Это не часть метода авторов, а мои переносы вывода в настройку агента без кода.

🔧 Техника: ремонт вручную в чате или в Cursor/Claude Code → дать точный текст ошибки, а не «попробуй ещё»

Когда агент вызвал инструмент неправильно, вставьте ему сообщение вида:

Твой вызов {инструмент} невалиден. Ошибки:
1. Нет поля {поле}
2. Поле {поле2} должно быть {тип}
Исправь вызов. Выведи все обязательные поля из контекста диалога. Не меняй инструмент.

Идея из статьи: конкретные ошибки + запрет менять инструмент. Саму ручную схему авторы не проверяли.

Правило для инструкции агента (CLAUDE.md, системный промпт), основанное на главном выводе про инструменты-двойники:

Правила работы с инструментами:
- Если два инструмента похожи по описанию, выбирай по условию: {условие_разграничения}.
- Если не уверен, какой инструмент выбрать, назови кандидатов и спроси уточнение, а не вызывай наугад.
- Всегда указывай имя инструмента явно.

Статья показала, что вред несут похожие инструменты в списке. Эти правила проверены не были.


🔗

Ресурсы

  • Работа: Robust Function Calling for LLM Agents Under Interface Drift — Aniruddha Chattopadhyay, Kanishka Halder, Partha Sarathi Roy (независимые исследователи)
  • Код и данные: публичный репозиторий tool-drift (GitHub, AniruddhaChattopadhyay/tool-drift)
  • Бенчмарки: DICE-BENCH, Berkeley Function Calling Leaderboard (BFCL)
  • Связанные работы: Guo et al. (переписывание описаний инструментов), Faghih et al. (чувствительность выбора инструмента к описанию)

📋 Дайджест исследования

Ключевая суть

Переименовали поля, переписали описания инструментов, а агент почти не заметил. Зато один новый похожий инструмент в каталоге ломает вызовы: точность в тестах падала, например, с 0,79 до 0,58. Метод SchemaShield-Lite позволяет автоматически чинить сломанные вызовы функций у агента: пустой вызов, забытое поле, не названный инструмент. Код проверяет вызов по схеме и выдаёт модели точный список ошибок, а модель переделывает вызов один раз. Простой повтор запроса даёт лишь +1–2 пункта точности. Короткая «карточка инструмента» в промпте поднимает точность с 0,64 до 0,81 ещё до всякого ремонта.

Принцип работы

Процесс из трёх шагов, и модель в нём делает только то, что умеет. 1. Модель делает вызов. Обычный код (валидатор) проверяет имя инструмента, обязательные поля и типы. 2. Если имя не названо, модель получает список инструментов, которые агент видит сейчас. Её просят выбрать один. 3. Если вызов битый, модель получает задачу, сам вызов и список ошибок. Она переделывает вызов для уже выбранного инструмента. Модель не угадывает, что сломалось. Ей говорят: нет поля X, поле Y должно быть числом. Это как редактор, который возвращает текст с пометками на полях, а не фразой «переделай, плохо».

Почему работает

Модель выбирает инструмент и заполняет поля только по тексту: описаниям, схемам, списку кандидатов. Текст поменялся, и она частично опирается на привычный образ. Отсюда пустой вызов и путаница между похожими инструментами. Повторный запрос даёт тот же вход, значит, и ту же ошибку. Конкретный список замечаний модель выполняет легко. Значения она сама достаёт из диалога. Авторы проверили и другой вариант: сказать «ты ошибся» и показать список инструментов, но без самих ошибок. Он помогает слабо. Тянет вперёд именно структурированный отчёт об ошибках, а не знание, что ответ был неверным. Ещё два приёма. Проверка идёт кодом, без LLM-судьи, поэтому отчёт точный. Ремонт идёт для одного выбранного инструмента, и путаница с двойниками не возвращается. Мелочь, которая спасает: бюджет токенов на ремонт нужен больше, чем на первый ответ. Авторы подняли его до 512, потому что на длинных диалогах вывод обрезался.

Когда применять

Агенты с инструментами в n8n, Make или своём коде → особенно когда каталог инструментов растёт, а команда добавляет похожие функции. Подходит и когда схемы полей меняются после запуска. Например, в CRM-ассистенте появились «сделка» и «заявка» с почти одним описанием. НЕ подходит, когда вызов формально валидный, а значение неверное: не тот товар, не та дата. Валидатор такое не ловит, ремонт не запустится. Без проверки в коде метод тоже не работает.

Мини-рецепт

1. Собери карточки: для каждого инструмента напиши имя, описание, обязательные поля и типы. Положи их в первый промпт. Это уже даёт прирост без ремонта.
2. Поставь сторожа: после ответа модели добавь узел с кодом. Он проверяет имя инструмента, наличие обязательных полей и типы.
3. Пиши ошибки по делу: «нет поля phone_number», «quantity: ждём целое число, пришла строка». Фразу «ошибка в вызове» не используй.
4. Нет имени инструмента: сначала покажи модели список инструментов, которые агент видит сейчас. Не весь каталог компании. Пусть выберет один.
5. Чини один раз: отправь модели задачу, битый вызов, карточку и список ошибок. Добавь: <инструкция>выведи все обязательные поля из диалога, даже если вызов был пустым.
6. Дай запас токенов: на ремонт ставь около 512, иначе длинный ответ обрежется.
7. Не крути цикл: если после ремонта вызов всё ещё битый, отправь диалог человеку.

Примеры

[ПЛОХО] : Ты ошибся в вызове инструмента. Попробуй ещё раз.
[ХОРОШО] : Исправь вызов инструмента создать_сделку. Ошибки валидации: 1. Нет обязательного поля phone_number. 2. Нет обязательного поля city. 3. Поле quantity: ожидается целое число, получена строка «две». 4. Неизвестное поле «телефон». Выведи все обязательные поля из диалога с клиентом. Используй только поля из карточки инструмента. Верни только JSON. В плохом запросе модель получает тот же вход и повторяет ту же ошибку. В хорошем она видит, что поле телефон переименовали в phone_number. Число «две» она запишет цифрой 2, а город возьмёт из диалога.
Источник: Robust Function Calling for LLM Agents Under Interface Drift
ArXiv ID: 2610.23342 | Сгенерировано: 2026-10-19 08:20

Проблемы LLM

ПроблемаСутьКак обойти
Повтор того же запроса не исправляет ошибкуМодель выдала битый результат: нет поля, не тот тип, пустой вызов. Ты просто отправляешь запрос ещё раз. Вход тот же, поэтому ошибка та же. Фраза «ты ошибся, попробуй снова» тоже почти не помогает. Это касается любого структурированного вывода: JSON, форм, вызовов функцийНе повторяй вслепую. Проверь вывод кодом и покажи модели точный список ошибок. Например: «нет поля phone_number», «quantity должно быть числом». Подробнее в методе ниже

Методы

МетодСуть
Ремонт по списку ошибок от проверки кодом — исправляет битый структурированный выводЧто делать: 1) Проверь ответ модели кодом, без второй модели в роли судьи. Сверь имя, обязательные поля и типы. 2) Если есть ошибки, сделай один новый запрос. Дай в нём задачу, исходный битый ответ, описание нужной структуры и нумерованный список ошибок. 3) Попроси вернуть только исправленный вывод. Запрос: Исправь вызов. Выведи ВСЕ обязательные поля из диалога, даже если прежний вызов был пустым. Используй только поля из описания. Верни только JSON. Почему работает: Исправлять по чёткому списку замечаний модели легко. Она сама достаёт значения из текста диалога. Проверка кодом даёт конкретику, а не «что-то не так». Детали: Давай ремонту больше места на ответ, чем первому запросу. Иначе длинный вывод обрежется. Ремонтируй один раз. Если не вышло, передай человеку, а не крути цикл. Если не названо имя инструмента: сначала дай список доступных инструментов и попроси выбрать один. Потом заполняй аргументы только для выбранного. Так путаница между похожими инструментами не возвращается. Когда да: формальные ошибки, где проверка кодом их видит. Когда нет: вызов выглядит валидным, но значение неверное (не тот товар, не та дата). Проверка такое не ловит. Метод также добавляет токены и задержку на каждый ремонт
📖 Простыми словами

Robust Function Calling forLLMAgentsUnder Interface Drift

arXiv: 2610.23342

Когда API меняется, LLM-агенты моментально сыплются. Модель вызывает инструменты по текстовым описаниям, но стоит переименовать аргумент или добавить похожую ручку, как случается дрейф интерфейса. Нейросеть тупо цепляется за привычные паттерны: шлёт пустой вызов, забывает обязательные поля или путает типы данных. Обычный слепой повтор запроса здесь бесполезен — он даёт жалкие +1–2 пункта точности, потому что модель получает тот же контекст и повторяет ту же фигню.

Это как прийти в госорган со старым бланком, где клерк просто рявкает: "Заполняй заново!". Ты сидишь и гадаешь на кофейной гуще, что именно не так. Нормальный подход — когда тебе молча тыкают маркером: вот здесь пропустил поле, а тут написал текст вместо цифр.

Именно так работает SchemaShield-Lite — защитный слой валидации и быстрого ремонта. Система проверяет сгенерированный вызов по строгой схеме и, если он битый, возвращает модели точный список ошибок ровно на одну переделку. Если агент от перегруза вообще забыл вызвать функцию, его ведут за руку в два этапа: сначала заставляют выбрать имя из списка инструментов и только потом докручивают аргументы функции.

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

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

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с