> ## 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.

# Reparo de saída estruturada

> Reparo de saída estruturada por API Key: o gateway repara JSON malformado (truncamento, vírgulas, blocos) em Chat Completions, Responses, Claude e Gemini.

O JSON retornado pelo modelo em cenários de [saída estruturada](/pt/api/Structured-Output) às vezes não pode ser analisado: a saída é truncada por `max_tokens`, traz vírgulas finais ou o conteúdo vem empacotado em um bloco de código Markdown. Normalmente, a aplicação precisa escrever lógica de retentativa ou de correção manual para lidar com isso.

O **Reparo de saída estruturada** (Structured Output Repair) é uma capacidade **em nível de Key**, desativada por padrão. Uma vez ativada, para requisições **não-streaming** que declaram saída JSON estruturada, quando o JSON retornado pelo modelo apresenta erros de formato, o gateway da AIHubMix o corrige automaticamente para um JSON válido e analisável antes de retornar; o código do cliente não precisa de nenhuma alteração.

<Note>
  Esse controle vem desativado por padrão; quando não está ativado, todas as respostas são retornadas sem alterações. O controle é configurado de forma independente por Key e passa a valer imediatamente após a ativação.
</Note>

<Card title="Ir para a página de gerenciamento de Keys para configurar" icon="key" href="https://console.aihubmix.com/token" horizontal>
  Crie ou edite uma Key e ative o controle «Reparo de saída estruturada» (Structured Output Repair).
</Card>

<Frame>
  <img src="https://mintcdn.com/aihubmix/qSKYuy2NVPUOModZ/images/api/structured-output-repair/create-key-json-repair.png?fit=max&auto=format&n=qSKYuy2NVPUOModZ&q=85&s=119802fb4114c18581c6e47c1543620a" alt="Ativando o controle de reparo de saída estruturada no painel de edição de Key da AIHubMix" width="2886" height="1974" data-path="images/api/structured-output-repair/create-key-json-repair.png" />
</Frame>

***

## 1. Condições de ativação

O reparo só ocorre quando **todas** as condições abaixo são atendidas:

1. A Key usada na requisição já tem o «Reparo de saída estruturada» ativado.
2. A requisição é **não-streaming** (sem `stream: true`).
3. A requisição declara saída JSON estruturada (os campos de declaração de cada protocolo estão na tabela abaixo).
4. O conteúdo de texto retornado pelo modelo não pode ser analisado como JSON.

| Protocolo        | Endpoint                                        | Campo de declaração de saída estruturada                                                     |
| ---------------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------- |
| Chat Completions | `/v1/chat/completions`                          | `response_format.type` igual a `json_object` ou `json_schema`                                |
| Responses        | `/v1/responses`                                 | `text.format.type` igual a `json_schema` ou `json_object`                                    |
| Claude Messages  | `/v1/messages`                                  | `output_config.format.type` igual a `json_schema`                                            |
| Gemini           | `/gemini/v1beta/models/{model}:generateContent` | `generationConfig.responseMimeType` igual a `application/json`, ou `responseSchema` definido |

Quando o conteúdo já é um JSON válido, nada é alterado e ele é retornado como está.

***

## 2. Erros de formato que podem ser reparados

**Truncamento da saída deixando colchetes / aspas não fechados** (por exemplo, `finish_reason` igual a `length`):

```text Antes theme={null}
{"items": [{"name": "Widget", "price": 9.99}, {"name": "Gad
```

```json Depois theme={null}
{"items": [{"name": "Widget", "price": 9.99}, {"name": "Gad"}]}
```

**Empacotamento em bloco de código Markdown**:

````text Antes theme={null}
```json
{"status": "ok", "count": 3}
```
````

```json Depois theme={null}
{"status": "ok", "count": 3}
```

**Vírgula final**:

```text Antes theme={null}
{"a": 1, "b": 2,}
```

```json Depois theme={null}
{"a": 1, "b": 2}
```

**Aspas simples**:

```text Antes theme={null}
{'name': 'Widget'}
```

```json Depois theme={null}
{"name": "Widget"}
```

**Nomes de chave sem aspas**:

```text Antes theme={null}
{name: "Widget", price: 9.99}
```

```json Depois theme={null}
{"name": "Widget", "price": 9.99}
```

**Texto misturado com JSON** (JSON com texto explicativo antes ou depois):

```text Antes theme={null}
Here is the JSON you requested: {"name": "Widget", "price": 9.99}
```

```json Depois theme={null}
{"name": "Widget", "price": 9.99}
```

O reparo adota uma estratégia conservadora:

* O reparo apenas completa ou normaliza a sintaxe do JSON; **os valores numéricos e o conteúdo das strings permanecem no texto original, sem perda de precisão ou reescrita**.
* O produto do reparo precisa ser um objeto ou array JSON válido, e a diferença em relação ao texto original deve estar dentro de uma faixa razoável; se qualquer condição não for atendida, o reparo é abandonado e o conteúdo original é retornado como está.

***

## 3. Como saber se uma resposta foi reparada

Quando o reparo ocorre, há dois sinais programáveis / consultáveis:

1. **Cabeçalho de resposta** `X-JSON-Repaired: true` (quando não há reparo, esse cabeçalho não existe).
2. **Observação no log de chamadas**: na [página de registros de chamadas](https://console.aihubmix.com/logs), a coluna de observação da requisição correspondente exibe `This request gateway automatically corrected the JSON format issue in the model output.`

O uso de tokens e a cobrança são calculados com base na saída original do modelo; o reparo não altera o resultado da cobrança.

***

## 4. Exemplo completo

Tomando como exemplo a geração de informações de produto, a requisição usa `json_schema` para declarar a saída estruturada; com o controle ativado, mesmo que a saída do modelo apresente os erros de formato descritos acima, o `content` obtido pode ser analisado diretamente:

<CodeGroup>
  ```python Python theme={null}
  import json
  import os
  import requests

  response = requests.post(
      "https://aihubmix.com/v1/chat/completions",
      headers={
          "Authorization": f"Bearer {os.environ['AIHUBMIX_API_KEY']}",
          "Content-Type": "application/json",
      },
      json={
          "model": "gpt-5.2",
          "messages": [
              {"role": "user", "content": "Generate a product listing for a wireless keyboard."}
          ],
          "response_format": {
              "type": "json_schema",
              "json_schema": {
                  "name": "product",
                  "schema": {
                      "type": "object",
                      "properties": {
                          "name": {"type": "string"},
                          "price": {"type": "number"},
                          "description": {"type": "string"},
                      },
                      "required": ["name", "price"],
                      "additionalProperties": False,
                  },
              },
          },
      },
  )

  repaired = response.headers.get("X-JSON-Repaired") == "true"
  product = json.loads(response.json()["choices"][0]["message"]["content"])
  print(product, "repaired:", repaired)
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch("https://aihubmix.com/v1/chat/completions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.AIHUBMIX_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      model: "gpt-5.2",
      messages: [
        { role: "user", content: "Generate a product listing for a wireless keyboard." },
      ],
      response_format: {
        type: "json_schema",
        json_schema: {
          name: "product",
          schema: {
            type: "object",
            properties: {
              name: { type: "string" },
              price: { type: "number" },
              description: { type: "string" },
            },
            required: ["name", "price"],
            additionalProperties: false,
          },
        },
      },
    }),
  });

  const repaired = response.headers.get("X-JSON-Repaired") === "true";
  const data = await response.json();
  const product = JSON.parse(data.choices[0].message.content);
  console.log(product, "repaired:", repaired);
  ```

  ```shell curl theme={null}
  curl -sD - https://aihubmix.com/v1/chat/completions \
    -H "Authorization: Bearer $AIHUBMIX_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-5.2",
      "messages": [
        {"role": "user", "content": "Generate a product listing for a wireless keyboard."}
      ],
      "response_format": {
        "type": "json_schema",
        "json_schema": {
          "name": "product",
          "schema": {
            "type": "object",
            "properties": {
              "name": {"type": "string"},
              "price": {"type": "number"},
              "description": {"type": "string"}
            },
            "required": ["name", "price"],
            "additionalProperties": false
          }
        }
      }
    }'
  ```
</CodeGroup>

Para observar um reparo de forma proativa, você pode definir `max_tokens` com um valor baixo (como `80`) para que a saída seja truncada: o `finish_reason` da resposta será `length`, o `content` será o JSON válido já reparado e o cabeçalho de resposta trará `X-JSON-Repaired: true`.

***

## 5. Limites e observações

<Warning>
  Requisições em streaming (`stream: true`) não são reparadas e são encaminhadas como estão. Quando precisar da capacidade de reparo, use requisições não-streaming.
</Warning>

<Warning>
  O reparo garante que o conteúdo possa ser analisado como JSON; os dados perdidos por truncamento não podem ser recuperados. Recomenda-se verificar também o `finish_reason` / `stop_reason` e, quando a saída for truncada, aumentar o `max_tokens` conforme necessário e tentar novamente.
</Warning>

* **Reparo de sintaxe**: se os nomes e tipos dos campos correspondem ao seu schema ainda precisa ser validado pela aplicação.
* **Parâmetros de chamada de ferramentas fora do escopo do reparo**: o JSON dos parâmetros de `tool_calls` / `function_call` não é reparado; os parâmetros de ferramentas devem sempre ser validados pela aplicação antes da execução.
* **Saída com múltiplos blocos de texto não é reparada**: quando a saída do modelo contém vários blocos de texto (por exemplo, o Gemini retornando vários `parts`), ela é retornada como está.
* **Conteúdo de raciocínio não é afetado**: textos de raciocínio como `reasoning_content` e a parte de thought do Gemini não participam do reparo.

***

## Perguntas frequentes (FAQ)

**O reparo altera os valores numéricos ou o texto do conteúdo retornado?**

Não. O reparo apenas completa ou normaliza a sintaxe do JSON (completa colchetes de fechamento, remove vírgulas finais, normaliza aspas, remove marcadores de bloco de código); os valores numéricos e o conteúdo das strings permanecem no texto original da saída do modelo.

**Ativar o controle afeta requisições comuns que não declaram saída estruturada?**

Não. Requisições que não declaram campos de saída estruturada como `response_format`, bem como todas as requisições em streaming, têm suas respostas retornadas como estão.

**O reparo gera cobrança adicional ou altera o uso de tokens?**

Não. O uso de tokens e a cobrança são calculados com base na saída original do modelo; o processo de reparo não gera custo adicional.

**O JSON reparado certamente corresponde ao schema que defini?**

O reparo garante que o conteúdo possa ser analisado como JSON; se os nomes e tipos dos campos correspondem ao schema depende da própria saída do modelo, por isso recomenda-se manter a validação do schema na aplicação.
