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:
| Nivel | Acercarse | lo que controlas | Fallo típico |
|---|---|---|---|
| L0 | Sólo mensaje: “salida JSON” | restricción suave | ```json fences, prose, single quotes, trailing commas |
| L1 | Mensaje + ejemplos JSON de pocas tomas | Dar forma con el ejemplo, sin reglas estrictas | Desviación del nombre de campo, campos faltantes, tipos mixtos |
| L2 | JSON Mode⟧ (response_format: json_object, etc.) | La salida debe ser válida JSON | Parses, but price may be a string |
| L3 | Salida estructurada+ JSON Esquema⟧ | Campos, tipos, enumeración, obligatorios | Alucinació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.
| Proveedor | JSON Modo⟧ | Salida estructurada / Esquema | Notas |
|---|---|---|---|
| AI abierta | response_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éminis | responseMimeType: "application/json" | Above + responseJsonSchema or SDK response_schema | Verartículo dedicado Gemini API |
| Antrópico | Preguntar + analizar | output_format (Claude structured output) or schema in Messages API | Los 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:
- Generate: call model with Schema; log prompt, Schema version, raw
content. - Parse:
JSON.parse(or SDKparsed); on failure, retry whole response — no half-parse. - Schema validate: run same JSON Schema⟧ via AJV /
jsonschema/ Pydantic; retry or degrade on failure. - 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 estructurada | Llamadas a herramientas / MCP | |
|---|---|---|
| Restricciones | Respuesta final JSON al usuario | Tool argument JSON (inputSchema) |
| Efectos secundarios | Ninguno: solo datos | Host / MCP Se ejecuta el servidor |
| Uso típico | Extraer, clasificar, completar formularios, traspaso de agentes | Inventario, archivos, API externas |
| En caso de fracaso | Reintentar o humano | Error 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.