JSON Schema превращает структуру JSON в машинно читаемый контракт для моделей, инструментов, API и тестов. В статье мы сравниваем сценарии Structured Output, Function Calling и MCP, объясняем ограничения OpenAI, Gemini и Claude, а также показываем, почему для продакшена нужна внутренняя основная схема и отдельные адаптеры.
Модель возвращает корректный JSON, но приложение всё равно падает: отсутствует обязательное поле, пришёл неверный тип или появился неизвестный статус.
Быстрое решение: JSON Schema для AI Agent нужно использовать как машинно читаемый контракт между моделью, исполнителем инструмента, API и тестами. Для OpenAI, Gemini, Claude и MCP не следует без проверки переносить одну и ту же сложную схему: надёжнее хранить внутреннюю основную схему и отдельные адаптированные версии.
Эта статья рассчитана на три группы специалистов:
- разработчиков AI Agent, которым нужны стабильные ответы и параметры инструментов;
- платформенных инженеров, переносящих один сценарий между несколькими моделями;
- тестировщиков, строящих автоматическую проверку схем и регрессионную совместимость.
JSON Schema превращает JSON в контракт
Обычный JSON описывает конкретный набор данных. Он не объясняет приложению, какие поля обязательны, какие значения допустимы и что произойдёт при появлении неизвестного свойства.
Например:
{
"order_id": "A-1042",
"status": "paid",
"amount": 149.90
}
Человек понимает смысл объекта. Исполнителю API нужны дополнительные правила:
order_idдолжен быть строкой;statusможет принимать только разрешённые значения;amountдолжен быть числом;- все три поля должны присутствовать;
- лишние поля должны быть разрешены или запрещены явно.
JSON Schema фиксирует эти ограничения:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/order-result",
"type": "object",
"properties": {
"order_id": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["pending", "paid", "cancelled"]
},
"amount": {
"type": "number",
"minimum": 0
}
},
"required": ["order_id", "status", "amount"],
"additionalProperties": false
}
В чём разница между JSON Schema и обычным JSON? JSON — экземпляр данных. JSON Schema — описание правил, которым экземпляр должен соответствовать. Валидный JSON может быть синтаксически правильным, но не соответствовать контракту. Например, поле amount может прийти строкой, а status — со значением, которого нет в перечислении.
В официальном руководстве JSON Schema описаны базовые типы, свойства объектов, обязательные поля и ограничения на структуру данных. В проекте также полезно указывать $schema и $id, чтобы связывать документ с конкретной версией контракта. Руководство по основам JSON Schema
Для AI Agent схема решает четыре прикладные задачи:
- ограничивает форму ответа модели;
- позволяет проверить аргументы до запуска инструмента;
- делает формат API-пакета предсказуемым;
- даёт тестам единый объект для автоматической проверки.
Но JSON Schema не подтверждает, что данные правдивы. Она может проверить, что order_id является строкой. Она не знает, существует ли такой заказ, принадлежит ли он текущему пользователю и разрешена ли операция.
Structured Output ограничивает форму ответа
Структурированный ответ нужен там, где результат модели сразу поступает в код: при извлечении реквизитов, классификации, маршрутизации, генерации объектов интерфейса и подготовке данных для следующего шага агента.
Типичный поток выглядит так:
- приложение отправляет запрос и описание ожидаемой структуры;
- модель формирует объект;
- клиент разбирает JSON;
- валидатор проверяет соответствие схеме;
- бизнес-логика проверяет смысл данных;
- приложение передаёт результат дальше.
OpenAI Structured Outputs использует формат ответа на основе JSON Schema. В официальной документации отдельно указано, что строгий режим работает с поддерживаемым подмножеством схемы. Поэтому наличие ключевого слова в стандарте не означает, что оно будет принято конкретным режимом API. JSON mode, в свою очередь, решает задачу корректного JSON, но сам по себе не гарантирует соответствие нужной структуре. Документация OpenAI по Structured Outputs
Gemini Structured Output также работает с ограниченным набором возможностей JSON Schema. Документация Google перечисляет поддерживаемые типы и основные свойства, но не обещает реализацию всех конструкций стандарта. В частности, сложную схему с глубокими ссылками, условными ограничениями и комбинациями подтипов нельзя автоматически считать переносимой. Документация Gemini по структурированному выводу
Почему корректный JSON всё ещё может быть непригоден для приложения? Потому что синтаксис и контракт — разные уровни проверки. Объект может успешно распарситься, но содержать строку вместо числа, пропущенное поле или неизвестное значение перечисления.
Даже успешная проверка схемы не подтверждает бизнес-данные:
{
"date": "2026-02-31",
"order_id": "A-1042",
"amount": 999999999
}
Типы здесь могут быть правильными. Но дата не существует, заказ может отсутствовать, а сумма может выходить за пределы политики компании.
Рабочая цепочка должна выглядеть так:
Ответ модели
↓
Разбор JSON
↓
Проверка JSON Schema
↓
Проверка авторизации
↓
Проверка существования ресурсов
↓
Проверка бизнес-правил
↓
Вызов API или инструмента
Если пропустить последние уровни, разработчик легко примет структурированный, но недостоверный объект за безопасную команду.
Function Calling использует схему параметров
В Function Calling схема обычно описывает не финальный ответ, а аргументы инструмента.
Пример для инструмента создания счёта:
{
"type": "object",
"properties": {
"customer_id": {
"type": "string",
"description": "Идентификатор клиента"
},
"currency": {
"type": "string",
"enum": ["USD", "EUR"]
},
"amount": {
"type": "number",
"minimum": 0
}
},
"required": ["customer_id", "currency", "amount"],
"additionalProperties": false
}
Модель получает имя инструмента, описание и схему. Затем она предлагает вызов с аргументами. Само приложение решает, выполнять ли его.
Почему вызову инструмента нужна Schema? Без неё модель вынуждена угадывать имена полей, типы и допустимые значения. Она может вернуть валидный JSON, который не понимает исполнитель: например, использовать customer вместо customer_id, передать сумму строкой или выбрать неизвестную валюту.
Google в документации Function Calling разделяет объявление функции и фактическое исполнение: модель возвращает имя функции и аргументы, а код приложения запускает функцию и передаёт результат обратно. Документация Gemini по Function Calling
Claude Tool Use применяет поле input_schema для описания параметров инструмента. Anthropic также уделяет внимание описанию назначения инструмента и отдельных аргументов. Это важно для выбора инструмента: схема ограничивает форму данных, а текстовое описание объясняет модели, когда инструмент применять. Документация Claude по определению инструментов
После получения вызова исполнитель должен выполнить минимум шесть проверок:
- имя инструмента входит в разрешённый список;
- аргументы соответствуют схеме;
- пользователь имеет необходимые права;
- указанные ресурсы существуют;
- операция разрешена текущим состоянием объекта;
- повторный запуск не приведёт к двойному списанию или другой побочной операции.
Важно: JSON Schema не выдаёт разрешения. Если в схеме есть поле
user_id, модель не получает право выбирать любого пользователя. Значение нужно сопоставлять с текущей сессией и политикой доступа на стороне исполнителя.
Поле description тоже не следует считать защитным механизмом. Оно помогает модели лучше выбрать инструмент, но не заменяет авторизацию, ограничения на пути к файлам, проверку владельца ресурса и журналирование действий.
MCP связывает схемы входа и выхода
Model Context Protocol переносит контрактную модель на уровень протокола инструментов.
В описании MCP-инструмента используются:
name— имя;description— назначение;inputSchema— правила входных параметров;outputSchema— необязательное описание результата;structuredContent— структурированный результат выполнения.
inputSchema помогает клиенту понять, какие аргументы можно отправлять. outputSchema задаёт ожидаемую форму результата. structuredContent позволяет передавать данные следующему компоненту не только как свободный текст.
Какую роль выполняют inputSchema и outputSchema в MCP? Первая схема защищает входную границу инструмента. Вторая документирует и проверяет выходную границу. Это снижает количество ручного разбора между сервером инструмента, клиентом и AI Agent.
Официальная спецификация MCP описывает инструменты, входные схемы и структурированный результат. Если сервер объявляет outputSchema, клиенту рекомендуется проверять полученные данные перед дальнейшим использованием. Спецификация MCP Tools
При этом роли нельзя смешивать:
- MCP описывает публикацию и вызов инструмента;
- JSON Schema описывает форму входа и выхода;
- модель выбирает инструмент и предлагает аргументы;
- клиент или сервер принимает решение о фактическом выполнении.
Предложения по расширению MCP рассматривают более широкое применение JSON Schema 2020-12 для inputSchema, outputSchema и structuredContent. Но предложение по развитию протокола не равно обязательному поведению всех клиентов и серверов. При внедрении нужно фиксировать версию спецификации и возможности конкретной реализации. Предложение MCP по JSON Schema 2020-12
Совместимость платформ требует адаптеров
Поддерживают ли OpenAI, Gemini и Claude полную JSON Schema? Нет, такой вывод делать нельзя. Корректнее говорить о поддержке определённого подмножества в конкретном интерфейсе, режиме и версии API.
Для первичной оценки используйте следующий список:
- OpenAI Structured Outputs: подходит для строгого структурированного ответа, но требует соблюдения ограничений конкретного режима.
- Gemini Structured Output: подходит для простых объектов и массивов, однако заявленная поддержка является ограниченной.
- Function Calling: хорошо описывает аргументы инструментов, но не заменяет проверку исполнителя.
- Claude Tool Use: использует
input_schemaи подробные описания инструментов. - MCP Tools: применяет
inputSchema, а при необходимостиoutputSchemaиstructuredContent. - Единый контракт: возможен только после проверки общего подмножества и поведения каждого адаптера.
Наиболее рискованно переносить без теста:
- сложные
oneOf,anyOfиallOf; - глубокие или рекурсивные
$ref; - конструкции
if,thenиelse; - необычные комбинации ограничений строк и чисел;
- корневые массивы и примитивные значения;
- неодинаковое поведение
additionalProperties; - схемы с большим количеством необязательных и взаимоисключающих полей.
Для общего слоя разумнее начать с объектов, строк, чисел, массивов, required, enum и items. Когда минимальная версия стабильно проходит проверки, можно добавлять более сложные ограничения отдельными итерациями.
Решающий список для выбора архитектуры
Отметьте пункты, которые соответствуют вашему проекту:
- [ ] Ответ модели сразу читает программный код, а не человек.
- [ ] Инструмент изменяет данные, деньги, права или состояние ресурса.
- [ ] Один сценарий должен работать у двух и более провайдеров.
- [ ] Схема содержит
enum, массивы, ссылки или строгие ограничения. - [ ] Результат инструмента передаётся следующему агенту как структурированные данные.
- [ ] Команда обязана обнаруживать несовместимые изменения до выпуска.
- [ ] В проекте есть CI/CD для повторной проверки моделей и API.
Выбирайте архитектуру по количеству отмеченных пунктов:
- 0–1 пункт: достаточно базовой JSON Schema и локальной проверки ответа.
- 2–3 пункта: разделите схему ответа и схему аргументов инструмента, добавьте бизнес-валидацию.
- 4–5 пунктов: храните основную схему и отдельные адаптеры под OpenAI, Gemini, Claude или MCP.
- 6–7 пунктов: добавьте версионирование, отрицательные примеры, матрицу совместимости и обязательный регрессионный запуск в CI/CD.
Этот список — не формальный стандарт. Его задача — быстро определить, когда простая схема превращается в отдельный инженерный актив, которым нужно управлять как кодом.
Основная схема и версии адаптеров
Можно ли использовать одну JSON Schema напрямую на всех платформах? Иногда — для небольшого объекта из базовых типов. Для сложного доменного контракта — только после преобразования и автоматической проверки.
Мы рекомендуем хранить три уровня:
- основную внутреннюю схему доменной модели;
- адаптер для OpenAI;
- адаптеры для Gemini, Claude и MCP.
Пример структуры:
schemas/
order-result/
1.2.0/
canonical.json
openai.json
gemini.json
claude.json
mcp.json
examples/
conversion-notes.md
В файле с правилами преобразования нужно фиксировать:
- исходную версию;
- целевую платформу;
- интерфейс: Structured Output, Function Calling или MCP;
- удалённые и заменённые ключевые слова;
- правила обработки обязательных полей;
- поведение неизвестных свойств;
- дату последней проверки;
- версию модели и API;
- причину несовместимости, если адаптер отличается от оригинала.
Пошаговый процесс внедрения:
- Описать доменную модель независимо от провайдера.
- Добавить
$schema,$id, версию и примеры. - Выделить общий минимальный набор конструкций.
- Сгенерировать адаптер под конкретный интерфейс.
- Запустить положительные и отрицательные тесты.
- Отправить адаптированную схему в реальный API.
- Проверить фактический ответ модели.
- Проверить исполнителя инструмента.
- Сохранить результат в CI/CD.
- Оставить возможность отката на предыдущую версию.
Добавление необязательного поля обычно проще для совместимости, чем изменение типа существующего поля. Переименование, удаление, изменение enum и превращение необязательного свойства в обязательное нужно рассматривать как потенциально несовместимые изменения.
Бизнес-проверки идут вторым уровнем
JSON Schema отвечает на вопрос «имеет ли объект допустимую форму». Бизнес-валидация отвечает на вопрос «можно ли доверять этому объекту в текущей операции».
В продакшене нужны как минимум три слоя.
Проверка формы
Она проверяет:
- корректность JSON;
- тип корневого объекта;
- наличие обязательных полей;
- типы значений;
- разрешённые элементы перечислений;
- допустимость дополнительных свойств.
Проверка доменной модели
Она проверяет:
- существует ли заказ;
- принадлежит ли ресурс текущему пользователю;
- доступна ли операция;
- не превышена ли сумма;
- допустим ли переход между статусами;
- не устарела ли версия объекта.
Проверка безопасности
Она проверяет:
- имеет ли агент право вызвать инструмент;
- разрешено ли действие роли пользователя;
- можно ли использовать указанный путь;
- требуется ли подтверждение;
- безопасно ли повторить операцию.
Например, схема может объявить path строкой. Это не делает безопасным значение ../../secrets.env. Схема проверяет тип, но не знает разрешённый каталог и политику доступа процесса.
Практическое правило: результат валидации схемы следует передавать бизнес-валидатору, а не сразу в платёжный, административный или файловый API.
Регрессионные тесты для AI Agent
Для каждой схемы мы советуем подготовить набор случаев:
- полностью валидный объект;
- пропущенное обязательное поле;
- неправильный тип;
- неизвестное значение
enum; - лишнее свойство;
- пустой массив;
- минимальное допустимое значение;
- значение за пределами диапазона;
- конфликтующие поля;
- устаревшая версия контракта.
В отчёте полезно разделять статусы:
schema_accepted
model_output_parsed
schema_validation_passed
business_validation_passed
tool_authorized
tool_executed
Так команда видит точную границу ошибки. API мог принять схему, но модель могла вернуть отказ. JSON мог соответствовать схеме, но заказ мог не существовать. Инструмент мог быть выбран правильно, но пользователь мог не иметь разрешения.
В журнале теста нужно сохранять:
- имя и версию модели;
- используемый API;
- дату запуска;
- отправленную адаптированную схему;
- входной пример;
- результат проверки;
- текст ошибки;
- версию протокола MCP, если используется MCP-инструмент.
Не стоит строить регрессию на неопределённом «последнем» релизе модели. При изменении поведения провайдера это затруднит поиск причины. Фиксированная версия и повторяемый набор примеров дают намного более полезный сигнал.
Для команд, которые запускают такие проверки в macOS-зависимой CI/CD-цепочке, удалённый Mac может стать отдельным исполнительным узлом. Но сначала нужно стабилизировать схемы и адаптеры. Перенос неустойчивого теста на удалённую машину не исправит отсутствие контрактов.
Если нужен временный macOS-узел для автоматизации и интеграционных проверок, можно изучить аренду Mac в облаке. При чувствительности к задержке между тестовым узлом и внешними API дополнительно сравните облачные Mac в США и облачные Mac в Сингапуре.
Рабочее решение для новой системы
Наш порядок выбора простой:
- для JSON-ответа в интерфейс — Structured Output;
- для вызова API — отдельная схема аргументов инструмента;
- для MCP —
inputSchemaи, если результат передаётся дальше как данные,outputSchema; - для нескольких провайдеров — основная схема и адаптеры;
- для денег, ресурсов и прав — схема плюс бизнес- и security-валидация;
- для изменений контракта — регрессионный прогон до публикации.
Главная ошибка — считать JSON Schema разрешением на выполнение операции. Это контракт формы. Он делает обмен данными предсказуемее, но не подтверждает реальность, права и бизнес-допустимость значений.
Текущий подход «одна схема в коде, ручные исключения и тесты на случайной машине» имеет несколько реальных недостатков: несовместимое изменение обнаруживается поздно, разные модели требуют локальных исправлений, результаты сложно сравнивать, а интеграционные тесты зависят от окружения. Для краткосрочной матрицы проверок, macOS-зависимых CI/CD-задач и интеграционных запусков аренда Mac у ZekVPS может быть удобнее покупки отдельного устройства: не нужно заранее приобретать оборудование, постоянно поддерживать его включённым и выделять рабочее место под временный тестовый узел. Для постоянной круглосуточной нагрузки или задач с физическими интерфейсами собственный Mac может оказаться рациональнее.
Начните с основной схемы, отрицательных примеров и автоматического отчёта совместимости. После этого подключайте удалённый Mac как воспроизводимый исполнитель CI/CD, а не как замену отсутствующей архитектуре.
Перенесите AI-разработку на выделенный Mac от ZekVPS
Арендуйте полноценный Mac mini M4 bare-metal с macOS и правами администратора для тестирования моделей, API и инструментов автоматизации.
Используйте SSH для сценариев CI/CD и VNC для удалённой работы в графической среде без ограничений общей виртуальной машины.
Чтобы перевести MCP или Agent из демо в ежедневную работу, сначала зафиксируйте облачный Mac со снимками. Смотреть тарифы ZekVPS Mac mini — Разделите лабораторию и рабочий стол — деплой станет спокойнее.