Chargement

Utilisation stricte d'outils : cessez de rejeter vos propres appels

Leçon 210 min
Chargement

Utilisation stricte d'outils : cessez de rejeter vos propres appels

RésuméTranscription

Lorsque votre backend rejette un appel d'outil que Claude lui-même a produit, l'utilisation stricte d'outils est la solution. La vidéo l'active pour un outil chez Meridian, un cabinet de conseil en ingénierie fictif, et exécute les mêmes 100 requêtes avec cette fonctionnalité désactivée puis activée.

La démonstration de cette vidéo a été enregistrée en septembre 2026. Elle a été exécutée sur Claude Haiku 4.5 (claude-haiku-4-5). Les résultats peuvent différer sur des modèles plus récents.

Claude suit généralement le input_schema d'un outil, mais rien ne l'impose par défaut. Ainsi, il arrive que votre backend rejette un appel d'outil effectué par Claude, car l'entrée de l'appel présente l'un des éléments suivants :

  • La chaîne de caractères "2" au lieu de l'entier 2
  • Un champ obligatoire manquant

L'utilisation stricte d'outils résout ce problème. Un seul indicateur, strict: true, permet de faire correspondre l'entrée que Claude écrit à votre schéma.

Chez Meridian, un assistant utilise l'outil queue_stamp_request pour mettre en file d'attente des jeux de plans en vue du tampon d'un ingénieur agréé. Le validateur de Meridian est le code qui vérifie chaque appel d'outil. Lorsque le mode strict est désactivé, il rejette 79 des 100 requêtes. Lorsque le mode strict est activé et que le schéma est généré à partir du validateur, il n'en rejette aucune.

Fonctionnement de l'utilisation stricte d'outils

Avec strict: true, l'API compile d'abord votre schéma JSON (JSON Schema) en une grammaire. Une grammaire est un ensemble de règles qui indique quels jetons peuvent apparaître ensuite à chaque point de l'entrée. Ensuite, chaque fois que Claude choisit le jeton suivant de l'appel d'outil, il ne peut choisir qu'un jeton autorisé par la grammaire. C'est ce qu'on appelle l'échantillonnage contraint par grammaire.

Le schéma indique que revision est un entier, et Claude a écrit jusqu'à "revision":. Sans le mode strict, cinq jetons suivants peuvent être choisis : 3, "3", three, 3.0, et null. Avec strict: true, seul 3 peut être choisi et les quatre autres sont barrés.

Avec strict: true, seuls les jetons autorisés par votre schéma peuvent être choisis, de sorte qu'un champ entier reçoit un entier.

Voici la définition d'outil de Meridian, simplifiée. Le mode strict nécessite deux de ses lignes : l'indicateur et un paramètre que l'indicateur exige.

json
{
  "name": "queue_stamp_request",
  "description": "Queues a drawing set for a professional engineer's stamp.",
  "strict": true,
  "input_schema": {
    "type": "object",
    "properties": {
      "drawing_set_id": {"type": "string"},
      "revision": {"type": "integer"}
    },
    "required": ["drawing_set_id", "revision"],
    "additionalProperties": false
  }
}
  • "strict": true est l'indicateur. Il se trouve au niveau supérieur, à côté de name, description et input_schema, en dehors du schéma.
  • "additionalProperties": false est le paramètre. Il signifie que l'entrée ne peut pas contenir un champ que le schéma ne nomme pas, et le mode strict l'exige sur chaque objet.

Générez le schéma à partir de votre validateur

L'utilisation stricte d'outils fait correspondre l'entrée que Claude écrit à votre schéma, le schéma doit donc dire ce que dit votre validateur. Lorsque vous rédigez le schéma à la main, les deux finissent par diverger. Un appel d'outil peut alors correspondre au schéma tout en étant rejeté. Chez Meridian, un schéma rédigé à la main faisait du numéro de licence une simple chaîne de caractères sans pattern. Ainsi, "PE 46196" passait le schéma mais échouait au validateur, qui exige PE- suivi de cinq chiffres.

Écrivez les règles une seule fois, dans votre validateur, et générez le schéma à partir de celui-ci. En Python, le validateur est généralement une classe Pydantic. En TypeScript, il est généralement écrit avec Zod.

Voici la classe Pydantic de Meridian, StampRequest, accompagnée du code qui l'utilise, puis le schéma que renvoie StampRequest.model_json_schema(). Chaque # ... représente du code non affiché, et le schéma ne montre que le numéro de licence.

python
class StampRequest(BaseModel):
    model_config = {"extra": "forbid"}
    # ...
    pe_license_number: str | None = Field(pattern=r"^PE-\d{5}$")
    # ...
stamp_tool = {
    # ...
    "input_schema": StampRequest.model_json_schema(),
    "strict": True,
}
stamp_request = StampRequest.model_validate(call.input)
json
{
  "additionalProperties": false,
  "properties": {
    "pe_license_number": {
      "anyOf": [
        {"pattern": "^PE-\\d{5}$", "type": "string"},
        {"type": "null"}
      ],
      "title": "Pe License Number"
    }
  }
}
  • "extra": "forbid" devient "additionalProperties": false, le paramètre exigé par le mode strict.
  • str | None devient anyOf, de sorte que le numéro de licence est soit une chaîne de caractères correspondant à ce pattern, soit null.
  • model_validate() vérifie call.input, l'entrée écrite par Claude, par rapport à la même classe.

Comparez les exécutions avec le mode strict désactivé et activé

Le test de Meridian envoie 100 demandes de tampon en langage naturel à Claude Haiku 4.5 avec l'outil queue_stamp_request, et StampRequest valide chaque appel d'outil. Les mêmes 100 requêtes sont exécutées deux fois : d'abord avec un schéma rédigé à la main et le mode strict désactivé, puis avec le schéma généré et le mode strict activé.

Rejouez les deux exécutions ci-dessous.

Chargement

Le pattern du schéma indique le format autorisé, et le mode strict oblige Claude à s'y conformer.

Le mode strict contrôle la forme de l'entrée mais ne peut pas fournir un fait que la requête n'a jamais donné. Sur les 100 requêtes, 28 ne mentionnent jamais de licence. Le schéma généré autorise null pour le numéro de licence, et les 28 sont revenues avec null.

Limites de l'utilisation stricte d'outils

Six points à connaître, à compter d'octobre 2026 :

  1. N'incluez pas d'informations de santé protégées (PHI). Les schémas compilés ne bénéficient pas des mêmes protections PHI que les requêtes et les réponses. Évitez donc d'inclure des PHI dans les noms de propriétés, les valeurs enum, les valeurs const et les expressions pattern.
  2. Les bornes ne sont pas prises en charge. Une requête dont le schéma utilise minimum, maximum, minLength ou maxLength renvoie une erreur 400. Vérifiez les bornes dans une fonction de validation, comme le @field_validator de Pydantic, et mentionnez-les dans la description du champ.
  3. Les limites s'additionnent sur l'ensemble des outils. Une requête peut contenir au maximum 20 outils stricts. Sur l'ensemble de ces outils, elle peut contenir au maximum 24 paramètres facultatifs. Elle peut également contenir au maximum 16 paramètres utilisant anyOf ou un tableau de types, ce que génère un champ nullable tel que str | None.
  4. L'entrée peut tout de même ne pas correspondre au schéma. Cela se produit après un refus, lorsqu'une réponse est tronquée au niveau de max_tokens, ou lorsqu'une chaîne enum ou const revient avec une capitalisation différente.
  5. Certains modèles rejettent un appel d'outil forcé. Définir tool_choice sur any ou tool force un appel d'outil. Cela renvoie une erreur 400 sur Claude Opus 5.5, Claude Sonnet 5.5, Claude Fable 5.1 et Claude Mythos 5.1. Sur ces modèles, laissez tool_choice sur auto, sa valeur par défaut.
  6. L'appel programmatique d'outils ne peut pas utiliser d'outils stricts. Dans l'appel programmatique d'outils, Claude écrit du code qui appelle vos outils. Cela est abordé dans la leçon 8.

Points clés à retenir

  • strict: true fait correspondre l'entrée de l'outil à votre schéma, sauf après un refus ou une réponse tronquée, ou lorsqu'une chaîne enum ou const change de casse.
  • Générez le schéma à partir de votre validateur, comme une classe Pydantic.
  • N'incluez pas de bornes dans le schéma, et comptez les outils, les paramètres facultatifs et les paramètres nullables sur l'ensemble de la requête.