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

# Sorties Structurees (Structured Outputs)

> Contraignez le format de sortie des modeles via JSON Schema (Structured Outputs). Compatible avec OpenAI, Anthropic Claude, Gemini et plus encore -- response_format, output_config.format, degradation automatique et conversion inter-protocoles.

## Apercu des capacites

Les sorties structurees (Structured Outputs) permettent a la reponse du modele de respecter strictement un JSON Schema que vous definissez, garantissant que la valeur retournee peut etre directement analysee par votre programme, sans regex ni post-traitement.

Contrairement a une simple instruction dans le prompt demandant au modele de "retourner du JSON", les sorties structurees reposent sur le **decodage contraint (Constrained Decoding)** : le fournisseur en amont compile le JSON Schema en regles grammaticales qui contraignent la generation token par token lors de l'inference -- le modele **ne peut pas** produire de contenu violant le Schema.

Cas d'usage typiques :

* Extraction d'entites et de champs a partir de texte non structure
* Classification / etiquetage / analyse de sentiments
* Transmission standardisee de resultats intermediaires dans un raisonnement multi-etapes
* Contraintes de typage fort sur les parametres d'appel d'outils d'un Agent

## Correspondance des parametres par protocole

<Note>
  Les noms de parametres different selon les trois protocoles, mais le mecanisme sous-jacent est identique : la sortie du modele correspond strictement au JSON Schema que vous fournissez.
</Note>

| Protocole                          | Parametre                                  | Modeles compatibles                                         |
| ---------------------------------- | ------------------------------------------ | ----------------------------------------------------------- |
| OpenAI Chat `/v1/chat/completions` | `response_format.type: "json_schema"`      | Claude 4.5+, GPT-4o / GPT-5 et successeurs, serie Gemini    |
| Anthropic Messages `/v1/messages`  | `output_config.format.type: "json_schema"` | Claude 4.5+ (direct / Vertex) ; Bedrock uniquement 4.5--4.6 |
| OpenAI Responses `/v1/responses`   | `text.format.type: "json_schema"`          | Selon les capacites du modele en amont                      |

### Limitations AWS Bedrock

Sur AWS Bedrock, les versions de Claude 4.7 et ulterieures utilisent le chemin d'inference Mantle, qui ne prend actuellement pas en charge `output_config.format`. La passerelle supprime automatiquement le champ `format` pour ces modeles et signale la degradation dans un en-tete de reponse (voir [Mecanisme de degradation automatique](#mecanisme-de-degradation-automatique) ci-dessous) -- la requete ne provoquera pas d'erreur.

***

## Demarrage rapide

### Protocole OpenAI (recommande)

Compatible avec tous les modeles prenant en charge les sorties structurees, universel entre fournisseurs.

<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": "Extraire les informations suivantes : Jean Dupont, 28 ans, Paris 15e"}
      ],
      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": "Jean Dupont", "age": 28, "city": "Paris 15e"}
  ```

  ```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: "Extraire les informations suivantes : Jean Dupont, 28 ans, Paris 15e" },
    ],
    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": "Extraire les informations suivantes : Jean Dupont, 28 ans, Paris 15e"}
      ],
      "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>

### Utilisation d'autres modeles (exemple GLM-5.2)

Le meme jeu de parametres du protocole OpenAI s'applique a tous les modeles prenant en charge les sorties structurees -- il suffit de changer le champ `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": "Extraire les informations suivantes : Jean Dupont, 28 ans, Paris 15e"}
    ],
    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": "Jean Dupont", "age": 28, "city": "Paris 15e"}
```

### Protocole natif Claude

Utilisation directe via le SDK Anthropic, avec le parametre `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": "Extraire les informations suivantes : Jean Dupont, 28 ans, Paris 15e"}
      ],
      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": "Extraire les informations suivantes : Jean Dupont, 28 ans, Paris 15e"}
      ],
      "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>

***

## Points cles pour la redaction du Schema

### Champs obligatoires

Tout type `object` doit declarer explicitement `additionalProperties: false`, sinon certains fournisseurs en amont rejetteront la requete.

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

### Objets imbriques

Les `object` imbriques necessitent egalement `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
}
```

### Differences de Schema entre protocoles

| Caracteristique                                     | Protocole OpenAI             | Protocole Anthropic                                                                            |
| --------------------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------- |
| Champ `name`                                        | Obligatoire                  | Non pris en charge (gere automatiquement par la passerelle lors des appels inter-protocoles)   |
| Champ `strict`                                      | Optionnel, `true` recommande | Non pris en charge                                                                             |
| Contraintes numeriques (`minimum`, `maximum`, etc.) | Prises en charge             | Non prises en charge (nettoyees automatiquement par la passerelle, sans impact sur la requete) |
| Contraintes de chaine (`minLength`, `maxLength`)    | Prises en charge             | Non prises en charge (nettoyees automatiquement par la passerelle)                             |

<Tip>
  Lorsque vous appelez un modele Claude via le protocole OpenAI, la passerelle convertit automatiquement le format du Schema et nettoie les mots-cles incompatibles -- aucune adaptation manuelle n'est necessaire.
</Tip>

***

## Mecanisme de degradation automatique

Par defaut, la passerelle active la protection par degradation automatique des sorties structurees pour toutes les requetes. Lorsqu'un modele ou une plateforme ne prend pas en charge cette fonctionnalite, la passerelle **ne renvoie pas d'erreur** mais supprime automatiquement les contraintes de Schema et signale la raison de la degradation dans un en-tete de reponse. Votre requete recevra toujours une reponse normale du modele, mais la sortie ne sera pas soumise aux contraintes strictes du Schema.

Cela signifie que vous pouvez activer les sorties structurees de maniere uniforme cote client sans avoir a gerer la compatibilite pour chaque modele :

* **Changement de modele sans souci** : lorsque le meme code bascule entre Claude, GPT, Gemini et GLM, meme si le modele cible ne prend pas en charge les sorties structurees, la requete ne provoquera pas d'erreur
* **Routage Fallback transparent** : lorsque le canal principal est indisponible et qu'un routage Fallback redirige vers un canal de secours, meme si la version du modele de ce canal ne prend pas en charge les sorties structurees, la requete aboutira normalement
* **Logique client simplifiee** : inutile de maintenir une liste des modeles compatibles avec les sorties structurees, la passerelle gere tout automatiquement ; le client n'a qu'a verifier l'en-tete de reponse pour decider si une analyse supplementaire est necessaire

### En-tetes de reponse

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

| reason                                 | Signification                                                                                      |
| -------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `model_unsupported`                    | Ce modele (ou ce modele sur la plateforme actuelle) ne prend pas en charge les sorties structurees |
| `json_object_unsupported_on_anthropic` | Le mode `json_object` ne peut pas etre converti au format Anthropic                                |
| `json_schema_missing_schema`           | Le type `json_schema` a ete specifie mais le champ `schema` est manquant                           |
| `schema_keywords_stripped`             | Certains mots-cles de contrainte du Schema ont ete nettoyes (par ex. `minimum`, `maxLength`)       |

### Exemple de detection

```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": "Extraire les informations : Jean Dupont, 28 ans"}],
        "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,
                }
            }
        }
    }
)

# Verifier si une degradation a eu lieu (par ex. requete routee vers un canal Bedrock non compatible)
degraded = response.headers.get("X-Structured-Output-Degraded")
if degraded:
    print(f"Sortie structuree degradee : {degraded}")
    # La reponse du modele est toujours normale, mais la sortie n'est pas contrainte par le Schema
else:
    import json
    data = json.loads(response.json()["choices"][0]["message"]["content"])
    print(data)  # {"name": "Jean Dupont", "age": 28}
```

***

## Difference avec le mode `json_object`

|                        | `json_schema` (Sorties structurees)                             | `json_object`                          |
| ---------------------- | --------------------------------------------------------------- | -------------------------------------- |
| Garantie de sortie     | Correspondance stricte avec le Schema specifie                  | Garantit uniquement un JSON valide     |
| Controle des champs    | Noms, types et caractere obligatoire des champs sont contraints | Aucune contrainte                      |
| Protocoles compatibles | OpenAI / Anthropic / Responses                                  | Protocole compatible OpenAI uniquement |
| Support Claude         | Via `output_config.format`                                      | Non pris en charge                     |

<Warning>
  Le mode `json_object` ne peut pas etre converti vers le protocole natif Claude. Si vous envoyez `response_format: {"type": "json_object"}` a Claude via le protocole OpenAI, l'en-tete de reponse signalera une degradation `json_object_unsupported_on_anthropic`. Il est recommande d'utiliser directement le type `json_schema`.
</Warning>

***

## Questions frequentes

<AccordionGroup>
  <Accordion title="Quels modeles prennent en charge les Structured Outputs ?">
    **Serie Claude** (via `output_config.format` de l'API Anthropic) :

    * Opus / Sonnet / Haiku 4.5 et versions ulterieures
    * Fable / Mythos 5 et versions ulterieures
    * Plateforme Bedrock : uniquement 4.5--4.6 ; Vertex AI identique a l'acces direct

    **Serie OpenAI** (via `response_format`) :

    * GPT-4o et versions ulterieures, serie GPT-5

    **Serie Gemini** (via `responseSchema`) :

    * Gemini 2.5 et versions ulterieures

    Vous pouvez consulter les etiquettes de capacites de chaque modele sur la [page de liste des modeles](https://aihubmix.com/models).
  </Accordion>

  <Accordion title="Pourquoi certains modeles Claude sur Bedrock ne prennent-ils pas en charge les sorties structurees ?">
    Sur AWS Bedrock, Claude 4.7+ utilise le nouveau chemin d'inference Mantle, qui n'accepte actuellement pas le parametre `output_config.format`. La passerelle gere cela automatiquement : elle supprime le champ format et renvoie une reponse normale, tout en ajoutant l'en-tete de degradation `X-Structured-Output-Degraded: model_unsupported`. Claude 4.5--4.6 est entierement pris en charge sur Bedrock.
  </Accordion>

  <Accordion title="Le JSON Schema est-il modifie lors d'appels inter-protocoles ?">
    Oui. Lorsque vous appelez un modele Claude via le protocole OpenAI, la passerelle effectue automatiquement :

    1. La conversion de `response_format` en `output_config.format`
    2. La suppression des mots-cles du Schema non pris en charge par Anthropic (`minimum`, `maxLength`, etc.)
    3. Si des mots-cles ont ete nettoyes, l'en-tete de reponse signale `schema_keywords_stripped`

    La conversion inverse (protocole Claude vers modele OpenAI) est egalement automatique.
  </Accordion>

  <Accordion title="Les Structured Outputs peuvent-ils etre utilises simultanement avec Extended Thinking ?">
    Oui. Le champ `format` (sorties structurees) dans `output_config` et le champ `effort` (intensite de reflexion) dans `reasoning` sont des parametres independants qui peuvent etre definis simultanement :

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

  <Accordion title="Quelle est la difference du mecanisme de degradation par rapport a d'autres plateformes d'agregation comme OpenRouter ?">
    La plupart des plateformes d'agregation d'API renvoient directement une erreur lorsqu'un modele ne prend pas en charge les sorties structurees. AIHubMix adopte une strategie de **degradation gracieuse** : suppression automatique des parametres incompatibles, retour normal de la reponse du modele, et notification au client de la raison de la degradation via l'en-tete `X-Structured-Output-Degraded`. Votre application ne sera pas interrompue.
  </Accordion>
</AccordionGroup>
