Structured output: почему агенты ломаются без строгих схем
Structured output заставляет модель отвечать по заданной JSON-схеме, а не просто «в формате JSON». Для агентов это разница между рабочим пайплайном и бесконечным парсингом сломанных ответов.

Агент вызывает модель, получает ответ, парсит его как JSON — и падает, потому что модель обернула объект в ```json, добавила фразу «Вот ваш результат:» или поставила запятую там, где её быть не должно. Каждый, кто собирал многошаговый пайплайн на LLM, знает эту боль: одна кривая скобка в одном ответе из тысячи, и весь процесс встаёт. Structured output — механизм, который перекладывает гарантию формата с промпта на движок вывода: модель физически не может выдать текст, не соответствующий заданной схеме.
Что это такое и чем отличается от «попроси JSON в промпте»
Долгое время формат ответа выпрашивали словами: «верни строго JSON, без пояснений». Это работает статистически, а не гарантированно. Модель обучена генерировать правдоподобный текст, и в редких случаях правдоподобным ей кажется markdown-блок или комментарий. Structured output решает задачу иначе — через ограничение генерации на уровне сэмплирования токенов.
Технически это чаще всего constrained decoding: на каждом шаге генерации движок разрешает только те токены, которые не нарушают грамматику схемы. Если по JSON Schema сейчас ожидается закрывающая кавычка или число, токен с буквой просто не попадёт в выборку. Результат — ответ, который всегда валиден относительно схемы. Не «почти всегда», а всегда, если провайдер реализовал механизм честно.
Три уровня строгости
- JSON mode — гарантирует, что ответ будет синтаксически валидным JSON, но не проверяет структуру. Поля могут отсутствовать, типы — не совпадать.
- JSON Schema / Structured Outputs — ответ соответствует конкретной схеме: обязательные поля, типы, enum-значения, вложенность.
- Function calling / tool calling — модель возвращает вызов инструмента с аргументами по схеме этого инструмента. По сути тот же structured output, но встроенный в механику вызова функций.
Почему это критично именно для агентов
Одиночный запрос к чат-боту прощает многое: пользователь сам разберёт кривой ответ. Агент — это цепочка автоматических шагов, где выход одного вызова становится входом следующего. Ошибка формата на шаге три роняет всё, что было построено на шагах один и два, а вы платите за токены каждого повтора.
Посчитайте цену вопроса. Пайплайн из пяти шагов, где каждый шаг парсит JSON с вероятностью успеха 98%. Вероятность, что весь пайплайн пройдёт без ретрая, — примерно 0,98 в пятой степени, около 90%. Каждый десятый запуск требует повтора: лишние токены, лишняя задержка, лишние деньги. Со strict-схемой этот класс ошибок исчезает целиком, и вы возвращаете себе те самые проценты надёжности, которые терялись на парсинге.
Structured output не делает модель умнее. Он делает её предсказуемой — а для агента предсказуемость важнее интеллекта на каждом отдельном шаге.
Где structured output не спасает
Схема гарантирует форму, а не смысл. Модель обязана вернуть поле price типа number — но не обязана вернуть правильную цену. Constrained decoding не защищает от галлюцинаций содержимого, только от мусора в структуре. Второй нюанс: жёсткая схема может подталкивать модель к менее качественным ответам, если формат мешает ей «рассуждать». Отсюда распространённый приём — сначала дать модели поле reasoning в схеме, а уже потом поле с итоговым решением.
Как это выглядит у основных провайдеров
Механизм в том или ином виде есть у большинства крупных провайдеров и в открытых инструментах. Различаются глубина гарантий и способ задания схемы. Возможности API меняются, поэтому конкретные параметры и лимиты сверяйте в актуальной документации провайдера на дату вашей интеграции.
| Подход | Что гарантирует | Как задаётся |
|---|---|---|
| OpenAI Structured Outputs | Строгое соответствие JSON Schema (strict-режим) | response_format с JSON Schema или function calling |
| Anthropic tool use | Аргументы вызова инструмента по схеме инструмента | Описание tool с input_schema |
| Google Gemini | Ответ по заданной схеме ответа | responseSchema / responseMimeType |
| Локальные модели (Outlines, llama.cpp grammars) | Constrained decoding по грамматике или JSON Schema | GBNF-грамматика или JSON Schema на своей инфраструктуре |
Важная оговорка: не каждая функция с названием «JSON» даёт строгую гарантию. Одни провайдеры проверяют только синтаксис JSON, другие — полное соответствие схеме. Перед тем как убрать из кода блок обработки ошибок парсинга, проверьте в документации, что именно гарантирует конкретный режим, а не полагайтесь на название.
Кому это пригодится и кому нет
Structured output нужен не всем и не всегда. Он окупается там, где ответ модели читает не человек, а другой код.
- Мультиагентные пайплайны и цепочки вызовов — здесь это почти обязательно: один сломанный ответ роняет весь процесс.
- Извлечение данных из текста — распарсить резюме, счёт, письмо в заранее известные поля. Классический сценарий, где схема экономит часы отладки.
- Классификация и роутинг — когда нужен строго один из нескольких вариантов, enum в схеме исключает ответы вроде «скорее всего, категория А, но возможно и Б».
- Вызов внешних API из ответа модели — аргументы функции должны совпадать по типам, иначе вызов упадёт.
Кому это скорее мешает:
- Свободный диалог и генерация текста — статьи, письма, ответы поддержки в чате. Схема тут лишний костыль.
- Задачи с длинным рассуждением, где жёсткий формат сбивает модель. Если качество важнее структуры, лучше дать модели свободу, а формат навести отдельным шагом.
- Быстрые прототипы, где проще один раз обработать исключение при парсинге, чем описывать полную схему.
Практика: с чего начать
- Опишите ожидаемый ответ как JSON Schema с обязательными полями и типами. Явно перечислите required-поля — иначе модель может их пропустить.
- Проверьте в документации провайдера, какой режим даёт строгую гарантию схемы, а не только валидный JSON.
- Заложите поле для рассуждения перед полем с итогом, если задача требует логики.
- Даже при strict-режиме оставьте валидацию содержимого на своей стороне: схема проверяет форму, а не факты.
- Сравните качество ответов со схемой и без неё на своих данных. Если строгий формат заметно роняет точность — навешивайте структуру отдельным, более дешёвым вызовом.
Constrained decoding — генерация, при которой на каждом шаге движок разрешает модели выбирать только те токены, что не нарушают заданную грамматику или схему. Так формат ответа гарантируется механикой вывода, а не удачей.
Prompt-инженер: Идеальные запросы для Midjourney, ChatGPT и других моделей.
Спросить за 15 ₽Источники: OpenAI — Structured Outputs (документация), Anthropic — Tool use (документация)
Частые вопросы
Structured output убирает галлюцinations?
Чем JSON mode отличается от JSON Schema?
Structured output снижает качество ответов модели?
Нужно ли теперь убрать обработку ошибок парсинга?
Можно ли использовать structured output с локальными моделями?
Function calling и structured output — это одно и то же?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.