> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Saídas Estruturadas (Structured Outputs)

> Controle o formato de saída do modelo via JSON Schema (Structured Outputs). Compatível com OpenAI, Anthropic Claude, Gemini e outros modelos usando response_format e output_config.format, com degradação automática e conversão entre protocolos.

## Visão geral das capacidades

Saídas Estruturadas (Structured Outputs) fazem com que a resposta do modelo siga rigorosamente o JSON Schema que você definiu, garantindo que o valor retornado possa ser analisado diretamente pelo seu programa, sem necessidade de expressões regulares ou pós-processamento.

Diferente de pedir ao modelo no prompt para "retornar JSON", as saídas estruturadas são baseadas em **decodificação restrita (Constrained Decoding)**: o provedor compila o JSON Schema em regras gramaticais e restringe a geração token a token durante a inferência, tornando **impossível** que o modelo produza conteúdo que viole o Schema.

Cenários típicos:

* Extrair entidades e campos de texto não estruturado
* Classificação / rotulagem / análise de sentimento
* Padronização de resultados intermediários em raciocínio multi-etapas
* Restrição de tipos fortes nos parâmetros de chamada de ferramentas de Agents

## Comparação de parâmetros por protocolo

<Note>
  Os nomes dos parâmetros diferem entre os três protocolos, mas o mecanismo subjacente é o mesmo: a saída do modelo corresponde rigorosamente ao JSON Schema que você forneceu.
</Note>

| Protocolo                          | Parâmetro                                  | Modelos compatíveis                                   |
| ---------------------------------- | ------------------------------------------ | ----------------------------------------------------- |
| OpenAI Chat `/v1/chat/completions` | `response_format.type: "json_schema"`      | Claude 4.5+, GPT-4o / série GPT-5, série Gemini       |
| Anthropic Messages `/v1/messages`  | `output_config.format.type: "json_schema"` | Claude 4.5+ (direto / Vertex); Bedrock apenas 4.5–4.6 |
| OpenAI Responses `/v1/responses`   | `text.format.type: "json_schema"`          | Conforme capacidade do modelo upstream                |

### Limitações do AWS Bedrock

No AWS Bedrock, as versões Claude 4.7 e superiores utilizam o caminho de inferência Mantle, que atualmente não suporta `output_config.format`. O gateway remove automaticamente o campo `format` para esses modelos e marca a degradação no cabeçalho de resposta (veja [Mecanismo de degradação automática](#mecanismo-de-degradação-automática) abaixo). A requisição não retornará erro por causa disso.

***

## Início rápido

### Protocolo OpenAI (recomendado)

Aplicável a todos os modelos que suportam saídas estruturadas, universal entre fornecedores.

<CodeGroup>
  ```python Python theme={null}
  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": "Extraia as seguintes informações: João Silva, 28 anos, Centro de São Paulo"}
      ],
      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": "João Silva", "age": 28, "city": "Centro de São Paulo"}
  ```

  ```typescript Node.js theme={null}
  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: "Extraia as seguintes informações: João Silva, 28 anos, Centro de São Paulo" },
    ],
    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);
  ```

  ```bash cURL theme={null}
  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": "Extraia as seguintes informações: João Silva, 28 anos, Centro de São Paulo"}
      ],
      "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
          }
        }
      }
    }'
  ```
</CodeGroup>

### Usando outros modelos (exemplo GLM-5.2)

O mesmo conjunto de parâmetros do protocolo OpenAI se aplica a todos os modelos que suportam saídas estruturadas. Basta trocar o `model`.

```python Python theme={null}
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": "Extraia as seguintes informações: João Silva, 28 anos, Centro de São Paulo"}
    ],
    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": "João Silva", "age": 28, "city": "Centro de São Paulo"}
```

### Protocolo nativo Claude

Usando o SDK da Anthropic diretamente, com o parâmetro `output_config.format`.

<CodeGroup>
  ```python Python theme={null}
  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": "Extraia as seguintes informações: João Silva, 28 anos, Centro de São Paulo"}
      ],
      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)
  ```

  ```bash cURL theme={null}
  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": "Extraia as seguintes informações: João Silva, 28 anos, Centro de São Paulo"}
      ],
      "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
          }
        }
      }
    }'
  ```
</CodeGroup>

***

## Pontos-chave para escrever o Schema

### Campos obrigatórios

Todos os tipos `object` devem declarar explicitamente `additionalProperties: false`, caso contrário alguns provedores upstream rejeitarão a requisição.

```json theme={null}
{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "score": { "type": "number" }
  },
  "required": ["name", "score"],
  "additionalProperties": false
}
```

### Objetos aninhados

Objetos `object` aninhados também precisam de `additionalProperties: false`:

```json theme={null}
{
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "type": "string" }
      },
      "required": ["name", "email"],
      "additionalProperties": false
    }
  },
  "required": ["user"],
  "additionalProperties": false
}
```

### Diferenças de Schema entre protocolos

| Característica                                   | Protocolo OpenAI             | Protocolo Anthropic                                                               |
| ------------------------------------------------ | ---------------------------- | --------------------------------------------------------------------------------- |
| Campo `name`                                     | Obrigatório                  | Não suportado (tratado automaticamente pelo gateway em chamadas entre protocolos) |
| Campo `strict`                                   | Opcional, recomendado `true` | Não suportado                                                                     |
| Restrições numéricas (`minimum`, `maximum` etc.) | Suportado                    | Não suportado (o gateway limpa automaticamente, sem afetar a requisição)          |
| Restrições de string (`minLength`, `maxLength`)  | Suportado                    | Não suportado (o gateway limpa automaticamente)                                   |

<Tip>
  Ao chamar modelos Claude usando o protocolo OpenAI, o gateway converte automaticamente o formato do Schema e limpa palavras-chave incompatíveis, sem necessidade de adaptação manual.
</Tip>

***

## Mecanismo de degradação automática

O gateway habilita por padrão a proteção de degradação automática de saídas estruturadas para todas as requisições. Quando o modelo ou a plataforma não oferece suporte, o gateway **não retorna um erro**, mas remove automaticamente a restrição do Schema e marca o motivo da degradação no cabeçalho de resposta. Sua requisição ainda receberá uma resposta normal do modelo, apenas a saída não será restringida pelo Schema.

Isso significa que você pode ativar saídas estruturadas de forma unificada no cliente sem precisar fazer verificações de compatibilidade para cada modelo:

* **Troca de modelos sem preocupação**: o mesmo código funciona ao alternar entre Claude, GPT, Gemini e GLM. Mesmo que o modelo de destino não suporte saídas estruturadas, a requisição não falhará
* **Roteamento de fallback transparente**: quando o canal principal não está disponível e o fallback roteia para um canal de backup, mesmo que a versão do modelo do canal de backup não suporte saídas estruturadas, a requisição ainda será concluída normalmente
* **Lógica simplificada no cliente**: não é necessário manter uma lista de "quais modelos suportam saídas estruturadas". O gateway já cuida disso automaticamente; o cliente só precisa verificar o cabeçalho de resposta para decidir se é necessária uma análise adicional

### Cabeçalho de resposta

```
X-Structured-Output-Degraded: <reason>
```

| reason                                 | Significado                                                                                 |
| -------------------------------------- | ------------------------------------------------------------------------------------------- |
| `model_unsupported`                    | Este modelo (ou este modelo na plataforma atual) não suporta saídas estruturadas            |
| `json_object_unsupported_on_anthropic` | O modo `json_object` não pode ser convertido para o formato Anthropic                       |
| `json_schema_missing_schema`           | O tipo `json_schema` foi especificado, mas o campo `schema` está ausente                    |
| `schema_keywords_stripped`             | Algumas palavras-chave de restrição do Schema foram removidas (como `minimum`, `maxLength`) |

### Exemplo de detecção

```python Python theme={null}
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": "Extraia as informações: João Silva, 28 anos"}],
        "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,
                }
            }
        }
    }
)

# Verifica se ocorreu degradação (por exemplo, quando a requisição foi roteada para um canal Bedrock sem suporte)
degraded = response.headers.get("X-Structured-Output-Degraded")
if degraded:
    print(f"Saída estruturada degradada: {degraded}")
    # Neste caso, a resposta do modelo ainda é normal, mas a saída não é restringida pelo Schema
else:
    import json
    data = json.loads(response.json()["choices"][0]["message"]["content"])
    print(data)  # {"name": "João Silva", "age": 28}
```

***

## Diferença em relação ao modo `json_object`

|                        | `json_schema` (Saídas Estruturadas)                     | `json_object`                            |
| ---------------------- | ------------------------------------------------------- | ---------------------------------------- |
| Garantia de saída      | Correspondência rigorosa com o Schema especificado      | Apenas garante que é um JSON válido      |
| Controle de campos     | Nomes, tipos e obrigatoriedade dos campos são restritos | Sem restrições                           |
| Protocolos compatíveis | OpenAI / Anthropic / Responses                          | Apenas protocolos compatíveis com OpenAI |
| Suporte Claude         | Via `output_config.format`                              | Não suportado                            |

<Warning>
  O modo `json_object` não pode ser convertido para o protocolo nativo Claude. Se você enviar `response_format: {"type": "json_object"}` para o Claude via protocolo OpenAI, o cabeçalho de resposta marcará a degradação `json_object_unsupported_on_anthropic`. Recomenda-se usar diretamente o tipo `json_schema`.
</Warning>

***

## Perguntas frequentes

<AccordionGroup>
  <Accordion title="Quais modelos suportam Structured Outputs?">
    **Série Claude** (via `output_config.format` da API Anthropic):

    * Opus / Sonnet / Haiku 4.5 e versões superiores
    * Fable / Mythos 5 e versões superiores
    * Plataforma Bedrock apenas 4.5–4.6; Vertex AI igual ao acesso direto

    **Série OpenAI** (via `response_format`):

    * GPT-4o e superiores, série GPT-5

    **Série Gemini** (via `responseSchema`):

    * Gemini 2.5 e superiores

    Você pode verificar as tags de capacidade de cada modelo na [página de lista de modelos](https://aihubmix.com/models).
  </Accordion>

  <Accordion title="Por que alguns modelos Claude no Bedrock não suportam saídas estruturadas?">
    No AWS Bedrock, o Claude 4.7+ utiliza o novo caminho de inferência Mantle, que atualmente não aceita o parâmetro `output_config.format`. O gateway trata isso automaticamente: remove o campo format e retorna a resposta normalmente, ao mesmo tempo marcando o cabeçalho de degradação `X-Structured-Output-Degraded: model_unsupported`. O Claude 4.5–4.6 tem suporte completo no Bedrock.
  </Accordion>

  <Accordion title="O JSON Schema é modificado em chamadas entre protocolos?">
    Sim. Ao chamar modelos Claude via protocolo OpenAI, o gateway automaticamente:

    1. Converte `response_format` para `output_config.format`
    2. Remove palavras-chave do Schema não suportadas pela Anthropic (`minimum`, `maxLength` etc.)
    3. Se alguma palavra-chave for removida, o cabeçalho de resposta marca `schema_keywords_stripped`

    A conversão reversa (protocolo Claude chamando modelos OpenAI) também é automática.
  </Accordion>

  <Accordion title="Structured Outputs pode ser usado junto com Extended Thinking?">
    Sim. O `format` em `output_config` (saídas estruturadas) e o `effort` em `reasoning` (intensidade de raciocínio) são parâmetros independentes e podem ser definidos simultaneamente:

    ```json theme={null}
    {
      "output_config": {
        "format": {
          "type": "json_schema",
          "schema": { ... }
        }
      },
      "reasoning": {
        "effort": "high"
      }
    }
    ```
  </Accordion>

  <Accordion title="Qual a diferença do mecanismo de degradação em comparação com outras plataformas de agregação como OpenRouter?">
    A maioria das plataformas de agregação de API retorna um erro diretamente quando o modelo não suporta saídas estruturadas. O AIHubMix adota uma estratégia de **degradação graciosa**: remove automaticamente os parâmetros incompatíveis, retorna a resposta do modelo normalmente e informa o cliente sobre o motivo da degradação através do cabeçalho de resposta `X-Structured-Output-Degraded`. Sua aplicação não será interrompida por causa disso.
  </Accordion>
</AccordionGroup>
