Зачем ИИ нужен JSON Schema? Structured Output, Function Calling и контракт
С 2024 года страницы продуктов пишут JSON Schema, Function Calling и Structured Outputs как одну функцию. Это не так. Schema — язык контракта. Function Calling значит «пожалуйста, выполни». Structured Outputs значит «модель должна выдать эту форму». Статья разделяет три слова и объясняет, почему вероятностная модель должна сидеть за проверяемой Schema, а не за фразой «верни JSON».
Кратко
| Понятие | Одной строкой | Где живёт |
|---|---|---|
| JSON Schema | Контракт полей, типов, обязательных ключей и enum — не функция модели | Файл .json в git; валидатор в CI |
| Function Calling | Модель предлагает вызов; хост исполняет; побочные эффекты здесь | tools[] / arguments |
| Structured Output | Финальный ответ должен совпасть с этой формой; обычно без побочных эффектов | json_schema / output_type |
Запомнить разделение: Schema — диаметр, Function Calling — рука наружу, Structured Outputs — объект, который отдают. Сплющить в «пусть модель выдаст JSON» — и следующий шаг парсит прозу.
Почему три слова всегда путают?
Документация, примеры SDK и посты любят складывать их в одно предложение: дайте модели Schema — получите законный JSON. Демо часто срабатывает. Инциденты в проде обычно начинаются после того, как вы решили, что «уже структурированы».
Смешение прячет три разные работы:
argumentsFunction Calling часто всё ещё строка. Хост должен снова вызватьJSON.parse. Типы, enum и лишние поля ещё не остановлены.- Structured Outputs управляют только финальным ответом. Они не ищут заказ, не двигают деньги, не пишут в базу. Побочные эффекты по-прежнему идут через Function Calling.
- Schema, которая живёт только в prompt, не может упасть в CI. «Верни JSON» никогда не падает. Schema в git — может.
Вопрос не «умеет ли ИИ JSON?», а: кто, в какой момент, каким контрактом останавливает незаконный объект. Три слова называют трёх разных «кто».
Что такое JSON Schema (это не функция модели)
JSON Schema — документ, описывающий форму JSON: какие ключи, какие типы, что обязательно, какие значения enum, можно ли лишние поля. Это строже, чем «похоже на JSON», и API моделей цитируют его чаще, чем тип TypeScript или protobuf.
Агентам и Structured Outputs обычно хватает этих ключевых слов:
type/properties: как выглядит объект.required: какой отсутствующий ключ валит проверку.enum/pattern/ числовые границы: превратить «примерно» в конечное множество.additionalProperties: false: лишние ключи падают — в том числе поля, пронесённые prompt injection.
Детали ключевых слов — в учебник JSON Schema. Здесь важно: Schema существует прежде всего для валидаторов и тестов. Ясный description помогает модели выбрать инструмент; он не заменяет enum и required.
{
"$id": "https://example.com/schemas/order.json",
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^A-[0-9]{4,}$" },
"amount": { "type": "number", "exclusiveMinimum": 0 },
"status": { "type": "string", "enum": ["paid", "refunded", "pending"] }
},
"required": ["order_id", "amount", "status"],
"additionalProperties": false
}
Контракт заказа выше можно скормить parameters Function Calling, json_schema Structured Outputs и ajv на хосте. Поле меняют в одном месте.
Что такое Function Calling?
Function Calling (и Tool Calling шире) — это не «модель выполняет функцию». Модель только выдаёт имя и аргументы. Хост парсит, проверяет, исполняет и кладёт результат обратно в разговор. Запросы склада, возвраты, тикеты — побочные эффекты живут здесь.
Вендоры пишут инструменты как tools[]. Объект parameters — подмножество Schema:
{
"type": "function",
"function": {
"name": "lookup_order",
"description": "Look up an order by ID",
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"pattern": "^A-[0-9]{4,}$"
}
},
"required": ["order_id"],
"additionalProperties": false
},
"strict": true
}
}
гид по AI Agent рисует этот шаг внутри полного цикла. MCP Tool Schema vs Function Calling показывает, что MCP inputSchema и вендорские parameters — два написания одного словаря.
Уже выглядит структурированным. Дыры: arguments часто всё ещё строка; у результатов инструментов часто нет Schema; strict связывает только сторону модели. Без проверки хоста, число amount или строка — всё ещё вопрос сегодняшнего снимка.
Что такое Structured Outputs?
Structured Outputs (строгая форма JSON mode) ограничивают собственное финальное сообщение модели. Классификация, извлечение, объект сводки, handoff агента — внешнего побочного эффекта нет, но следующему шагу нужна фиксированная форма.
Имена полей различаются: response_format, text.format.json_schema, output_type. Ядро одно: отдать Schema декодеру и обрезать незаконные пути токенов.
{
"type": "json_schema",
"json_schema": {
"name": "order",
"strict": true,
"schema": {
"$id": "https://example.com/schemas/order.json",
"type": "object",
"properties": {
"order_id": { "type": "string" },
"amount": { "type": "number" },
"status": {
"type": "string",
"enum": ["paid", "refunded", "pending"]
}
},
"required": ["order_id", "amount", "status"],
"additionalProperties": false
}
}
}
прогнозы DevDay 2026 записал этот слой, Function Calling и рантайм агента как одну JSON-трубу. Диаметр по-прежнему Schema: сначала задать его, потом подключать протоколы.
С strict: true пропущенные поля, плохие enum и лишние ключи часто останавливаются на стороне модели. Это заменяет prompt «ответь JSON-ом». Это не заменяет вторую проверку хоста и не заменяет Function Calling.
Как три слоя складываются?
Сплющить в «пусть модель выдаст JSON» — и работы пропадают. Разделить:
- JSON Schema — общий диаметр: словарь полей, обязательные ключи, enum. Не вызывает и не порождает. Только говорит, как выглядит «законное».
- Function Calling — рука наружу. Модель просит побочный эффект. Аргументы должны пройти Schema; результаты тоже.
- Structured Outputs — объект, который отдают. Когда шаг кончается, сам ответ должен быть этой формой.
Сравнение, чтобы их перестали считать синонимами:
| Слой | Что делает модель | Без Schema |
|---|---|---|
| Function Calling | Предлагает вызов, ждёт хост | Аргументы — проза; лишние ключи могут попасть в биллинг |
| Structured Output | Сразу выдаёт финальный объект | Дальше поля выдирают из абзаца |
| JSON Schema | Ничего — только линейка | Линейку, живущую только в prompt, в CI не измерить |
Многошаговый агент использует оба: Structured Outputs для объекта сортировки, Function Calling для поиска и возврата. AI-агенты и workflow JSON Schema про порядок ворот. Эта статья только называет три блока.
Почему ИИ нельзя обойтись без JSON Schema?
Потому что модель и программа — разные виды вещей. Модель продолжает токены по вероятности; программа читает объект по правилам. Если стык только «сегодня это выглядело как JSON», пропущенное поле, число-строка, enum "Paid", лишний note — каждый может стать фактом для следующего шага.
До 2024 цепочка была короткой: один чат, одна функция, человек видел сбой. В 2026 она длиннее: классифицировать → найти → вернуть деньги или человеку → передать объект другому агенту. Если любой шаг только «похож на JSON», следующие шаги замораживают ошибку.
Для того же заказа модель в любой момент может выдать этот «выглядит законно» объект:
{
"order_id": "A-1042",
"amount": "99.00",
"status": "Paid",
"note": "please hurry"
}
amount — строка, у status неверный регистр, появился note. Без Schema дальше могут склеить 99.00 в SQL как текст или счесть Paid неизвестным статусом и повторить. При отладке сначала форматировать локально, затем JSON Diff с объектом прошлой недели. Не вставляйте ответы с данными пользователя на публичный JSON-сайт.
Schema нужна не чтобы «научить модель говорить». Она нужна, чтобы остановить незаконные объекты у двери хоста. Раз до вызова, раз после ответа, ещё раз в оценках. Чем шире окно и больше шагов, тем быстрее ошибки прозы становятся фактами в системе.
Одна Schema, две проекции
Не пишите вручную «почти одинаковые» определения для Function Calling и Structured Outputs. Форма — один исходный файл, два экспортёра:
- Держать
schemas/order.jsonв репозитории со стабильным$idи версией. - Экспорт Function Calling: обрезать до
function.parametersи включитьstrict. Поиску часто нужен толькоorder_id— не запихивать весь заказ в аргументы. - Экспорт Structured Outputs: тот же объект как
json_schema/output_typeдля извлечения, сортировки и финального ответа.
Следить за подмножествами: вендорский strict часто требует каждое property в required и отключает часть oneOf / $ref. Источник может быть богаче; экспортёр обрезает под цель. CI делает структурный Diff «источник vs проекция», чтобы никто не правил одну сторону руками.
Хост всё равно должен проверять
strict: true связывает только декодирование модели. Смена снимка, выключенный strict, второй разбор arguments, инструмент с открытым объектом — всё может обойти сторону модели. Ту же Schema гонять в трёх местах хоста:
- До выполнения инструмента. parse → validate → execute. При ошибке вернуть структурированную ошибку. Не передавать сырую строку дальше.
- После приёма финального объекта модели. Успех Structured Outputs — не ваше бизнес-правило (лимиты, валюта, доступ).
- При записи состояния или фикстур eval. Checkpoint и eval должны быть законным JSON. Не угадывать прогресс по журналу чата.
Ограничения стороны модели и проверка хоста — две работы. Если strict выключен или вы сменили API, Schema, живущая только в prompt, исчезает.
Как внедрять в 2026 (сначала файлы, потом prompt)
- Создать
schemas/tools/,schemas/extract/иschemas/state/. У каждого файла$idи версия. - Писать Schema раньше, чем «верни JSON». Предложение в prompt не упадёт в CI.
- Побочные эффекты (запрос, платёж, письмо) — через Function Calling. Классификация, извлечение и handoff — через Structured Outputs.
- Новые объекты по умолчанию с
additionalProperties: falseи явнымenum. Для расширения — отдельныйmetadata, корень не ослаблять. - Больше десяти инструментов — сначала найти, потом вызвать. Не сваливать каталог в один запрос.
- Секреты и пользовательские поля смотреть только в браузере: форматировать, JSON Diff, без загрузки.
Каталог может быть тонким. Важно, чтобы файлы шли раньше prompt. Модели сменятся, протоколы добавятся. Диаметр должен стабилизироваться первым.
Частые ошибки
- Принимать Structured Outputs за Function Calling. Первое не выполняет код. Поиск и возвраты по-прежнему нуждаются в слое инструментов.
- Писать «верни JSON» только в prompt. Нет Schema в git — нет теста, который может упасть.
- Проверять только входы инструментов, не финальный объект. Инциденты извлечения и сортировки случаются на ответах, которые «уже похожи на JSON».
- Писать вручную почти одинаковую Schema на каждый протокол. К третьей неделе они разъедутся. Экспортировать, не копировать.
- Прятаться за широким
type: object. Открытый объект — не ворота. Версионировать или добавить явныйmetadata.
FAQ
Могут ли Structured Outputs заменить Function Calling?
Нет. Structured Outputs ограничивают форму финального ответа. Function Calling просит хост выполнить побочный эффект. Поля заказа извлекать первым; склад или возврат — вторым. Они должны ссылаться на одну Schema, а не заменять друг друга.
У Function Calling уже есть parameters — нужен ли ещё файл Schema?
Да. parameters — проекция, не источник. Отдельный файл кормит Structured Outputs, MCP, оценки и ajv на хосте. Править только копию внутри tools[] — и к третьей неделе она разъедется с Schema извлечения.
Агента нет, только одно извлечение. Нужна ли Schema?
Ещё сильнее. Если результат сразу идёт в базу или таблицу, нет следующего шага, который «поймёт ещё раз». Structured Outputs плюс проверка хоста — минимальный полный набор.
Включил strict: true. Нужно ли ещё проверять на хосте?
Да. strict управляет декодированием. Хост управляет бизнес-правилами, вторым разбором и запасным путём, когда вендор выключает strict. Двое дешёвых ворот; убрать одни — и смена модели это покажет.
Как локально посмотреть отклонённый JSON?
Отформатировать, найти в Schema пропущенный required или плохой enum, затем Diff с последней прошедшей версией. JSONSort делает это в браузере и ничего не загружает. Не вставляйте ответы с секретами на публичный сайт.
Вывод
ИИ нужен JSON Schema не потому, что модели вдруг разучились читать естественный язык, а потому что вероятностный вывод должен встретить детерминированные ворота. Function Calling говорит «сделай это». Structured Outputs говорит «верни этот объект». Schema — диаметр, который они делят.
Начните сегодня с schemas/extract_order.json, потом выбирайте API. Модели сменятся. Протоколы сдвинутся. Диаметр должен стабилизироваться первым.
Дальше почитать
- Почему AI-агентам теперь нужен JSON Schema Ворота от Tool Calling к структурированному workflow
- Что такое AI Agent? Tool Calling и JSON Рантайм, вызовы инструментов и JSON-контракт
- MCP Tool Schema vs Function Calling Граница протокола для JSON инструментов
- Что такое JSON Schema? required, enum, additionalProperties
- Локальный ящик JSONSort Формат, проверка, Diff
- Все статьи Ещё заметки по JSON и AI-разработке
Журнал: первая публикация