Cómo la IA genera JSON conforme a JSON Schema: del Prompt al Structured Output

Del JSON solo en prompt y JSON Mode a Structured Outputs — restricciones JSON Schema, comparación OpenAI / Gemini / Anthropic, pipeline de validación y diferencia con Tool Calling.

Publicaciones anteriores de esta serie cubrieronpor qué los agentes necesitan JSON(Llamada de herramientas al flujo de datos MCP),por qué JSON Schema⟧ se convirtió en infraestructura(Esquema, llamada a función y evolución de MCP), yConfiguración de Salida estructurada específica de Gemini(Guía Géminis API).

Este artículo se aleja:Independientemente del modelo API que utilice, ¿cómo se pasa de "responda en JSON" a "la salida debe coincidir con este JSON esquema⟧"?? Los proveedores convergieron en esto en 2024-2026 bajo nombres como Structured Outputs⟧ / JSON Schema⟧ mode: la misma idea, nombres de campo, subconjuntos de esquemas y límites ligeramente diferentes con Tool Calling.

Cuatro niveles, cada uno estrictomás que el anterior

Los equipos suelen utilizar cuatro enfoques para obtener JSON de un modelo; la confiabilidad difiere en un orden de magnitud:

NivelAcercarselo que controlasFallo típico
L0Sólo mensaje: “salida JSON”restricción suave```json fences, prose, single quotes, trailing commas
L1Mensaje + ejemplos JSON de pocas tomasDar forma con el ejemplo, sin reglas estrictasDesviación del nombre de campo, campos faltantes, tipos mixtos
L2JSON Mode⟧ (response_format: json_object, etc.)La salida debe ser válida JSONParses, but price may be a string
L3Salida estructurada+ JSON Esquema⟧Campos, tipos, enumeración, obligatoriosAlucinación semántica, truncamiento, palabras clave ignoradas

For production extraction, classification, or form filling, aim for L3. L0–L1 suit exploration; L2 when shape varies and you only need JSON.parse. L3 is the contract programs can consume directly.

Qué controla JSON Schema⟧ y qué no

JSON Esquema⟧describe la estructura del documento: campos, tipos, claves requeridas, enumeraciones, rangos, forma del elemento de matriz. Los proveedores Salidas estructuradas compilan ese esquema en generación, no solo lo pegan en el mensaje.

Schema can enforce: syntax shape (object / array / string / integer), required, enum, minimum / maximum, additionalProperties: false, nested objects and arrays.

Schema cannot enforce business correctness. Example: “total_cents must equal sum of line items” — assert that in code after Schema validation. Schema also does not fact-check: a well-typed fabricated invoice number is still hallucination.

Tool inputSchema uses the same language; Structured Output constrains the final reply, Tool Calling constrains tool arguments. See guía de flujo de datos.

Decodificación restringida: por qué Schema supera a Prompt

Las indicaciones sólo aumentan las probabilidades de cumplimiento. Usos de Salida Estructuradadecodificación restringida: en cada token, el decodificador suprime los tokens que romperían la sintaxis JSON o violarían el esquema.

Por lo general, obtienes JSON analizable y con forma correcta sin vallas de rebajas que eliminan expresiones regulares. Las implementaciones difieren (FSM, gramática, máscaras logit), pero el contrato de desarrollador es el mismo:pasar el esquema a la API, no solo el mensaje.

Garantías de decodificación restringidasestructura, nosemántica. Vuelva a validar siempre con el mismo esquema y agregue reglas de negocio en producción.

Comparación OpenAI, Géminis, Antrópico

Mismo concepto, diferentes nombres de campos. Ejemplo: extraer un objeto de factura.

ProveedorJSON Modo⟧Salida estructurada / EsquemaNotas
AI abiertaresponse_format: { type: "json_object" }response_format: { type: "json_schema", json_schema: { name, schema, strict: true } }strict: true rejects undeclared fields; works with Pydantic model_json_schema()
Google GéminisresponseMimeType: "application/json"Above + responseJsonSchema or SDK response_schemaVerartículo dedicado Gemini API
AntrópicoPreguntar + analizaroutput_format (Claude structured output) or schema in Messages APILos campos evolucionan con SDK; mantener el esquema plano

When migrating vendors, keep the Schema itself standard JSON Schema⟧ (type, properties, required, enum); SDKs only wrap the request. Do not mix OpenAPI 3.0 uppercase types (OBJECT) with JSON Schema⟧ lowercase (object).

Escribir un buen esquema: de Pydantic a producción

Recommended flow: define types in Pydantic / Zod → export JSON Schema⟧ → tune → send to API. Put semantics in description — it enters model context and disambiguates “qty = pieces vs boxes”; type: integer alone cannot.

from pydantic import BaseModel, Field


class LineItem(BaseModel):
    name: str = Field(description="Product name")
    qty: int = Field(description="Quantity, positive integer", ge=1)
    unit_price_cents: int = Field(description="Unit price in cents", ge=0)


class Invoice(BaseModel):
    vendor: str
    currency: str = Field(description="ISO 4217, e.g. CNY")
    items: list[LineItem]
    total_cents: int

schema = Invoice.model_json_schema()
# In production add additionalProperties: false

Reglas prácticas:

  • Prefer object root over root-level array; { "items": [...] } is more stable on some APIs.
  • Start with type / properties / required / enum, then add additionalProperties, min/max; do not dump full Draft 2020-12 — some keywords are ignored.
  • Siga anidando a poca profundidad; Se rechazan las referencias circulares: aplana el esquema.
  • Esquema dividido frente a solicitud: Esquema = forma; Mensaje = semántica (“extraer factura del texto a continuación…”).

Ejemplo de OpenAI Resultadosestructurados⟧

Chat Completions supports json_schema response format since 2024. With strict: true, output should only contain Schema fields:

from openai import OpenAI
from pydantic import BaseModel

client = OpenAI()

class Invoice(BaseModel):
    vendor: str
    total_cents: int

response = client.chat.completions.create(
    model="gpt-4o-2024-08-06",
    messages=[
        {"role": "user", "content": "Extract invoice: Acme sold 2 keyboards for 398 CNY."}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "invoice",
            "strict": True,
            "schema": Invoice.model_json_schema(),
        },
    },
)

data = response.choices[0].message.content  # JSON string
import json
invoice = json.loads(data)

Gemini uses response_mime_type + response_json_schema — see the dedicated Gemini API article. For Anthropic, check current SDK structured output docs — same idea, official field names.

Canal de producción: generar → analizar → validar → reintentar

Salida estructurada no es “una sola llamada a la API y listo”. Corrija estos cuatro pasos:

  1. Generate: call model with Schema; log prompt, Schema version, raw content.
  2. Parse: JSON.parse (or SDK parsed); on failure, retry whole response — no half-parse.
  3. Schema validate: run same JSON Schema⟧ via AJV / jsonschema / Pydantic; retry or degrade on failure.
  4. Validación empresarial: afirmaciones personalizadas (totales, claves externas); motor humano o de reglas en caso de falla.

En desarrollo, almacene Schema más 2 o 3 muestras positivas/negativas en el repositorio; use JSON Toolbox⟧ localmente para la estructura y Diff: la misma mentalidad que las pruebas de contrato REST, el consumidor es el LLM.

Errores comunes: pedir "explicar y luego JSON" mientras el JSON Mode⟧ está activado; truncamiento (aumentar el máximo de tokens o dividir tareas); Claves API en demostraciones de frontend; La versión del esquema se desvía del mensaje.

En qué se diferencia de Tool Calling

Salida estructuradaLlamadas a herramientas / MCP
RestriccionesRespuesta final JSON al usuarioTool argument JSON (inputSchema)
Efectos secundariosNinguno: solo datosHost / MCP Se ejecuta el servidor
Uso típicoExtraer, clasificar, completar formularios, traspaso de agentesInventario, archivos, API externas
En caso de fracasoReintentar o humanoError en el mensaje de la herramienta → preguntar al modelo nuevamente

Un bucle de agente completo suele tener el siguiente aspecto:Salida estructurada extrae la intención → Llamada a herramientas actúa → Salida estructurada o resúmenes en prosa para el usuario. No utilice Salida estructurada para fingir que “se llamó al pago API”; el modelo no lo llamó.

Preguntas frecuentes

¿Es suficiente “por favor envíe JSON” en el mensaje?

No. Las indicaciones solo aumentan las probabilidades de cumplimiento: todavía ocurren vallas de rebajas, comas finales y deriva de campo. En producción, habilite al menos JSON Modo⟧; Lo ideal es pasar JSON Schema⟧ a través del canal API Structured Output para que la decodificación excluya los tokens ilegales.

¿Cuál es la diferencia entre JSON Modo⟧ y Salida Estructurada?

JSON Mode⟧ solo garantiza texto JSON válido, no nombres de campos, tipos o claves requeridas. Salida estructurada agrega JSON Esquema⟧ y filtra tokens durante la generación; la forma se estabiliza para que pueda almacenar o pasar al siguiente salto directamente.

¿Son iguales los campos de configuración OpenAI, Gemini y Anthropic?

Mismo concepto, diferentes nombres. OpenAI: formato_respuesta con json_schema y strict; Géminis: responseMimeType + responseJsonSchema; Antrópico: output_format o salida estructurada en herramientas. Mantener el esquema estándar; Los SDK envuelven solicitudes.

¿Puede la Salida estructurada reemplazar la Llamada a herramientas?

No. Salida estructurada restringe la respuesta JSON final; Tool Calling restringe el argumento de la herramienta JSON y requiere que el host ejecute las herramientas. Utilice el primero para extraer/clasificar/rellenar; este último para inventario, archivos, MCP. Las cadenas de agentes completas suelen utilizar ambos.

¿Aún necesito validar el resultado del modelo?

Sí. La decodificación restringida reduce los errores de sintaxis y la deriva tipográfica, pero no la corrección semántica (tipos válidos, valores fabricados). Vuelva a ejecutar el mismo JSON Schema⟧ en producción; reintentar, degradar o revisar en caso de falla.

¿Cómo valido el esquema y la salida de muestra localmente?

Guarde JSON Schema⟧ y algunos ejemplos de resultados de modelos como archivos JSON; use JSON Toolbox⟧ en el navegador para verificar la sintaxis y la estructura; no se carga nada.

Resumen

Para obtener JSON que coincida con JSON Schema⟧ de AI, el orden es importante:Primero defina el esquema, habilite JSON Modo⟧ / Salida estructurada, luego escriba el mensaje. Mensaje = semántica; Esquema = forma; Pydantic / Zod son fachadas amigables para los autores; Las API de los proveedores exponen los canales de esquema.

Ejecute una factura real o una transcripción de soporte de principio a fin: Esquema → Llamada API → pegue el resultado en un validador. Cuando coincida, transfiera la base de datos o el siguiente agente. Los argumentos de la herramienta aún pasan por Tool Calling / MCP; no se fusionen en una API.