Structured output в n8n: как превратить ответ LLM в надёжный JSON для workflow ¶
Обновлено: 2026-05-29
Короткий ответ ¶
Structured output нужен, когда результат LLM должен идти дальше по workflow: в CRM, таблицу, HTTP API, ticket system, database или approval. Вместо свободного текста модель возвращает JSON по схеме, а n8n проверяет поля, типы, enum, confidence и допустимые действия. Это не “красивый формат ответа”, а контракт между AI-узлом и остальной автоматизацией.
Почему свободный текст ломает workflow ¶
Свободный ответ удобен человеку, но плохо подходит автоматизации. Сегодня модель пишет “приоритет высокий”, завтра “High”, послезавтра “срочно”, а в четвёртом запуске добавляет объяснение до JSON. CRM ждёт одно поле, а получает абзац. IF node сравнивает status, но status приходит на русском, английском или вообще отсутствует. Так появляются тихие ошибки: workflow вроде зелёный, но данные записаны неверно.
Structured output решает эту проблему: вы заранее описываете, какие поля нужны, какие значения допустимы, какие поля обязательны и как downstream nodes должны интерпретировать ответ. В n8n это особенно важно, потому что AI step обычно находится в середине цепочки. После него идут IF, Switch, Merge, HTTP Request, CRM, Google Sheets, Data Table или Webhook response. Каждый следующий шаг должен получать предсказуемую структуру.
Что должно быть в хорошей JSON Schema ¶
Хорошая схема короткая, конкретная и связана с бизнес-действием. Не пытайтесь описать весь мир. Опишите ровно то, что нужно следующему шагу.
Пример для triage тикета:
{
"type": "object",
"additionalProperties": false,
"required": ["category", "priority", "confidence", "summary", "next_action"],
"properties": {
"category": {
"type": "string",
"enum": ["billing", "technical", "account", "sales", "other"]
},
"priority": {
"type": "string",
"enum": ["low", "normal", "high", "urgent"]
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1
},
"summary": {
"type": "string",
"maxLength": 500
},
"next_action": {
"type": "string",
"enum": ["auto_reply_draft", "assign_human", "ask_clarification", "ignore_spam"]
}
}
}
Поля enum важны для стабильности. Если оставить category свободной строкой, модель будет придумывать новые категории. Если downstream workflow не знает эту категорию, данные потеряют смысл.
Архитектура structured-output workflow ¶
- Trigger получает текст или документ.
- Code node нормализует input: очищает HTML, ограничивает длину, добавляет source.
- AI node получает задачу и schema.
- Structured Output Parser возвращает объект.
- Code node проверяет бизнес-условия: confidence, длину, enum, required fields.
- IF/Switch node отправляет item в нужную ветку.
- Low-risk output записывается автоматически.
- High-risk или low-confidence output идёт в human review.
- Audit log сохраняет schema_version, prompt_version, validation_status.
Structured Output Parser не должен быть единственным контролем. Он помогает форматировать ответ, но бизнес-правила лучше проверять отдельно. Например, если priority = urgent, но в тексте нет слов про outage, payment или security, можно отправить в review.
Validation после LLM ¶
Пример Code node:
const item = $json;
const errors = [];
const categories = ['billing', 'technical', 'account', 'sales', 'other'];
const priorities = ['low', 'normal', 'high', 'urgent'];
if (!categories.includes(item.category)) errors.push('invalid_category');
if (!priorities.includes(item.priority)) errors.push('invalid_priority');
if (typeof item.confidence !== 'number' || item.confidence < 0 || item.confidence > 1) errors.push('invalid_confidence');
if (!item.summary || item.summary.length > 500) errors.push('invalid_summary');
if (item.confidence < 0.72) errors.push('low_confidence');
return [{
json: {
...item,
validation_status: errors.length ? 'review' : 'ok',
validation_errors: errors
}
}];
Такой слой нужен даже при хорошей схеме. Он превращает “модель вроде вернула JSON” в “workflow знает, можно ли этому JSON доверять”.
Repair chain: когда чинить, а когда не чинить ¶
Repair chain полезен, если ошибка техническая: лишняя запятая, строка вместо числа, category в другом регистре. Но repair опасен, если проблема смысловая: модель не поняла текст, нет данных, противоречие в источниках, низкая confidence. Не чините смысловые ошибки автоматически. Отправляйте их в fallback или review.
Правило: формат можно ремонтировать, решение — проверять.
Частые ошибки ¶
- Слишком большая схема. Модель путается, поля пустеют, downstream становится хрупким.
- Нет enum. Категории “размножаются”, аналитика ломается.
- Нет additionalProperties false. Модель добавляет поля, которые никто не использует.
- Нет confidence. Нельзя отделить уверенный ответ от догадки.
- Нет schema_version. После изменения схемы старые executions трудно анализировать.
- Schema описывает UI, а не действие. Красивый JSON не помогает workflow принять решение.
- Structured output используется для всех задач. Иногда лучше обычный текст: например, итоговое письмо человеку.
Production-поля, которые часто забывают ¶
Добавьте технические поля:
{
"schema_version": "ticket_triage_v2",
"decision": "assign_human",
"confidence": 0.68,
"requires_review": true,
"evidence": ["клиент сообщил о двойном списании", "нет payment_id"],
"missing_fields": ["payment_id"],
"safe_to_send": false
}
Поля requires_review и safe_to_send помогают не плодить сложные IF nodes. Модель может предложить значение, но финальное решение всё равно должен проверить Code node.
Как тестировать ¶
Соберите dataset минимум из 30 кейсов: обычный запрос, спам, пустой текст, длинный текст, смешанный язык, несколько категорий сразу, angry customer, prompt injection, отсутствующие данные, ложный urgent, вопрос не по теме. Для каждого кейса храните expected category, priority и expected action.
Перед релизом прогоняйте dataset после изменения prompt, schema, модели или RAG. Если accuracy падает или растёт доля review, релиз лучше остановить. n8n evaluations помогают превратить такие проверки в регулярный процесс.
Когда structured output не нужен ¶
Он не нужен для финального human-readable текста, если этот текст никуда не парсится. Он не нужен для простых правил, которые лучше сделать IF node. Он не нужен, если downstream принимает только один вариант действия. Но если результат модели управляет маршрутизацией, записью в систему или финансовым решением — structured output обязателен.
FAQ ¶
Structured output гарантирует правильный ответ?
Нет. Он делает формат предсказуемым, но смысл ответа всё равно нужно проверять через validation, confidence, бизнес-правила и при необходимости human review.
Что лучше: JSON-пример в prompt или JSON Schema?
Для production лучше JSON Schema: она задаёт типы, required fields и enum. Пример можно добавить, но он не заменяет схему.
Нужно ли делать repair chain?
Да, для технических ошибок формата. Но смысловые ошибки, низкая confidence и отсутствие данных лучше отправлять в fallback или review.
Какие поля почти всегда нужны?
schema_version, decision/action, confidence, requires_review, evidence/source, missing_fields и validation_status.
Почему enum важен?
Enum не даёт модели придумывать новые значения. Это критично для Switch/IF nodes, CRM-полей и аналитики.