Почему Tool Calling AI-агентов зависит от JSON Schema: ошибки параметров, типов и валидация

Почему Tool Calling использует JSON Schema как контракт, как классифицировать ошибки параметров и типов в arguments, и pipeline валидации с ajv, strict mode и обратной связью модели.

Более ранние публикации в этой серии подготовили почву: эволюция схемы JSON, вызова функций и MCP объясняет, почему они существуют; Поток данных JSON от вызова инструмента к трассировке MCP, где перемещаются байты; станет ли JSON Schema стандартным агентским контрактом, охватывающим конвергенцию экосистемы. Эта статья посвящена практическому вопросу: почему вызов инструмента почти неизбежно зависит от схемы JSON и как классифицировать и проверять ошибки параметров и типов.

Когда модель выбирает инструмент и заполняет параметры, хост не может «полагаться на удачу» — перед выполнением он должен быстро отработать ту же схему. Один галлюцинированный аргумент может удалить данные, отправить неправильное электронное письмо или отравить следующий ход. Итог: JSON Schema — единственный контракт параметров, понятный как API-интерфейсам модели, MCP, так и средам выполнения хоста; проверять после синтаксического анализа и перед выполнением и возвращать структурированные ошибки для повторной попытки.

Почему вызов инструмента зависит от схемы JSON

Вызов инструмента (тот же поток данных, что и вызов функции) означает: модель выбирает инструмент и выводит аргументы JSON, соответствующие контракту. Три стороны должны договориться:

  • Model APIs: OpenAI, Gemini, and Anthropic Tools APIs describe parameters with JSON Schema; some vendors also constrain decoding with Schema.
  • MCP: each Tool’s inputSchema is JSON Schema; Hosts often pass it through or trim to a subset when mapping to model APIs.
  • Хост-программы: нужны машиночитаемые, версионные и проверяемые CI контракты — ajv, Python jsonschema и т. д., которые на порядки превосходят «формат JSON в командной строке».

Without Schema, hosts regex-parse or prompt-parse arguments—that breaks at Agent scale. Schema gives shape (which fields), types, and constraints (enum, minimum, pattern)—everything you need syntactically before calling HTTP/DB/MCP. Business rules (“does priority=high violate SLA?”) still need code; Schema blocks most hallucinations at the syntax layer.

User intent → model reads JSON Schema in tools[]
           → outputs tool_calls[].function.arguments (JSON string)
           → host JSON.parse + Schema validate
           → only then call MCP / HTTP / DB

Три места, где Schema находится в цепочке вызовов

ЭтапРоль схемыТипичный отказ
Регистрация инструмента (инструменты/список MCP)Сообщает модели, какие инструменты существуют и какие аргументы им нужны.Неверная схема, несоответствие черновика, вводящее в заблуждение описание.
Вывод модели (tool_calls.arguments)Ограничивает сгенерированный параметр JSONОтсутствуют обязательные, неправильные типы, придуманные поля
Результат инструмента (сообщения)Необязательно: ограничить форму результата перед контекстом.Ответ не в формате JSON, дрейф поля

Vs. Structured Output: Structured Output constrains the final user-facing JSON reply; Tool Calling Schema constrains execution parameters. You can share one Schema source (Pydantic / Zod), but validate Tool arguments on every tool_calls before execute.

Ошибки параметров: отсутствуют, лишние, неправильные имена, синтаксис.

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

ОшибкаПримерКлючевое слово схемысмягчение последствий
Отсутствует обязательноеSchema needs title, args only have priorityrequiredОтправить ошибку обратно; уточнить обязательно в описании
Дополнительные поляModel invents urgent: trueadditionalProperties: falseOpenAI часто применяет строгие меры; в противном случае снимите или отклоните
Неправильное написание ключаtitel vs titleproperties keysПоследовательное именование; сильные описания
Синтаксис JSONЗавершающая запятая, одинарные кавычки(слой разбора)JSON.parse сначала; Структурированный вывод уменьшает синтаксические ошибки
Пустые аргументы{} but Schema has requiredrequired, minPropertiesZero-arg tools: explicit properties: {}
// Schema fragment
{
  "type": "object",
  "properties": {
    "ticket_id": { "type": "string", "description": "Ticket ID" },
    "note": { "type": "string" }
  },
  "required": ["ticket_id"],
  "additionalProperties": false
}

// Model output (missing ticket_id) → validation fails
{ "note": "Please handle ASAP" }

Ошибки типов: несоответствия, перечисление, вложение, приведение.

Ошибки типа: поля существуют, но тип или формат JSON значений нарушает схему:

ОшибкаПримерОбщая причина
Примитивный типlimit: "10" should be numberМодели часто преобразуют числа в строки.
нарушение перечисленияpriority: "urgent", enum is low/medium/highВ описании не указаны допустимые значения
Вложенный массив/объектExpected tags: [], got stringСхема слишком сложна для подмножества модели.
строка форматаemail fails format: emailГаллюцинированные форматы электронной почты или дат
один из/любой изПолиморфный аргумент не соответствует ни одной веткеСлишком сложная схема для целевого API

Coercion: some validators coerce "10" to 10. In production Agents, prefer coercion off—silent fixes hide systematic drift. If you must coerce, document it and lock behavior in CI samples.

// Type error example
Schema: { "limit": { "type": "integer", "minimum": 1, "maximum": 100 } }
Model:  { "limit": " fifty " }  // string, not numeric → fail

Проверка: синтаксис, аргументы, строгий режим

1. Проверьте саму схему

Before registering tools, meta-validate parameters / inputSchema (draft 2020-12, etc.). JSON Toolbox in the browser works locally—don’t ship invalid Schema to model APIs.

2. Подтвердить аргументы против схемы

After JSON.parse(arguments), validate with the same Schema used at registration:

  • JavaScript / TypeScript: ajv (mind draft and strict options)
  • Python: jsonschema, Pydantic (model_validate after JSON parse)
  • Генератор кода: Zod / Pydantic → Схема JSON с одним исходным кодом

3. Строгий режим поставщика

OpenAI strict: true requires a stricter subset (e.g. all objects with additionalProperties: false). That reduces model-side errors but does not replace host validation—dialects differ by vendor; see the Contract article.

4. CI на основе выборки

Для каждого инструмента: действительные образцы аргументов + преднамеренные сбои в CI. Изменения схемы нарушают изменения API — устанавливайте их версии.

Сквозной конвейер и обратная связь об ошибках

Минимальный конвейер (расширяет статью о потоках данных):

1. tools/list or static register → validate each inputSchema syntax
2. On tool_calls → JSON.parse(arguments)
   ├─ parse fail → tool message "JSON syntax error: …" → model retry
   └─ parse ok → ajv/jsonschema validate
        ├─ fail → structured errors (missing, type, enum) → feed back
        └─ ok → execute + optional business rules
3. Tool result → optional result Schema before append to messages
4. Log: schema version, raw arguments, error codes (no secrets)

Error feedback must be machine-readable: “ticket_id is required” beats “bad params, retry”. Many frameworks format validation errors as JSON in the tool role for self-correction.

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

Практические рекомендации

  • Единый источник схемы: Pydantic / Zod → MCP inputSchema + инструменты OpenAI.
  • Описания — это подсказки: они управляют перечислением и обязательным соответствием — просматривайте схему так же, как код API.
  • Простая схема, строгая проверка: обрезать глубину oneOf/$ref до целевого подмножества API; быстро выходит из строя, никаких тихих исправлений.
  • Две обязательные контрольные точки: после Tool_calls перед выполнением; после возврата MCP перед контекстом (если результаты подаются в модель).
  • Сначала проверьте локально: вставьте схему + примеры аргументов в JSON Toolbox перед производством.
  • Отдельно от структурированного вывода: ответ пользователя. Схема и схема инструментов — не объединяйте.

FAQ

Может ли вызов инструмента пропустить схему JSON и использовать естественный язык для параметров?

Прототипы да; номер производства Естественный язык не может быть отказоустойчивым или CI-версией; в моделях отсутствуют поля и типы дрейфа. Основные API и MCP по умолчанию используют схему.

Аргументы — это строка или объект?

Большинство API-интерфейсов завершения чата используют строку JSON — затем выполняется проверка JSON.parse. Некоторые новые API возвращают объекты; в любом случае подтвердите с помощью той же схемы.

Сколько попыток при неудачной проверке?

Часто 1–3 со структурированной обратной связью по ошибкам, затем уточняйте или переходите на более высокий уровень. Бесконечная повторная попытка сжигает жетоны и может зацикливаться на галлюцинациях.

ajv против Пидантика?

Хосты узла/TS: ajv напрямую в схеме JSON. Python с моделями Pydantic: генерируйте Schema + model_validate во время выполнения. Тот же источник, что и схема, ориентированная на модель.

При включенном строгом режиме проверка на хосте все еще выполняется?

Да. строгий уменьшает ошибки модели; он не предотвращает грязные результаты MCP, дрейф схемы/кода или нарушения бизнес-правил.

Как проверить схему и аргументы локально?

Вставьте схему и образец JSON в JSON Toolbox — проверка локально в браузере, ничего не загружается.

Резюме и следующие шаги

Вызов инструмента зависит от схемы JSON, поскольку это общий контракт проверяемых параметров для моделей, MCP и хостов. Классифицировать ошибки параметров (отсутствующие, лишние, неправильное имя, синтаксис) и ошибки типов (типы, перечисления, вложенность); перехватывать перед выполнением и передавать структурированные ошибки для самоисправления.

Далее: выберите один реальный инструмент (например, создание билета), напишите схему + действительные/недействительные образцы, проверьте локально в JSON Toolbox, затем подключите агента. Порядок серий: эволюция → поток данных → контракт → эта статья (проверка).