Guías de IA · 13 min de lectura

Structured Outputs explicados: cómo los LLM devuelven JSON válido

Structured Outputs ajusta las respuestas de los LLM a JSON Schema. Compara JSON mode y tool calling y conoce los límites de OpenAI, Claude y Gemini.

Ilustración de una corriente dispersa de partículas luminosas que atraviesa un molde geométrico transparente y sale en filas ordenadas de bloques de colores

Structured outputs es una función de las LLM API que obliga a la respuesta de un modelo a ajustarse al JSON Schema que se le proporciona. Mediante decodificación restringida, la API compila el esquema en una gramática o máquina de estados que limita la generación de tokens y evita errores de sintaxis y campos ausentes en las API de OpenAI, Anthropic y Google.

¿Qué son Structured Outputs en una LLM API?

Structured outputs en una LLM API restringe los tokens generados por un modelo para que la respuesta completa coincida con un JSON Schema proporcionado por el desarrollador. Anthropic y Google describen el mecanismo subyacente como decodificación restringida: antes de comenzar el muestreo, la API compila el esquema en una gramática o máquina de estados finitos que excluye cualquier token siguiente que infrinja la estructura, los nombres de las claves o los tipos de valores del esquema.

Sin structured outputs, pedir a un modelo de lenguaje en un prompt que responda en JSON no funciona de forma constante en producción. La documentación de Anthropic destaca cuatro fallos comunes cuando se depende solo de las instrucciones del prompt: errores de análisis por sintaxis JSON no válida, campos obligatorios ausentes, tipos de datos incoherentes e infracciones del esquema que requieren gestión de errores y reintentos. En la práctica, estos fallos se parecen a los siguientes ejemplos generales:

  • Errores de análisis por sintaxis JSON no válida: Por ejemplo, las llaves sin cerrar, las comas finales o el texto Markdown alrededor de los datos pueden hacer fallar un analizador JSON.
  • Campos obligatorios ausentes: Por ejemplo, un modelo puede omitir una clave que espera el código posterior de la aplicación.
  • Tipos de datos incoherentes: Por ejemplo, un campo numérico puede llegar como cadena o puede llegar un único valor en lugar de un array.
  • Infracciones del esquema que requieren gestión de errores y reintentos: Por ejemplo, las claves no solicitadas o los valores fuera de rango obligan a usar bucles de reintento y código de validación defensiva.

La decodificación restringida elimina la necesidad de instrucciones de formato contundentes en el prompt. Para mantener los tipos de la aplicación alineados con el esquema que se envía a la API, OpenAI y Google ofrecen herramientas nativas del SDK que aceptan clases Pydantic BaseModel en Python y objetos Zod en JavaScript, mientras que el SDK de Python de Anthropic acepta un modelo Pydantic mediante client.messages.parse() y analiza la respuesta en ese tipo.

¿En qué se diferencian Structured Outputs de JSON mode y del JSON solicitado solo mediante prompt?

Structured outputs garantiza el cumplimiento exacto de tu JSON Schema, mientras que JSON mode y las instrucciones basadas solo en prompts no pueden imponer nombres de propiedades concretos, estructuras anidadas ni campos obligatorios.

JSON mode fue el paso intermedio anterior a las restricciones completas del esquema. En OpenAI, activar JSON mode mediante { "type": "json_object" } garantiza que el modelo produzca JSON sintácticamente válido, siempre que la solicitud no encuentre un caso límite, como quedarse sin tokens de salida a mitad de un objeto. Sin embargo, la documentación de OpenAI establece advertencias explícitas: debes incluir una instrucción para producir JSON en algún punto del contexto de la conversación; de lo contrario, la API devuelve un error si falta la palabra JSON y, en caso contrario, el modelo puede generar un flujo interminable de espacios en blanco hasta alcanzar el límite de tokens.

OpenAI presenta structured outputs como la evolución de JSON mode y recomienda usar structured outputs siempre que sea compatible, reservando JSON mode para modelos antiguos como gpt-4-turbo y anteriores.

Característica JSON solo con prompt JSON mode Structured Outputs
Sintaxis JSON válida garantizada No Sí, salvo truncamiento Sí, salvo rechazo o truncamiento
Impone el esquema y los tipos exactos No No Sí
Requiere una instrucción JSON en el prompt Sí Sí, OpenAI la exige No
Elimina reintentos por formato No Parcialmente Sí, para la estructura del esquema
Análisis nativo con Pydantic y Zod Manual Manual Compatible con los SDK de los proveedores

Structured Outputs frente a Function Calling: ¿cuándo usar cada uno?

Structured outputs da formato a la respuesta final del modelo para tu aplicación o usuario final, mientras que function calling conecta el modelo con herramientas, API y fuentes de datos externas durante la ejecución.

Los desarrolladores suelen confundir ambas funciones porque las dos se basan en definiciones JSON Schema. OpenAI y Google establecen la misma frontera arquitectónica:

  • Usa structured outputs cuando quieras dar un formato claro al mensaje final del asistente para tu interfaz, base de datos o flujo posterior, por ejemplo para extraer datos o realizar una clasificación estructurada.
  • Usa function calling (tool use) cuando el modelo necesite solicitar una acción, consultar registros en tiempo real o invocar una rutina del backend antes de terminar de responder. Para profundizar en cómo encajan las definiciones de herramientas en los protocolos modernos, consulta nuestra guía de tool calling y MCP.

OpenAI ofrece esquemas estrictos de dos formas distintas: function calling con esquemas estrictos al conectar el modelo con herramientas o datos, y un formato de respuesta json_schema al estructurar la respuesta al usuario. Anthropic separa sus dos funciones en output_config.format para la respuesta final de Claude y strict: true en herramientas individuales para garantizar nombres de herramientas y argumentos de entrada válidos, y admite expresamente el uso de ambas en una sola solicitud. Combinar las dos resulta especialmente práctico en flujos de trabajo de agentes de IA, donde las llamadas intermedias a herramientas y el resumen final deben seguir contratos estrictos.

Cómo implementan Structured Outputs OpenAI, Anthropic y Google

En noviembre de 2026, OpenAI, Anthropic y Google implementan structured outputs mediante compilación de esquemas, aunque difieren sus parámetros de solicitud, las palabras clave de JSON Schema admitidas y los límites de complejidad.

Proveedor Cómo activarlo Herramientas de esquema del SDK Reglas destacadas del esquema Límites destacados
OpenAI Responses API text.format o Chat Completions response_format con type: "json_schema" y strict: true Pydantic BaseModel (Python), Zod (JS) La raíz debe ser un objeto, no anyOf; todos los campos en required; additionalProperties: false obligatorio; claves emitidas en el orden del esquema Hasta 5.000 propiedades, 10 niveles de anidamiento, 120.000 caracteres entre nombres/enums, 1.000 valores enum
Anthropic Claude output_config.format con type: "json_schema", más strict: true en herramientas client.messages.parse() con Pydantic (Python) Admite $ref/$defs, anyOf y allOf (con límites); additionalProperties: false obligatorio; sin límites numéricos ni de longitud de cadena Máximo 20 herramientas estrictas, 24 parámetros opcionales, 16 parámetros de unión, tiempo límite de compilación de 180s; caché de gramática de 24 horas
Google Gemini API Configuración de respuesta con tipo texto, mime_type: "application/json" y esquema Pydantic (Python), Zod (JS) Admite minimum/maximum, minItems/maxItems, prefixItems; elimina silenciosamente los límites no admitidos Los esquemas grandes o muy anidados fallan con 400 INVALID_ARGUMENT

OpenAI

OpenAI admite structured outputs a partir de GPT-4o y recomienda gpt-6-astra para proyectos nuevos. Llamar a la API con strict: true y una palabra clave no admitida como allOf, not, if/then/else, dependentRequired o dependentSchemas devuelve un error en lugar de fallar silenciosamente. OpenAI admite formatos de cadena como date-time, time, date, duration, email, hostname, ipv4, ipv6 y uuid, además de límites numéricos (minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf) y límites de arrays (minItems, maxItems).

Anthropic Claude

Anthropic admite structured outputs en todos los modelos de la Messages API, aunque no dentro de Managed Agents. Al usar client.messages.parse() en el SDK de Python, las restricciones no admitidas como minimum, maximum, minLength y maxLength se trasladan automáticamente a las descripciones de los campos para que Claude vea la intención, y el SDK valida localmente los datos devueltos frente al modelo Pydantic original.

Claude guarda las gramáticas compiladas en caché durante 24 horas desde el último uso; cambiar la estructura del esquema o el conjunto de herramientas invalida esa caché de gramática, pero editar nombres o descripciones de campos no. Como Claude también recibe un prompt de sistema automático que explica el formato JSON, el número de tokens de entrada aumenta ligeramente y cambiar output_config.format invalida la caché de prompts de la conversación. Las propiedades obligatorias se emiten primero, seguidas de las opcionales. Structured outputs funciona con streaming, recuento de tokens y Batch processing (con el descuento del 50 por ciento de Anthropic). Sin embargo, combinar salidas JSON con Citations devuelve un error 400 y structured outputs es incompatible con el rellenado previo de mensajes.

Google Gemini API

Google destaca la extracción de datos, la clasificación estructurada y los flujos de trabajo con agentes como principales casos de uso de structured outputs de Gemini. A diferencia de OpenAI y Anthropic, Gemini elimina e ignora silenciosamente varias palabras clave sin generar un error, entre ellas minLength, maxLength, minProperties, maxProperties, uniqueItems, contains, minContains y maxContains. Siempre debes ejecutar Pydantic model_validate_json() o Zod .parse() sobre las respuestas de Gemini para aplicar esas restricciones en el código de la aplicación. Si Gemini devuelve 400 INVALID_ARGUMENT por un esquema demasiado complejo, Google aconseja aplanar los anidamientos, reducir los campos opcionales o enums, acortar los nombres de propiedades y trasladar las reglas no estructurales a las descripciones de los campos.

Cómo diseñar un JSON Schema fiable para LLM

Un JSON Schema fiable para structured outputs de LLM mantiene una estructura plana, marca los campos como obligatorios y usa tipos que admiten null en lugar de claves opcionales. Diseñar esquemas en torno a reglas compartidas entre proveedores ayuda a evitar errores de compilación y rechazos inesperados durante la ejecución.

Usa esta lista antes de poner en producción un esquema para OpenAI, Claude o Gemini:

  1. Mantén poco profundo el anidamiento: Aplana los objetos muy anidados cuando sea posible para quedar muy por debajo del límite de 10 niveles de OpenAI y evitar rechazos de compilación de Gemini o Claude.
  2. Haz obligatorio cada campo: Incluye cada clave de objeto en required, ya que OpenAI aplica estrictamente esta regla y Claude limita a 24 el total de parámetros opcionales por solicitud.
  3. Usa uniones que admitan null para los datos ausentes: Representa los valores opcionales con "type": ["string", "null"] en lugar de omitir claves de required.
  4. Restringe los objetos: Establece "additionalProperties": false en cada definición de objeto, como exigen tanto OpenAI como Anthropic.
  5. Restringe las opciones fijas con enums: Sustituye las categorías de cadenas abiertas por arrays enum explícitos cuando solo sea válido un conjunto conocido de etiquetas.
  6. Escribe descripciones claras: Coloca las reglas del dominio y las restricciones ignoradas, como los objetivos de longitud de caracteres o las instrucciones alternativas, en la description de cada propiedad.

A continuación se muestra un esquema de ejemplo para clasificar un ticket de atención al cliente. Sigue las reglas comunes a los proveedores anteriores: una raíz de objeto, todos los campos obligatorios, un campo que admite null para metadatos opcionales, additionalProperties: false y un enum para el enrutamiento.

{
  "type": "object",
  "additionalProperties": false,
  "required": ["category", "urgency", "summary", "order_id"],
  "properties": {
    "category": {
      "type": "string",
      "enum": ["billing", "bug_report", "account_access", "other"],
      "description": "Primary topic of the support message."
    },
    "urgency": {
      "type": "string",
      "enum": ["low", "normal", "high"],
      "description": "Escalation priority based on user impact."
    },
    "summary": {
      "type": "string",
      "description": "One-sentence summary of the issue in 25 words or fewer."
    },
    "order_id": {
      "type": ["string", "null"],
      "description": "Order identifier if present in the message, otherwise null."
    }
  }
}

¿Qué puede seguir fallando con Structured Outputs?

Structured outputs garantiza una sintaxis válida conforme al esquema, pero las aplicaciones en producción siguen encontrando rechazos, truncamiento de tokens, valores alucinados, variaciones de mayúsculas en enums, latencia de la primera solicitud y entradas de usuario no fiables. Tratar el cumplimiento del esquema como una verificación de sintaxis en lugar de una verificación de veracidad o seguridad evita fallos silenciosos en producción.

Rechazos de seguridad y truncamiento por límite de tokens

Los modelos todavía pueden rechazar solicitudes inseguras de los usuarios o detenerse a mitad de la generación al alcanzar el límite de tokens de salida. En OpenAI, un rechazo de seguridad rellena un campo independiente refusal que no se ajusta a tu JSON Schema. En Anthropic Claude, un rechazo devuelve HTTP 200 con stop_reason establecido en "refusal" (que se sigue facturando) y prevalece sobre el esquema; del mismo modo, alcanzar el límite de salida devuelve stop_reason "max_tokens" con JSON incompleto. Comprueba siempre los indicadores de rechazo y las razones de parada antes de llamar a JSON.parse() o a un validador.

Valores válidos según el esquema pero incorrectos en los hechos

La decodificación restringida obliga al modelo a rellenar el esquema incluso cuando el texto de origen carece de una respuesta o contradice las suposiciones del esquema. Una respuesta puede superar todas las comprobaciones de tipo y enum y contener fechas inventadas, categorías incorrectas o conjeturas plausibles. OpenAI aconseja indicar al modelo en el prompt qué debe devolver cuando la entrada sea incompatible con el esquema, por ejemplo null o campos vacíos, y Google advierte a los desarrolladores que validen los valores en el código frente a las reglas de negocio. Para saber por qué las respuestas seguras pueden seguir siendo incorrectas, lee nuestra guía sobre tasas de alucinación de IA.

Mayúsculas de enums en Claude y latencia de compilación

Dos particularidades operativas toman por sorpresa a los equipos durante los despliegues:

  • Mayúsculas de enums en Claude: Anthropic señala que el uso de mayúsculas en enums no está garantizado durante la decodificación restringida, por lo que debes comparar las cadenas enum devueltas sin distinguir mayúsculas de minúsculas en la lógica de tu aplicación.
  • Retraso de compilación en la primera solicitud: Claude añade latencia adicional la primera vez que un esquema nuevo se compila en una gramática antes de guardarla en caché durante 24 horas, y OpenAI señala un retraso similar de procesamiento del esquema en la primera solicitud para modelos ajustados.

Prompt Injection dentro de los valores de campo

Restringir la estructura de salida no neutraliza las instrucciones maliciosas ocultas en texto no fiable que se resume o extrae a un campo de cadena JSON. Un modelo puede devolver correctamente JSON válido cuyo campo summary o notes contenga instrucciones inyectadas o contenido engañoso dirigido a herramientas posteriores o revisores humanos. Trata cada valor de campo analizado como entrada no fiable y consulta nuestra introducción sobre qué es prompt injection antes de pasar campos extraídos a acciones automatizadas.

Preguntas frecuentes

¿Structured outputs ralentiza las respuestas de los LLM?

Structured outputs puede añadir latencia en la primera solicitud con un esquema nuevo, mientras que las solicitudes posteriores almacenadas en caché se ejecutan sin sobrecarga de compilación. Anthropic guarda las gramáticas compiladas de Claude durante 24 horas desde el último uso, salvo que cambies la estructura del esquema o las definiciones de herramientas. OpenAI solo señala latencia adicional de procesamiento del esquema en la primera solicitud cuando se usan modelos ajustados.

¿Puede un LLM seguir alucinando al usar structured outputs?

Sí, un LLM puede seguir alucinando valores mientras devuelve JSON que cumple el esquema al 100 por ciento. La decodificación restringida limita la sintaxis de los tokens y los tipos de campos, no la exactitud factual. Si la entrada carece de información obligatoria, el modelo puede inventar valores para satisfacer las claves requeridas, salvo que permitas campos que admitan null y le indiques cuándo devolver null.

¿Debo usar Pydantic o Zod con las API de structured output?

Las herramientas nativas de esquema del SDK ayudan a mantener alineados los tipos de la aplicación y los esquemas de la API. OpenAI y Google admiten Pydantic en Python y Zod en JavaScript, mientras que el SDK de Python de Anthropic admite Pydantic mediante client.messages.parse(). Estas herramientas convierten tus modelos en JSON Schema, analizan las respuestas como objetos tipados y validan restricciones como las longitudes de cadena que Gemini elimina o Anthropic traslada a las descripciones de campos.

¿Qué sucede si un modelo rechaza una solicitud con structured outputs activado?

Cuando un modelo rechaza una solicitud por motivos de seguridad, el rechazo prevalece sobre tu JSON Schema. OpenAI coloca la explicación en un campo refusal específico en lugar de seguir el esquema, mientras que Anthropic devuelve HTTP 200 con stop_reason establecido en "refusal". Tu aplicación debe examinar esos campos antes de intentar analizar el JSON.

¿Por qué Claude o Gemini rechaza mi JSON Schema con un error 400?

Tanto Claude como Gemini rechazan con un error 400 los esquemas que superan los límites internos de complejidad de la gramática o la máquina de estados. Claude también devuelve un error 400 si incluyes funciones de esquema no admitidas, como esquemas recursivos o límites numéricos, o si combinas salidas JSON con Citations. Aplanar objetos anidados, acortar nombres y reducir parámetros opcionales o de unión suele resolver los rechazos de compilación.

Fuentes

Escrito por

Chunyu Cai

Chunyu Cai es el director ejecutivo de Lotook, LLC y un emprendedor que escribe sobre modelos de IA, agentes y cómo cambian el trabajo cotidiano. Chunyu Cai tiene un título de máster de Imperial College London.