Saltar al contenido principal

Descripcion general

Las salidas estructuradas (Structured Outputs) hacen que la respuesta del modelo se ajuste estrictamente al JSON Schema que definas, asegurando que el valor de retorno pueda ser parseado directamente por tu programa, sin necesidad de expresiones regulares ni post-procesamiento. A diferencia de pedirle al modelo en el prompt que “devuelva JSON”, las salidas estructuradas se basan en la decodificacion restringida (Constrained Decoding): el proveedor upstream compila el JSON Schema en reglas gramaticales y restringe la generacion token a token durante la inferencia, haciendo imposible que el modelo produzca contenido que viole el Schema. Escenarios tipicos:
  • Extraccion de entidades y campos a partir de texto no estructurado
  • Clasificacion / etiquetado / analisis de sentimiento
  • Transferencia estandarizada de resultados intermedios en razonamientos de multiples pasos
  • Restricciones de tipado fuerte en parametros de llamadas a herramientas de Agents

Comparacion de parametros por protocolo

Los nombres de parametros difieren entre los tres protocolos, pero el mecanismo subyacente es el mismo: la salida del modelo coincide estrictamente con el JSON Schema que proporcionas.
ProtocoloParametroModelos compatibles
OpenAI Chat /v1/chat/completionsresponse_format.type: "json_schema"Claude 4.5+, GPT-4o / serie GPT-5, serie Gemini
Anthropic Messages /v1/messagesoutput_config.format.type: "json_schema"Claude 4.5+ (directo / Vertex / Bedrock)
OpenAI Responses /v1/responsestext.format.type: "json_schema"Segun capacidad del modelo upstream

Inicio rapido

Protocolo OpenAI (recomendado)

Aplicable a todos los modelos que soportan salidas estructuradas, compatible entre proveedores.
from openai import OpenAI

client = OpenAI(
    api_key="<AIHUBMIX_API_KEY>",
    base_url="https://aihubmix.com/v1",
)

response = client.chat.completions.create(
    model="claude-sonnet-5",
    messages=[
        {"role": "user", "content": "Extract the following information: John Smith, 28 years old, San Francisco"}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "person_info",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "city": {"type": "string"}
                },
                "required": ["name", "age", "city"],
                "additionalProperties": False
            }
        }
    }
)

import json
data = json.loads(response.choices[0].message.content)
print(data)
# {"name": "John Smith", "age": 28, "city": "San Francisco"}
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "<AIHUBMIX_API_KEY>",
  baseURL: "https://aihubmix.com/v1",
});

const response = await client.chat.completions.create({
  model: "claude-sonnet-5",
  messages: [
    { role: "user", content: "Extract the following information: John Smith, 28 years old, San Francisco" },
  ],
  response_format: {
    type: "json_schema",
    json_schema: {
      name: "person_info",
      strict: true,
      schema: {
        type: "object",
        properties: {
          name: { type: "string" },
          age: { type: "integer" },
          city: { type: "string" },
        },
        required: ["name", "age", "city"],
        additionalProperties: false,
      },
    },
  },
});

const data = JSON.parse(response.choices[0].message.content);
console.log(data);
curl https://aihubmix.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <AIHUBMIX_API_KEY>" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [
      {"role": "user", "content": "Extract the following information: John Smith, 28 years old, San Francisco"}
    ],
    "response_format": {
      "type": "json_schema",
      "json_schema": {
        "name": "person_info",
        "strict": true,
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "age": {"type": "integer"},
            "city": {"type": "string"}
          },
          "required": ["name", "age", "city"],
          "additionalProperties": false
        }
      }
    }
  }'

Uso con otros modelos (ejemplo GLM-5.2)

El mismo conjunto de parametros del protocolo OpenAI se aplica a todos los modelos que soportan salidas estructuradas; basta con cambiar el campo model.
Python
from openai import OpenAI

client = OpenAI(
    api_key="<AIHUBMIX_API_KEY>",
    base_url="https://aihubmix.com/v1",
)

response = client.chat.completions.create(
    model="glm-5.2",
    messages=[
        {"role": "user", "content": "Extract the following information: John Smith, 28 years old, San Francisco"}
    ],
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "person_info",
            "strict": True,
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "city": {"type": "string"}
                },
                "required": ["name", "age", "city"],
                "additionalProperties": False
            }
        }
    }
)

import json
data = json.loads(response.choices[0].message.content)
print(data)
# {"name": "John Smith", "age": 28, "city": "San Francisco"}

Protocolo nativo de Claude

Llamada directa mediante el SDK de Anthropic, utilizando el parametro output_config.format.
import anthropic

client = anthropic.Anthropic(
    api_key="<AIHUBMIX_API_KEY>",
    base_url="https://aihubmix.com",
)

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Extract the following information: John Smith, 28 years old, San Francisco"}
    ],
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "age": {"type": "integer"},
                    "city": {"type": "string"}
                },
                "required": ["name", "age", "city"],
                "additionalProperties": False
            }
        }
    }
)

import json
data = json.loads(response.content[0].text)
print(data)
curl https://aihubmix.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: <AIHUBMIX_API_KEY>" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 1024,
    "messages": [
      {"role": "user", "content": "Extract the following information: John Smith, 28 years old, San Francisco"}
    ],
    "output_config": {
      "format": {
        "type": "json_schema",
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "age": {"type": "integer"},
            "city": {"type": "string"}
          },
          "required": ["name", "age", "city"],
          "additionalProperties": false
        }
      }
    }
  }'

Puntos clave para escribir Schemas

Campos obligatorios

Todos los tipos object deben declarar explicitamente additionalProperties: false; de lo contrario, algunos proveedores upstream rechazaran la solicitud.
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "score": { "type": "number" }
  },
  "required": ["name", "score"],
  "additionalProperties": false
}

Objetos anidados

Los object anidados tambien requieren additionalProperties: false:
{
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "type": "string" }
      },
      "required": ["name", "email"],
      "additionalProperties": false
    }
  },
  "required": ["user"],
  "additionalProperties": false
}

Diferencias de Schema entre protocolos

CaracteristicaProtocolo OpenAIProtocolo Anthropic
Campo nameObligatorioNo soportado (el gateway lo gestiona automaticamente en llamadas entre protocolos)
Campo strictOpcional, se recomienda trueNo soportado
Restricciones numericas (minimum, maximum, etc.)SoportadoNo soportado (el gateway las elimina automaticamente, sin afectar la solicitud)
Restricciones de cadena (minLength, maxLength)SoportadoNo soportado (el gateway las elimina automaticamente)
Al llamar a modelos Claude mediante el protocolo OpenAI, el gateway convierte automaticamente el formato del Schema y elimina las palabras clave incompatibles, sin necesidad de adaptacion manual.

Mecanismo de degradacion automatica

El gateway habilita por defecto la proteccion de degradacion automatica de salidas estructuradas para todas las solicitudes. Cuando el modelo o la plataforma no lo soportan, el gateway no devuelve un error, sino que elimina automaticamente las restricciones del Schema y marca el motivo de la degradacion en el encabezado de respuesta. Tu solicitud seguira recibiendo una respuesta normal del modelo, solo que la salida no estara sujeta a las restricciones forzadas del Schema. Esto significa que puedes habilitar con confianza las salidas estructuradas de forma uniforme en el cliente, sin necesidad de verificar la compatibilidad de cada modelo:
  • Cambio de modelos sin preocupaciones: al alternar entre Claude, GPT, Gemini y GLM con el mismo codigo, incluso si el modelo de destino no soporta salidas estructuradas, la solicitud no fallara
  • Reserva transparente: Incluso si la versión del modelo que finalmente procesa tu solicitud no admite salidas estructuradas, la solicitud se completa con normalidad y la degradación se indica en la cabecera de respuesta
  • Logica del cliente simplificada: no necesitas mantener una lista de “que modelos soportan salidas estructuradas”, el gateway ya lo gestiona automaticamente; el cliente solo necesita verificar el encabezado de respuesta para decidir si se requiere un analisis adicional

Encabezado de respuesta

X-Structured-Output-Degraded: <reason>
reasonSignificado
model_unsupportedEl modelo (o el modelo en la plataforma actual) no soporta salidas estructuradas
json_object_unsupported_on_anthropicEl modo json_object no puede convertirse al formato Anthropic
json_schema_missing_schemaSe especifico el tipo json_schema pero falta el campo schema
schema_keywords_strippedSe eliminaron algunas palabras clave de restriccion del Schema (como minimum, maxLength)

Ejemplo de deteccion

Python
import httpx

response = httpx.post(
    "https://aihubmix.com/v1/chat/completions",
    headers={
        "Authorization": "Bearer <AIHUBMIX_API_KEY>",
        "Content-Type": "application/json",
    },
    json={
        "model": "claude-sonnet-5",
        "messages": [{"role": "user", "content": "Extract info: John Smith, 28 years old"}],
        "response_format": {
            "type": "json_schema",
            "json_schema": {
                "name": "person",
                "strict": True,
                "schema": {
                    "type": "object",
                    "properties": {"name": {"type": "string"}, "age": {"type": "integer"}},
                    "required": ["name", "age"],
                    "additionalProperties": False,
                }
            }
        }
    }
)

# Verificar si ocurrio una degradacion
degraded = response.headers.get("X-Structured-Output-Degraded")
if degraded:
    print(f"Salida estructurada degradada: {degraded}")
    # La respuesta del modelo sigue siendo normal, pero la salida no esta sujeta a restricciones forzadas del Schema
else:
    import json
    data = json.loads(response.json()["choices"][0]["message"]["content"])
    print(data)  # {"name": "John Smith", "age": 28}

Diferencias con el modo json_object

json_schema (salidas estructuradas)json_object
Garantia de salidaCoincidencia estricta con el Schema especificadoSolo garantiza que sea JSON valido
Control de camposNombres, tipos y obligatoriedad de campos estan restringidosSin restricciones
Protocolos compatiblesOpenAI / Anthropic / ResponsesSolo protocolo compatible con OpenAI
Soporte de ClaudeMediante output_config.formatNo soportado
El modo json_object no soporta la conversion al protocolo nativo de Claude. Si envias response_format: {"type": "json_object"} a Claude mediante el protocolo OpenAI, el encabezado de respuesta marcara la degradacion json_object_unsupported_on_anthropic. Se recomienda usar directamente el tipo json_schema.

Preguntas frecuentes

Serie Claude (mediante output_config.format de la API de Anthropic):
  • Opus / Sonnet / Haiku 4.5 y versiones superiores
  • Fable / Mythos 5 y versiones superiores
Serie OpenAI (mediante response_format):
  • GPT-4o y superiores, serie GPT-5
Serie Gemini (mediante responseSchema):
  • Gemini 2.5 y superiores
Puedes consultar las etiquetas de capacidad de cada modelo en la pagina de lista de modelos.
Si. Al llamar a modelos Claude mediante el protocolo OpenAI, el gateway automaticamente:
  1. Convierte response_format a output_config.format
  2. Elimina las palabras clave del Schema no soportadas por Anthropic (minimum, maxLength, etc.)
  3. Si se eliminaron palabras clave, el encabezado de respuesta marca schema_keywords_stripped
La conversion inversa (protocolo Claude llamando a modelos OpenAI) tambien se realiza automaticamente.
Si. El campo format (salidas estructuradas) dentro de output_config y el campo effort (intensidad de razonamiento) dentro de reasoning son parametros independientes que se pueden configurar simultaneamente:
{
  "output_config": {
    "format": {
      "type": "json_schema",
      "schema": { ... }
    }
  },
  "reasoning": {
    "effort": "high"
  }
}
La mayoria de las plataformas de agregacion de API devuelven un error directamente cuando el modelo no soporta salidas estructuradas. AIHubMix adopta una estrategia de degradacion elegante: elimina automaticamente los parametros incompatibles, devuelve la respuesta del modelo normalmente e informa al cliente del motivo de la degradacion a traves del encabezado de respuesta X-Structured-Output-Degraded. Tu aplicacion no se interrumpira por este motivo.