Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Configuration du fournisseur

Chaque fournisseur de modèle se trouve dans [providers.models.<type>.<alias>]. <type> est un emplacement de famille canonique (consultez le Catalog pour chaque emplacement avec son point de terminaison). <alias> est le nom d’instance attribué par l’opérateur, choisissez n’importe quel nom descriptif (home, work, cn, gpt5, …).

Exemple de travail minimal

La configuration minimale qui se charge sans erreur comporte quatre en-têtes de section : une entrée de fournisseur, un agent qui y fait référence, et un profil de risque sur lequel l’agent applique ses contrôles. Configurez-les via la passerelle, zerocode ou zeroclaw config set ; la référence de configuration contient l’index complet des champs.

Référence des champs : entrée de fournisseur

Presque chaque famille reprend également les champs communs de ModelProviderConfig :

  • api_key : identifiant pour les fournisseurs qui utilisent des clés API de type bearer ou d’abonnement.
  • uri : surcharge complète de l’endpoint. Laisser non défini pour utiliser le résolveur d’endpoint de la famille.
  • model : identifiant du modèle envoyé au fournisseur.
  • temperature : température d’échantillonnage optionnelle.
  • timeout_secs : délai d’expiration de la requête HTTP en secondes. Une valeur supérieure à 300 augmente aussi la limite d’inactivité du flux du fournisseur (la limite par défaut de 300 secondes sur l’intervalle entre deux lectures du flux) pour OpenAI Responses et les fournisseurs compatibles OpenAI.
  • max_tokens : limite optionnelle de la longueur de la réponse.
  • extra_headers: en-têtes HTTP supplémentaires pour des passerelles personnalisées ou des ponts d’authentification.
  • fallback_models : identifiants de modèles alternatifs sur le même alias de fournisseur.
  • fallback: liste ordonnée d’autres alias de fournisseurs en notation pointée à essayer après l’échec de cet alias.
  • wire_api, native_tools, provider_extra, think, thinking_passthrough, et chat_template_kwargs : remplacements avancés du protocole et du corps de requête.
  • vision : remplace la capacité d’entrée d’image (vision) du fournisseur. Laissez cette option non définie pour utiliser la valeur par défaut intégrée à la famille. Définissez false pour un modèle purement textuel servi par une famille compatible avec la vision (par exemple, un modèle texte derrière llama.cpp) afin que les messages contenant des images soient routés vers un [multimodal] vision_model_provider configuré au lieu de provoquer une erreur ; définissez true pour forcer la vision. Sans fournisseur de vision configuré, un tour sans vision se poursuit en remplaçant les marqueurs de médias par un espace réservé lorsqu’aucune des références d’image du dernier message utilisateur ne passe les vérifications d’existence, de structure d’URI de données ou de politique de récupération distante (un fichier manquant, un URI de données malformé, ou une URL distante alors que multimodal.allow_remote_fetch est désactivé). Un chemin local n’est pris en compte que s’il est absolu, autorisé par la politique du système de fichiers de l’agent (la même vérification que celle appliquée par les outils de fichiers) et qu’il existe en tant que fichier ; les chemins rejetés par la politique ne sont jamais sondés. Si une référence passe, le tour échoue tout de même avec l’erreur de capacité de vision. La vérification de résolvabilité évalue au plus 16 marqueurs de chemin local absolus par tour ; pour ceux-ci, la vérification de politique et la sonde d’existence s’exécutent ensemble sur un thread bloquant, en dehors de l’exécuteur asynchrone. Un message comportant davantage de tels marqueurs traite les autres comme résolvables sans aucune vérification, de sorte qu’un message trop volumineux échoue vers l’erreur de capacité plutôt qu’une dégradation silencieuse.
  • tool_result_image_policy : gestion des images jointes aux résultats natifs role = "tool" envoyés aux fournisseurs compatibles chat-completions. Les images d’un résultat d’outil sont déclarées dans un tableau attachments à côté du texte du résultat, dans le conteneur de résultat d’outil ; elles ne sont jamais extraites du texte du résultat lui-même, de sorte que la syntaxe de marqueur littérale dans la sortie d’un outil n’est que du texte. Valeur par défaut "image_url" (envoyer les images déclarées sous forme de parties image_url) ; définir "omit" pour les supprimer et ajouter un avis fixe. La politique ne lit que le tableau attachments des conteneurs natifs ; un résultat d’outil hérité (sans clé de tableau) est transmis tel quel avec les deux paramètres, car il ne déclare rien et son contenu est du texte. Cela ne modifie pas les images envoyées directement par l’utilisateur ni les fournisseurs OpenAI Responses.
  • cache_passthrough : active le cache de prompts Anthropic sur les passerelles chat-completions qui traduisent vers l’API Messages d’Anthropic. Ajoute au plus deux points de rupture cache_control par requête et remonte dans l’usage des tokens les lectures de cache signalées par la passerelle. Valeur par défaut false, requêtes inchangées. Nécessite une qualification de la route avant toute utilisation en production ; voir Prompt cache passthrough.
  • cache_ttl : durée de vie d’une entrée de cache demandée pour les marqueurs de cache d’Anthropic. "5m" (par défaut) ou "1h". Ce paramètre s’applique directement au fournisseur natif Anthropic, ainsi qu’aux passerelles chat-completions derrière cache_passthrough ; sans passthrough, il est sans effet. Les fournisseurs qui émettent leurs propres marqueurs de cache par d’autres moyens (openrouter) ignorent ce paramètre. Voir Choisir une durée de vie de cache de 1h.
  • tls_ca_cert_path : chemin absolu vers un certificat CA encodé en PEM pour les connexions TLS à ce fournisseur (une surcharge de confiance par fournisseur, distincte du ca_cert_path TLS de la passerelle). L’expansion shell telle que ~ n’est pas effectuée ; laisser non défini pour utiliser le magasin de confiance du système.

Les entrées spécifiques à la famille ajoutent leurs propres champs typés en plus de ces champs partagés.

Passthrough de la réflexion Anthropic

thinking_passthrough = true sur une entrée de fournisseur compatible OpenAI active pour cet alias le passthrough de la réflexion étendue d’Anthropic : le budget de réflexion du runtime est transmis à la passerelle, les réponses de réflexion de la passerelle sont normalisées en blocs signés rejouables, et les blocs signés sont rejoués dans l’historique sortant.

Avant d’utiliser cet indicateur, vérifiez si la passerelle expose aussi un endpoint Anthropic Messages. Si c’est le cas, créez une entrée [providers.models.anthropic.<alias>] pointant vers cet endpoint avec uri : le fournisseur natif gère le raisonnement (thinking), la relecture des blocs signés et la mise en cache des prompts sans traduction. thinking_passthrough est destiné aux passerelles qui n’offrent que l’interface Chat Completions.

[providers.models.custom.my-gateway]
uri = "https://your-gateway.example.com"
model = "claude-group/claude-fable-5"
api_key = "..."
wire_api = "chat_completions"
thinking_passthrough = true

Ce que cela fait

  • Côté requête : lorsque le runtime fournit des paramètres de réflexion natifs, les corps de requête reçoivent au niveau supérieur un objet au format Anthropic : {"thinking": {"type": "enabled", "budget_tokens": N}}. Une clé provider_extra explicite prévaut toujours sur l’objet injecté, ce qui permet de figer une forme personnalisée via cette échappatoire. La normalisation de temperature et de max_tokens suit l’objet effectivement envoyé : ainsi, un {type = "off"} explicite conserve votre température et votre limite, et un objet enabled explicite avec son propre budget_tokens relève max_tokens au-dessus de ce budget. Lorsqu’un objet de réflexion est injecté, la température de la requête est fixée à 1.0, comme l’exige Anthropic ; les températures explicites ne s’appliquent que lorsque la réflexion est désactivée. Lorsqu’un budget de réflexion fixe est injecté, max_tokens est de même relevé à budget_tokens + 1 si la limite configurée ne lui est pas supérieure, comme l’exige Anthropic.
  • Capture : les réponses de réflexion de la passerelle sont normalisées dans le même format JSON signé, délimité par des sauts de ligne, que le fournisseur Anthropic natif stocke dans reasoning_content (une ligne {"thinking": ..., "signature": ...} par bloc). Les blocs ne contenant que une signature (texte vide, signature valide : la forme émise par TrueFoundry) sont conservés. Lorsque le drapeau est désactivé, les réponses de la passerelle contenant reasoning_content / thinking_blocks sont traitées exactement comme auparavant ; le comportement de raisonnement de DeepSeek, GLM et Qwen reste donc inchangé.
  • Rejeu : l’historique signé reconstruit un tableau thinking_blocks sur les messages assistant sortants et supprime les champs de type chaîne. La reconstruction est tout ou rien ; voir la limitation ci-dessous. La surcharge replay_assistant_reasoning = false reste prioritaire : les fournisseurs qui rejettent les entrées de raisonnement ne reçoivent rien, quelle que soit la combinaison de drapeaux.

Exigences et limitations

  • Nécessite une passerelle de traduction. Cet indicateur n’a de sens que pour les points de terminaison compatibles OpenAI qui traduisent entre l’API OpenAI Chat Completions et l’API Anthropic Messages (LiteLLM documente cette traduction ; le format a été vérifié sur une passerelle TrueFoundry en service). Lorsqu’il pointe vers un upstream sans traduction, l’objet thinking injecté est un paramètre inconnu et la requête échoue avec HTTP 400. C’est le mode de défaillance prévu : bruyant, dès la première requête, et non silencieux.
  • Une réflexion non signée invalide le rejeu. Les blocs de réflexion qu’Anthropic accepte en entrée doivent porter une signature valide. Un historique dont le raisonnement n’est pas signé (texte diffusé en flux, ou passerelle qui supprime les signatures) n’envoie aucun raisonnement, plutôt que de fabriquer des blocs qu’une passerelle rejetterait : toute ligne non analysable ou toute ligne de réflexion sans signature annule le rejeu de l’ensemble du message (aucune séquence partielle). Les blocs redacted_thinking structurellement invalides (sans charge utile data) sont omis individuellement, tandis que leurs frères valides sont rejoués. La liste blanche des blocs capturés se limite exactement à thinking (texte et/ou signature requis) et redacted_thinking (data opaque requis, rejoué tel quel et sans signature par conception) ; tout autre type de bloc émis par une passerelle est ignoré à la capture et n’est jamais transmis lors du rejeu. Le chemin de repli guidé par le prompt rejoue les mêmes blocs validés, de sorte qu’un second repli de schéma n’abandonne pas la trajectoire signée.
  • Les blocs de contenu imbriqués ne sont pas capturés. Seuls les champs reasoning_content, reasoning et thinking_blocks de premier niveau sont lus. Les blocs au format Anthropic imbriqués dans un tableau content ne sont pas capturés ; ouvrez une issue avec un exemple de trafic réseau si votre passerelle en émet.
  • Le passthrough désactive le streaming sur la feuille. La normalisation des captures s’applique aux réponses non streaming, et les trames SSE de réflexion du gateway n’ont pas encore été vérifiées. Le fournisseur se déclare donc non streaming : lorsqu’il est le fournisseur qui sert la requête, toute la boucle d’outils s’exécute sur le canal non streaming, où la capture signée et le rejeu restent corrects. Deux cas limites existent. Un Router qui résout ce fournisseur exécute son chemin non streaming et synthétise les événements de streaming standard. Un domaine de fiabilité contenant un fournisseur de repli compatible streaming peut servir le tour via ce repli (en affichant l’avis de repli standard). Les opérateurs qui exigent que chaque tour passe par le fournisseur ayant activé l’option doivent donc configurer un domaine entièrement non streaming. Le streaming tour par tour sur la feuille reprendra lorsque la prise en charge du streaming en mode filaire natif sera disponible.
  • La forme de la réflexion suit le modèle. L’objet injecté correspond à la résolution de style du fournisseur natif : les modèles à budget fixe reçoivent {"type": "enabled", "budget_tokens": N}, tandis que les modèles adaptatifs uniquement (Opus 4.7, toute la famille Fable 5) reçoivent {"type": "adaptive"} sans clé de budget. Les identifiants de modèle de la passerelle peuvent comporter des préfixes de routage (claude-group/...) ; la résolution s’effectue par sous-chaînes, de sorte que les identifiants préfixés aboutissent à la même forme que les noms nus. Lorsque l’environnement d’exécution demande un mode d’affichage, la clé display en snake_case s’ajoute aux deux formes (omitted, updates, summarized) ; si aucun affichage n’est demandé, la clé est omise entièrement.
  • Porte de sortie : pour les formes que cette fonctionnalité ne couvre pas, provider_extra fusionne toujours du JSON arbitraire de premier niveau dans chaque corps de requête, y compris un objet thinking statique, à vos risques et périls, sans aucune gestion de la réponse.

Voir aussi

  • Réflexion étendue native avec le fournisseur Anthropic : #10542.
  • Échappatoire pour le corps de requête : provider_extra ci-dessus ; référence.

Ordre de résolution des champs

Pour la plupart des familles, l’URL est résolue dans cet ordre :

  1. Substitution opérateur : champ uri sur l’entrée d’alias, s’il est défini.
  2. Endpoint de famille : l’énumération *Endpoint de la famille fournit l’URL (par ex. OpenAIEndpoint::Default -> https://api.openai.com/v1). Les familles multi-régions disposent d’un champ endpoint sur l’entrée d’alias qui sélectionne la variante (par ex. endpoint = "cn" pour Moonshot).
  3. Familles basées sur des modèles : Azure accepte des entrées typées (resource, deployment, api_version) et les substitue dans le modèle d’URI de la famille. Les champs manquants échouent explicitement à l’exécution.

Bedrock est une exception : le nom d’hôte de son point de terminaison est construit au moment de la requête à partir de la région de signature résolue via la chaîne d’identifiants AWS (AWS_REGION, AWS_DEFAULT_REGION, ou la region du profil credential_process ou IMDS actif). Le champ d’alias uri et le champ providers.models.bedrock.<alias>.region au niveau du schéma n’ont aucun effet dans l’implémentation actuelle.

Emplacements familiaux

Chaque slot, son endpoint par défaut et son exécution locale ou non figurent dans le Catalogue. Il existe une clé canonique par fournisseur : pas de synonymes.

Identifiants

Formes de saisie et de stockage des identifiants prises en charge :

  1. api_key = "..." en ligne dans l’entrée d’alias (acceptable en développement, risqué pour les configs versionnées).
  2. Références 1Password : définissez un champ secret sur op://vault/item/field. ZeroClaw conserve la référence dans la configuration et la résout à l’exécution avec op read, le CLI 1Password doit donc être installé et connecté.
  3. Magasin de secrets au niveau de la configuration : chiffré dans ~/.zeroclaw/secrets via un fichier de clé local.
  4. Substitution générique via variable d’environnement : ZEROCLAW_providers__models__<type>__<alias>__api_key=... définit providers.models.<type>.<alias>.api_key au démarrage. Consultez Variables d’environnement pour la grammaire complète.

Les substitutions d’environnement schema-mirror prévalent au démarrage. Elles remplacent l’identifiant en mémoire pour ce processus sans réécrire la valeur stockée inline, chiffrée ou op:// sur le disque.

zeroclaw quickstart écrit les identifiants dans le magasin de secrets par défaut. Les configurations que vous validez ne doivent pas contenir de clés en ligne. Pour les noms par défaut de l’écosystème que vous exportez déjà dans votre shell ($ANTHROPIC_API_KEY, $OPENROUTER_API_KEY, …), la référence env-vars présente les expansions bash d’une seule ligne qui font pointer un nom miroir du schéma vers la valeur existante.

Authentification OAuth et authentification par abonnement

Plusieurs fournisseurs acceptent des jetons OAuth ou de type abonnement au lieu de clés API brutes. Obtenez le jeton depuis le tableau de bord ou le flux CLI du fournisseur, puis insérez-le dans l’entrée d’alias de la même manière qu’une clé API :

  • Anthropic / Claude : Les clés API et les jetons de la console générés par claude setup-token pour Claude Max se placent dans api_key sur [providers.models.anthropic.<alias>]. Dans le Quickstart, choisissez api_key ou setup_token ; l’entrée de fournisseur enregistrée correspond toujours au champ canonique anthropic.
  • Abonnement OpenAI Codex : exécutez zeroclaw auth login --model-provider openai-codex (ou importez une connexion CLI Codex existante avec --import ~/.codex/auth.json), puis définissez requires_openai_auth = true et laissez api_key non défini dans [providers.models.openai.<alias>] ; le runtime lit le profil d’authentification openai-codex stocké par ZeroClaw.
  • Gemini CLI : [providers.models.gemini_cli.<alias>] délègue l’exécution à la CLI gemini ; utilisez le flux d’authentification propre à la CLI.
  • Grok Build CLI : [providers.models.grok_cli.<alias>] exécute une commande externe via l’interface ACP documentée grok agent stdio. Le prompt assemblé est transmis sous forme de JSON-RPC sur stdin, jamais via argv ni par un fichier de prompt. L’authentification utilise par défaut le cache de connexion de la CLI. Pour l’authentification par clé API, exportez XAI_API_KEY dans l’environnement du démon et ajoutez explicitement env_passthrough = ["XAI_API_KEY"] à l’alias ; l’alias typé api_key reste non pris en charge. Un working_directory absolu et existant est requis et définit à la fois le cwd du processus enfant et la limite de session ACP. L’environnement du processus enfant est vidé avant son lancement, et env_passthrough est vide par défaut. Les autres variables XAI_* appartenant au fournisseur et toutes les variables GROK_* sont rejetées. ZeroClaw utilise par défaut --sandbox strict, --permission-mode dontAsk, un ensemble vide d’outils intégrés et des réponses d’autorisation ACP qui refusent en cas d’échec. extra_args est l’activation explicite propre à chaque alias pour assouplir ces contrôles. Les options de contournement --always-approve, --dangerously-skip-permissions, --yolo et --permission-mode=bypassPermissions amènent le client ACP sans interface à sélectionner allow_once ; les autres modes d’autorisation continuent d’entraîner la sélection de reject_once. Les options ACP de transport, de modèle, de session et de cwd, ainsi que les arguments positionnels et courts, sont réservés ; les options longues inconnues qui prennent une valeur utilisent --flag=value. L’alias vision = true ne fait qu’autoriser ZeroClaw à envoyer des blocs d’image ACP ; Grok continue d’annoncer promptCapabilities.image = false jusqu’à la version 0.2.118 incluse et n’utilise pas de manière fiable le contenu de l’image — laissez ce paramètre non défini en production ; voir vision ACP / entrée d’image.
  • Qwen / MiniMax : définissez auth_mode = "o_auth" dans l’entrée d’alias, ainsi que les champs oauth_* pertinents (voir env-vars → OAuth et champs de chemin CLI).

Configuration d’OpenAI Astra

L’identifiant de modèle public de l’API OpenAI est gpt-6-astra. Le guide du modèle exige l’API Responses pour l’appel d’outils et répertorie temperature parmi les paramètres non pris en charge. Configurez la route de l’API publique sur un alias openai avec une clé API et un protocole Responses explicite :

[providers.models.openai.astra_api]
api_key        = "op://platform/openai/api-key"
model          = "gpt-6-astra"
wire_api       = "responses"
vision         = true
context_window = 1050000
max_tokens     = 32000

[runtime]
reasoning_effort = "high"

[runtime_profiles.astra]
agentic             = true
max_tool_iterations = 12
max_history_messages = 80
max_context_tokens  = 200000

[agents.astra]
model_provider  = "openai.astra_api"
runtime_profile = "astra"
risk_profile    = "supervised"

Les valeurs numériques ci-dessus correspondent à un budget local intentionnel, et non à une recommandation de remplir la fenêtre annoncée par le modèle. L’entrée du fournisseur enregistre la capacité du point de terminaison et le plafond de sortie, tandis que le profil d’exécution conserve un budget d’entrée estimé plus petit et borne la boucle d’outils. Ajustez-les selon la charge de travail et laissez une marge pour la sortie. Les champs ont des responsables distincts :

  • providers.models.openai.astra_api.context_window enregistre la fenêtre d’entrée du modèle utilisée par la gestion budgétaire tenant compte du fournisseur.
  • providers.models.openai.astra_api.max_tokens limite la sortie générée ; ce n’est pas une limite de l’historique d’entrée.
  • runtime_profiles.astra.max_context_tokens est le seuil estimé de réduction locale de ZeroClaw. Il peut être inférieur à context_window.
  • runtime_profiles.astra.max_tool_iterations limite la boucle d’outils agentique, tandis que max_history_messages borne séparément les tours utilisateur complets conservés, y compris leurs échanges d’outils. Le cache d’expéditeurs du canal conserve sa propre limite basée sur les lignes.
  • runtime.reasoning_effort est le niveau de raisonnement global transmis au fournisseur. ZeroClaw accepte actuellement minimal, low, medium, high et xhigh. L’API publique d’Astra accepte low, medium, high, xhigh et max, donc utilisez une valeur commune en attendant que la prise en charge de max pour le raisonnement soit disponible.

Ne définissez pas temperature du fournisseur pour Astra. L’adaptateur Responses transmet la valeur configurée et ne corrige pas les paramètres d’échantillonnage non pris en charge. Distinguez les erreurs de validation de l’API des restrictions liées au compte, au palier d’utilisation, à la région ou à l’accès au backend.

vision = true est l’affirmation de l’opérateur selon laquelle ce modèle et ce point de terminaison exacts acceptent les entrées d’image. La spécification publique du modèle Astra indique actuellement la prise en charge des entrées d’image, mais vérifiez le compte et le point de terminaison configurés avant de l’activer. La sérialisation des images dans les résultats d’outils constitue une frontière d’adaptateur distincte, suivie dans #9599.

La route d’abonnement Codex utilise requires_openai_auth = true au lieu d’une clé API, et doit utiliser un ID de modèle exact servi par ce backend. La disponibilité publique de l’API ne garantit pas la disponibilité sur le backend Codex : suivez le guide de l’abonnement Codex et testez le compte avant de router le trafic de production.

L’API publique peut prendre en charge des fonctionnalités que ZeroClaw n’expose pas encore pour cet adaptateur. Suivez la continuité de l’état de raisonnement dans #10706, les outils de fonction asynchrones dans #10704, le guidage de réponse active dans #10708, et l’appel programmatique d’outils dans #10707. Ce sont des propositions tant que leurs implémentations ZeroClaw et routes de fournisseur n’ont pas été vérifiées.

Remplacements adaptés aux conteneurs

Lorsque ZeroClaw s’exécute dans un conteneur et qu’un fournisseur se trouve sur l’hôte (par ex. Ollama), définissez uri sur une adresse accessible depuis l’hôte. Le mécanisme générique de surcharge par variables d’environnement (ZEROCLAW_<dotted_path_with_double_underscores>=<value>) peut définir le même champ à l’exécution sans modifier la configuration :

sh

ZEROCLAW_providers__models__ollama__home__uri=http://ollama:11434 zeroclaw agent -a assistant

__ est le séparateur de chemin ; l’exemple ci-dessus définit providers.models.ollama.home.uri. Consultez Variables d’environnement pour la grammaire complète.

Capacité de vision par modèle

Utilisez vision lorsqu’une famille de fournisseurs peut servir à la fois des modèles multimodaux et des modèles texte uniquement. La valeur appartient à l’alias du fournisseur, de sorte que les chemins de routage et de repli la résolvent en même temps que le point de terminaison, les identifiants et le modèle de cet alias :

[providers.models.openai.vision]
model = "gpt-4o"
wire_api = "responses"
vision = true

[providers.models.llamacpp.text]
model = "qwen3-4b"
vision = false

Laisser vision non défini préserve la valeur par défaut intégrée de la famille de fournisseurs. Pour les alias OpenAI Responses, définissez vision = true pour les modèles qui acceptent les entrées d’image ; cette activation explicite empêche que des modèles Responses uniquement textuels reçoivent accidentellement des charges utiles d’image.

Le paramètre vision = true est une affirmation explicite de l’opérateur selon laquelle l’alias sélectionné accepte les entrées d’image. Il modifie le routage des images : ZeroClaw conserve les pièces jointes d’image sur cet alias au lieu de les traiter comme du texte uniquement ou de les acheminer vers multimodal.vision_model_provider. Ne le définissez que pour une combinaison fournisseur et modèle testée. Pour grok_cli, le même champ contrôle uniquement si ZeroClaw envoie des blocs d’images ACP ; il ne modifie pas l’annonce promptCapabilities.image de Grok (toujours false jusqu’à la version 0.2.118) et ne permet pas à la CLI de décrire l’image de manière fiable. Voir vision ACP / entrée d’image.

Lorsque [multimodal] vision_model_provider désigne un alias de fournisseur avec point, son model est utilisé automatiquement. Un [multimodal] vision_model explicite est prioritaire sur le modèle de l’alias ; si aucun n’est défini, le modèle de tour principal est utilisé pour des raisons de rétrocompatibilité.

Affichage natif du raisonnement (Anthropic)

agent.thinking.display contrôle la manière dont le raisonnement étendu d’Anthropic est transmis lorsque le raisonnement natif est activé (agent.thinking.native_thinking = true). Valeurs acceptées :

  • off (par défaut) : aucun champ display n’est envoyé ; les requêtes sont identiques au niveau des octets à celles des versions précédentes de ZeroClaw et les requêtes de réflexion utilisent le mécanisme de secours sans streaming.
  • omitted : Anthropic omet le texte de réflexion de la réponse ; les blocs ne contiennent que la signature (thinking vide, signature requise), ce qui préserve la relecture tout en réduisant au minimum le raisonnement visible.
  • updates : la requête inclut la version bêta thinking-display-updates-2026-08-18 et utilise le chemin de réponse en streaming. La progression lisible de la réflexion est affichée en direct pendant que le modèle travaille ; la charge utile de raisonnement signée est conservée séparément pour la relecture de l’historique et n’est jamais affichée.
  • summarized : même comportement de streaming, en demandant un raisonnement résumé.
[agent.thinking]
native_thinking = true
display = "updates"

Ce paramètre nécessite un compte Anthropic inscrit au programme bêta thinking-display-updates ; sans inscription, l’API rejette la requête. Définissez display = "off" (ou supprimez le champ) pour revenir au comportement précédent au niveau du protocole.

Passthrough du cache de prompts (passerelles chat-completions)

cache_passthrough = true sur un alias de fournisseur chat-completions active la mise en cache des invites Anthropic pour ses requêtes. Utilisez-le avec les passerelles qui traduisent Chat Completions vers l’API Anthropic Messages (LiteLLM, TrueFoundry, et similaires) ; la famille Anthropic native met déjà en cache par défaut et ignore ce champ.

Avant d’utiliser ce flag, vérifiez si la passerelle expose aussi un endpoint Anthropic Messages. Si c’est le cas, pointez une entrée [providers.models.anthropic.<alias>] vers celui-ci avec uri et ignorez complètement le passthrough : le provider natif place ses propres breakpoints de cache. cache_passthrough est destiné aux passerelles qui n’offrent que la surface Chat Completions.

Lorsque l’option est activée, les requêtes reçoivent au plus deux points d’arrêt cache_control : un sur le prompt système, et un point d’arrêt glissant sur le dernier message une fois que la conversation compte plus d’un message non système, soit la même condition que celle appliquée par le fournisseur natif Anthropic. Pour un message qui se termine par une image, le point d’arrêt glissant se place sur le dernier bloc de texte du message ; l’image est couverte par le tour suivant. Avec merge_system_into_user, le rôle system n’atteint jamais le réseau, donc le premier message utilisateur fusionné (ou le message utilisateur synthétique portant le texte système) porte à la place le point d’arrêt équivalent au système. Seuls les messages portant un point d’arrêt voient leur sérialisation modifiée.

La case d’option s’applique aussi aux chemins de requêtes structurées : les tours d’agent, les appels d’outils et le streaming structuré. Les helpers texte seul (chat_with_system, chat_with_history, les anciennes API de flux par fragments) n’émettent volontairement aucun point de rupture, même lorsque l’option est activée, car leurs réponses ne renvoient aucune donnée d’utilisation de tokens. Une écriture de cache premium déclenchée par ces helpers ne pourrait jamais apparaître dans la comptabilité. Sur ces helpers, l’option est sans effet, ce qui signifie aussi que les ré-entrées de repli qui passent par eux envoient des requêtes non marquées. Avec l’option désactivée (valeur par défaut), les corps de requête sont identiques octet pour octet à ceux des versions précédentes.

[providers.models.custom.claude-via-gateway]
uri = "https://<gateway-host>/v1"
model = "<anthropic-routed model>"
api_key = "op://platform/gateway/api-key"
cache_passthrough = true

Prérequis et mises en garde :

  • Le support de la passerelle est requis. Le point de rupture n’atteint Anthropic que si la passerelle transmet le contenu sous forme de blocs avec cache_control vers l’API Messages native. Les routes qui relaient l’API OpenAI proprement dite ignorent ce champ. Un modèle non routé vers Anthropic derrière la même passerelle n’échoue pas bruyamment : le champ est accepté puis supprimé, et la passerelle peut tout de même comptabiliser les jetons d’écriture de cache sur cette route dans sa propre facturation d’utilisation. Attribuez plutôt un alias dédié aux modèles routés vers Anthropic, au lieu d’activer l’indicateur sur une entrée mixte.
  • Taille et TTL. Anthropic ne met en cache que les préfixes d’au moins 1024 tokens (2048 sur certains modèles plus petits), et les entrées expirent après environ cinq minutes, rafraîchies à chaque lecture. Les conversations courtes ou peu fréquentes n’en tirent aucun bénéfice. La durée de vie est configurable par fournisseur avec cache_ttl ; voir Choosing a 1h cache lifetime.
  • Les écritures coûtent cher. Les jetons écrits dans le cache sont facturés à un tarif supérieur au prix d’entrée ; la route observée facture les écritures du cache par défaut de 5 minutes à 1,25x. Les écritures avec une durée de vie de 1 h peuvent être facturées à un tarif différent ; voir Choosing a 1h cache lifetime pour le chiffre de planification. Les lectures sont beaucoup moins chères. Une route qui écrit le cache à chaque requête sans jamais le lire coûte plus cher que si aucun cache n’était utilisé.
  • Vérifier d’abord la route exacte. Une passerelle expose plusieurs alias de modèle pour un même compte amont, et un alias qui accepte et facture les écritures de cache peut tout de même ne jamais servir de lectures de cache. Avant de vous fier au paramètre en production, envoyez une requête avec le paramètre, et vérifiez que l’usage renvoie cache_creation_input_tokens > 0 ; puis répétez immédiatement la requête strictement identique et vérifiez cache_read_input_tokens > 0. Une simple création de cache n’est pas une preuve que la mise en cache fonctionne. Relancez ce test par paire après toute modification de l’alias de modèle ou de la route de la passerelle.
  • Rapport d’utilisation. Lorsque la passerelle transmet les compteurs d’utilisation au format Anthropic, cache_read_input_tokens alimente la valeur d’entrée mise en cache dans le rapport d’utilisation des tokens et des coûts, et cache_creation_input_tokens est écrit dans le journal de débogage uniquement sous forme de compteurs. Une réponse qui signale zéro lecture de cache conserve la valeur mise en cache à zéro, sans se replier sur le compteur au format OpenAI. Cette comptabilisation ne couvre que les chemins structurés, ce qui explique précisément pourquoi les helpers sans capture d’utilisation restent inactifs plus haut.
  • Les définitions d’outils ne sont pas marquées séparément. Le fournisseur Anthropic natif marque en plus la dernière définition d’outil, ce qui couvre les tokens du schéma d’outils lorsqu’aucun prompt système n’existe. Cet indicateur ne marque pas les définitions d’outils ; les requêtes avec outils mais sans prompt système ne mettent en cache que le point de rupture glissant des messages. La qualification de la passerelle en production a montré qu’avec un prompt système présent, les tokens du schéma d’outils se trouvent de toute façon à l’intérieur du préfixe mis en cache.

Choisir une durée de vie de cache de 1 h

cache_ttl = "1h" demande une durée de vie d’une heure pour les entrées de cache créées par les marqueurs de ce fournisseur, au lieu de la valeur par défaut de cinq minutes. Utilisez-le lorsque les conversations reprennent régulièrement plus de cinq minutes après la requête précédente : chaque tour repris paie une réécriture du cache au plein tarif pour un préfixe qu’une durée de vie plus longue aurait maintenu actif.

L’arithmétique du seuil de rentabilité, où P désigne le prix de base en entrée du préfixe : une écriture de cache de 5 min coûte 1,25P et une écriture de 1 h coûte 2P, donc choisir la durée de vie de 1 h coûte 0,75P de plus par écriture de cache (un succès renouvelle l’entrée, si bien que la surcharge est payée à chaque écriture, et non par heure). Chaque expiration évitée grâce à la durée de vie plus longue économise 1,25P moins la lecture à 0,1P, soit environ 1,15P. Pour un préfixe de 140 k tokens à un tarif d’entrée de 10 $/M, P vaut 1,40 $ : environ 1,05 $ de surcoût d’écriture par écriture de 1 h, environ 1,61 $ économisés par expiration évitée, si bien que la première pause évitée rapporte environ 0,56 $ net et chaque pause suivante rapporte la totalité des 1,61 $. L’économie est bornée : elle n’existe que pour un préfixe réutilisé après un intervalle supérieur à cinq minutes et inférieur à une heure ; un intervalle au-delà d’une heure fait payer à nouveau l’écriture à 2x, sans aucune économie. En plus de la surcharge d’écriture, la durée de vie de 1 h ajoute un petit coût sur chaque suffixe ajouté : quelques milliers de tokens multipliés par 0,75 et par le tarif d’entrée, soit deux à trois centimes par tour pour un suffixe de quelques milliers de tokens à ce tarif. (Le tarif de lecture de 0,1x est la valeur courante ; certains modèles diffèrent, il faut donc vérifier la grille tarifaire de la mise en cache des prompts d’Anthropic pour le modèle concerné.) Les conversations qui marquent une pause entre cinq minutes et une heure privilégient "1h" ; celles qui restent actives, se terminent rapidement ou marquent une pause au-delà d’une heure privilégient la valeur par défaut.

Planifiez en tenant compte du prix nominal d’écriture de cache à 2x d’Anthropic. Une passerelle placée devant l’API peut facturer les écritures 1h à son propre tarif. Le registre (ledger) tarifie les écritures de cache au tarif cache_write_per_mtok configuré ou en temps réel lorsqu’il est présent, et au tarif d’entrée standard lorsque seul le repli du catalogue s’applique (le catalogue ne comporte pas de tarif d’écriture). cache_ttl ne sélectionne pas de tarif d’écriture : un opérateur qui fait passer une entrée à "1h" doit définir le tarif d’écriture du fournisseur de façon à correspondre à ce que la route facture réellement.

Deux réserves issues de la qualification du chemin en conditions réelles : la survie au-delà de cinq minutes a été démontrée à deux reprises, à six et quarante-neuf minutes ; une durée de vie complète d’une heure n’a pas été mesurée. Par ailleurs, une seule durée de vie TTL s’applique à tous les marqueurs générés par cette implémentation : les marqueurs system, tool et rolling-message du fournisseur natif Anthropic, ainsi que les points de rupture du passthrough compatible, portent tous la durée de vie configurée. Les cache_control fournis par l’opérateur (via les champs du corps provider_extra ou le JSON brut des outils) ne bénéficient pas de cette garantie, et tout mélange de durées de vie au sein d’une même requête doit respecter la règle d’ordre d’Anthropic (un marqueur de 1h avant un marqueur de 5m).

[providers.models.custom.claude-via-gateway]
uri = "https://<gateway-host>/v1"
model = "<anthropic-routed model>"
api_key = "op://platform/gateway/api-key"
cache_passthrough = true
cache_ttl = "1h"

Sur une entrée native Anthropic, la même clé fonctionne sans cache_passthrough :

[providers.models.anthropic.direct]
model = "claude-sonnet-4-5"
cache_ttl = "1h"

Limites d’entrée des images

[multimodal] borne chaque image qui entre dans le pipeline de requête, quelle que soit sa source : pièces jointes des canaux, pièces jointes déclarées par un outil, et téléversement depuis le tableau de bord web.

[multimodal]
max_image_size_mb = 20   # per image, decoded bytes (default: 20, clamped to 1-20)
max_images        = 4    # most images kept per request (default: 4, clamped to 1-16)

max_image_size_mb est mesuré avant l’encodage en base64, de sorte que la charge utile encodée atteignant le fournisseur est environ un tiers plus grande. La limite de 20 MiB est la plus basse borne commune par image ou par requête parmi les API de vision prises en charge, et les images étant mises en mémoire tampon entièrement, elle borne également la mémoire de la passerelle par envoi. Abaissez la valeur pour plafonner le coût d’envoi par tour.

Les fournisseurs appliquent leurs propres limites en plus de ce paramètre. Anthropic refuse une image unique dépassant 10 Mo encodée en base64, soit environ 7,5 MiB décodée, et son client applique cette limite quelle que soit la valeur autorisée par max_image_size_mb. Le coût en contexte du modèle ne dépend pas de la taille en octets : les fournisseurs rastérisent les images et facturent selon les dimensions en pixels, donc un fichier volumineux et un petit fichier à la même résolution coûtent à peu près le même prix.

max_images compte chaque image encore présente dans la conversation, et non uniquement les nouvelles, de sorte qu’une session longue finit par l’atteindre. Au-delà de la limite, les images les plus anciennes sont supprimées en un seul lot, jusqu’à la moitié de la limite arrondie à l’entier supérieur (4 devient 2, 16 devient 8), puis le nombre remonte jusqu’à la limite avant le lot suivant. Supprimer une image modifie un message antérieur, si bien que le cache de prompt du fournisseur est reconstruit à partir de ce message ; le traitement par lots fait que cela ne se produit qu’une fois toutes les max_images / 2 + 1 nouvelles images, au lieu de chaque fois. Juste après un lot, le modèle voit moins d’anciennes images que la limite ne le permet. Augmentez la limite pour les sessions riches en captures d’écran.

Réglages par famille : exemples détaillés

Ollama

Ollama utilise par défaut le point de terminaison local, un alias local n’a donc besoin que du nom du modèle :

[providers.models.ollama.local]
model = "llama3.1"

Définissez uri lorsque ZeroClaw ne s’exécute pas sur le même hôte qu’Ollama :

[providers.models.ollama.host]
model = "llama3.1"
uri = "http://host.docker.internal:11434"

Les champs optionnels spécifiques à Ollama sont num_ctx, num_predict et temperature_override.

Hailo-Ollama

Hailo-Ollama utilise un emplacement hailo_ollama distinct, car son API native exige une mise en forme des requêtes plus stricte que celle d’Ollama classique. Une instance locale utilise par défaut http://localhost:8000 ; la découverte des modèles lit sa réponse en direct de /api/tags.

[providers.models.hailo_ollama.edge]
model = "qwen3:1.7b"
context_window = 2048
max_tokens = 256
timeout_secs = 90
queue_timeout_secs = 30

Définissez uri sur l’URL de base de Hailo-Ollama lorsqu’il s’exécute sur un autre hôte. L’URL doit utiliser http ou https et ne doit contenir ni identifiants, ni requête, ni fragment. Un alias api_key est envoyé sous forme d’en-tête Authorization Bearer, et les extra_headers sont transmis aux requêtes de chat natives et de catalogue. Ne configurez pas à la fois api_key et un en-tête Authorization explicite dans extra_headers : ZeroClaw rejette cette combinaison d’identifiants ambiguë. Il sérialise la génération à une seule requête active par point de terminaison normalisé, même lorsque plusieurs alias ciblent ce même point de terminaison, et rejette les travaux en file d’attente après queue_timeout_secs.

Pour un point de terminaison non loopback, http simple envoie les prompts et les réponses sans chiffrement de transport ni authentification ; utilisez https lorsque le réseau n’est pas un lien isolé et de confiance. Le fournisseur accepte HTTP en clair pour les déploiements locaux et les déploiements sur réseau local explicitement approuvés, car le point de terminaison natif de Hailo-Ollama ne dispose d’aucun contrat d’authentification.

Hailo-Ollama rejette les options de transport qu’il ne peut pas honorer, au lieu de les ignorer silencieusement. En particulier, tls_ca_cert_path, think=true, vision=true, le thinking natif au niveau de l’appel, provider_extra, api_path, wire_api et chat_template_kwargs ne sont pas pris en charge. Définissez native_tools = false (ou laissez-le non défini).

Si une requête acceptée atteint son délai d’expiration HTTP ou se termine par une autre défaillance de transport après la connexion, ZeroClaw met cet endpoint en quarantaine pour le reste du processus, car Hailo peut encore générer une réponse après la déconnexion du client. Vérifiez que le backend est inactif (redémarrez-le si nécessaire), puis redémarrez ZeroClaw pour lever la quarantaine. Un échec d’établissement de connexion ne met pas l’endpoint en quarantaine.

Pour la compatibilité avec le backend natif, ZeroClaw omet les champs de transport think et num_ctx non pris en charge plutôt que de prétendre les contrôler. Le service natif analyse chaque message décodé comme un prompt structuré au format JSON une seconde fois ; ZeroClaw échappe donc à la fois les antislashs littéraux et les caractères de contrôle CR/LF/tabulation dans la valeur de l’API afin de préserver leur sens d’origine lors de cette analyse. context_window contrôle la budgétisation locale de l’historique de ZeroClaw, réalisée au mieux. Omettez-le pour éviter une hypothèse de contexte à l’échelle du fournisseur ; configurez une valeur positive pour activer la budgétisation locale. Une valeur explicite de zéro est rejetée par le diagnostic de configuration partagé. Elle n’est volontairement pas envoyée à Hailo-Ollama. Les requêtes de réflexion native au niveau de l’appel sont rejetées avant toute requête vers le backend. Les réponses doivent être une réponse complète non diffusée en flux (done=true), et une réponse complète vide est traitée comme une erreur. Un context_window faible supprime les anciens tours complets ancrés sur l’utilisateur, en utilisant le budget agrégé configuré, réalisé au mieux. Les instructions système sont intégrées au premier message utilisateur conservé avant cette vérification. Lorsqu’un context_window non nul est configuré et que le tour complet le plus récent dépasse à lui seul le budget configuré, la requête échoue localement avant le transport, au lieu de supprimer ce tour ou de le remplacer par une invite synthétique. Lorsque context_window est omis, aucun budget local à l’échelle du fournisseur n’est appliqué. Il n’existe aucune limite à l’échelle du fournisseur sur le nombre de caractères ou de messages ; le HEF natif et le runtime restent l’autorité pour la capacité de contexte réellement prise en charge.

Si la réponse native ne contient aucun contenu visible mais contient un raisonnement interne non vide, le fournisseur utilise ce champ comme solution de repli en texte ordinaire, en dernier recours, pour assurer la compatibilité avec les modèles qui y placent leur unique sortie. Il n’expose pas de canal de raisonnement distinct, et les appelants ne doivent pas considérer cette solution de repli comme une preuve que la réflexion étendue est prise en charge.

L’appel natif d’outils, le streaming et la vision ne sont pas annoncés. Comme le DTO de chat Hailo-Ollama 0.5.1 ne possède aucun champ image, vision=true est rejeté au lieu de remplacer cette capacité texte uniquement ; configurez plutôt un fournisseur distinct capable de vision. Les appels d’outils guidés par le prompt et leurs résultats restent disponibles sous forme d’historique en texte brut lorsque le protocole d’outils injecté complet tient dans le premier message borné ; ZeroClaw rejette un protocole trop volumineux au lieu d’envoyer des instructions d’outils tronquées.

Azure OpenAI

Azure OpenAI détermine son point de terminaison à partir des champs Azure renseignés :

[providers.models.azure.work]
api_key = "op://platform/azure-openai/api-key"
model = "gpt-4o"
resource = "example-resource"
deployment = "gpt-4o-prod"
api_version = "2024-10-21"

Les valeurs resource, deployment et api_version se trouvent dans cette configuration typée, elles ne sont pas lues à partir des variables d’environnement spécifiques à Azure. Utilisez uri uniquement lorsque vous devez remplacer complètement le point de terminaison calculé.

Amazon Bedrock

Bedrock nécessite un alias avec un modèle ; la région du point de terminaison provient actuellement du chemin d’environnement/profil d’authentification Bedrock :

[providers.models.bedrock.work]
model = "anthropic.claude-sonnet-4-6"

Le fournisseur Bedrock utilise les chemins d’identification implémentés dans crates/zeroclaw-providers/src/bedrock.rs :

  1. api_key sur l’alias Bedrock, ou BEDROCK_API_KEY, utilise l’authentification par jeton porteur Bedrock et prévaut sur les identifiants SigV4.
  2. AWS_ACCESS_KEY_ID plus AWS_SECRET_ACCESS_KEY utilise SigV4. AWS_SESSION_TOKEN est optionnel. AWS_REGION ou AWS_DEFAULT_REGION sélectionne la région de signature et utilise us-east-1 par défaut.
  3. credential_process dans le profil actif issu de ~/.aws/config, ou de AWS_CONFIG_FILE, utilise SigV4. AWS_PROFILE sélectionne le profil et prend la valeur default par défaut.
  4. Les informations d’identification d’instance EC2 IMDSv2 constituent le dernier mécanisme de secours pour SigV4.

Le schéma de configuration définit en outre un champ providers.models.bedrock.<alias>.region, mais l’implémentation actuelle ne le lit pas. La région du point de terminaison est toujours résolue à partir de la chaîne d’informations d’identification AWS (variables d’environnement, credential_process ou IMDS) comme décrit ci-dessus.

Un profil statique normal dans ~/.aws/credentials n’est pas lu par l’implémentation Bedrock actuelle. ~/.zeroclaw/secrets ne stocke que les secrets de configuration ZeroClaw, tels qu’un alias api_key ; il n’exporte pas les variables AWS_* pour le fournisseur.

Pour réutiliser un profil AWS CLI via le chemin de profil implémenté, ajoutez un credential_process dans ~/.aws/config :

[profile zeroclaw-bedrock]
credential_process = /usr/bin/aws configure export-credentials --profile my-existing-profile
region = us-east-1

/usr/bin/aws est le chemin par défaut sur Debian et Ubuntu. Sur les autres systèmes, utilisez le chemin absolu obtenu avec command -v aws.

Ensuite, exécutez ZeroClaw avec AWS_PROFILE=zeroclaw-bedrock. Pour un service utilisateur systemd, consultez Gestion des services.

Multi-région (Moonshot / Qwen / GLM / MiniMax / …)

Un type par famille ; choisissez la région via le champ typé endpoint sur l’entrée d’alias.

Point de terminaison personnalisé compatible OpenAI

Le slot custom nécessite uri. Voir Custom providers.

Choix du fournisseur utilisé par un agent

Les agents référencent un fournisseur par alias pointé. Les entrées de fournisseur seules ne font rien.

risk_profile et runtime_profile référencent des tables d’alias indépendantes, leurs noms n’ont donc pas besoin de correspondre (runtime_profile est également facultatif). Config::validate() échoue bruyamment au démarrage si model_provider ne se résout pas en une entrée [providers.models.<type>.<alias>] configurée, ou si risk_profile ne se résout pas en une entrée [risk_profiles.<alias>] configurée.

Pour plusieurs agents pointant vers différents fournisseurs, consultez Routing.

Prise en charge d’un tour d’outil unique

Le paramètre single_tool_rounds du profil d’exécution de l’agent est désactivé par défaut. Voir Tours à outil unique pour la configuration, la comptabilisation et le comportement de restauration. Il ne demande un seul appel par réponse que lorsque la route de modèle effective et chaque repli accessible respectent un contrôle natif.

Chemin du fournisseur configuréContrôle natifSupport
openai, authentification par clé d’API, point de terminaison officiel OpenAI, protocole chat-completions ou Responsesparallel_tool_calls: falsePris en charge
anthropic, point de terminaison officiel d’Anthropictool_choice.disable_parallel_tool_use: truePris en charge
Points de terminaison personnalisés ou compatibles, OVH, authentification par abonnement Codex et autres adaptateursAucun contrôle vérifiéLot avec un avertissement de limitation visible

Responses et Anthropic transmettent le contrôle dans les requêtes en streaming comme dans les requêtes sans streaming. OpenAI chat-completions utilise son implémentation existante sans streaming, y compris lorsqu’un routeur projette cette réponse sous forme d’événements de streaming. Les requêtes sans outils conservent leur format de transmission existant. Partager un adaptateur avec un fournisseur pris en charge n’établit pas la prise en charge d’un autre endpoint. Une chaîne de repli mixte reste en mode batch, même si son fournisseur principal prend en charge le contrôle.

Repli en cas d’échec

Lorsqu’une requête vers un fournisseur échoue après avoir épuisé ses tentatives (fournisseur indisponible, clé limitée en débit, modèle indisponible), l’alias peut basculer vers les alternatives que vous déclarez sur l’entrée de l’alias. Deux axes indépendants et ordonnés :

  • fallback_models : identifiants de modèles alternatifs essayés sur ce fournisseur, en utilisant le même endpoint, la même clé et les mêmes en-têtes. Seul l’identifiant du modèle change. Utilisez-le lorsqu’un fournisseur propose un modèle de secours (une variante plus petite ou plus ancienne) qui doit être essayé avant de quitter complètement le fournisseur.
  • fallback : une liste ordonnée d’autres alias de fournisseurs (références pointées <type>.<alias> vers [providers.models]). Chaque alias de secours est résolu avec ses propres identifiants, point de terminaison et modèle ; un alias de secours n’hérite jamais de la clé de l’alias défaillant.

Ordre des tentatives

Le parcours est en profondeur d’abord : la liste complète des modèles d’un alias est épuisée avant de le quitter, puis chaque alias fallback est parcouru à son tour, en appliquant récursivement les fallback_models et le fallback propres à cet alias. Supposons que anthropic.prod serve claude-sonnet-4-5, liste claude-haiku-4-5 dans ses fallback_models, et désigne openai.backup (servant gpt-4.1) dans son fallback. L’ordre des tentatives est alors :

anthropic.prod/claude-sonnet-4-5
  -> anthropic.prod/claude-haiku-4-5
  -> openai.backup/gpt-4.1
  -> (request fails)

Les alias de repli peuvent eux-mêmes déclarer fallback, donc la chaîne est aussi longue que votre configuration le permet, jusqu’à une profondeur maximale de 3 alias. Une chaîne qui boucle sur elle-même (a -> b -> a) est détectée et l’arête du cycle est élaguée, et une chaîne acyclique plus profonde que la limite voit ses liens restants élagués ; aucune ne boucle, ne se bloque ou ne provoque de débordement de pile.

Mauvaise configuration

Une entrée fallback qui désigne un alias non configuré, qui ferme un cycle, ou une chaîne qui dépasse la profondeur maximale est non fatale : Config::validate() réussit quand même, l’arête fautive est ignorée à l’exécution, et le problème est signalé sous forme d’avertissement de validation (dangling_fallback_ref / fallback_cycle / max_fallback_depth_exceeded) dans la CLI et dans le tableau de bord. Une entrée fallback_models vide ou qui duplique le model principal de l’alias est de même ignorée à l’exécution et signalée (empty_fallback_model / fallback_model_duplicates_primary). Un lien de repli défectueux se dégrade de manière contrôlée, il n’empêche jamais l’agent de s’exécuter.

Refus et repli d’Anthropic

Les requêtes natives vers Anthropic peuvent renvoyer un refus : une réponse HTTP 200 dont stop_reason vaut "refusal", émise par les classificateurs de sécurité de Fable plutôt qu’une complétion normale. ZeroClaw traite un refus comme une erreur typée afin que le mécanisme de repli puisse le récupérer de deux manières :

  • Côté client (fallback_models, ci-dessus) : le refus remonte comme une erreur, et ZeroClaw passe au modèle ou à l’alias suivant, comme pour toute autre défaillance d’un fournisseur, de sorte que la réponse provient d’un autre modèle.
  • Côté serveur (server_fallback_models sur [providers.models.anthropic.<alias>]) : Anthropic relance la requête refusée auprès d’un modèle listé de son côté, dans un seul appel non diffusé en continu. Les entrées doivent désigner des cibles de repli autorisées, par exemple en associant claude-fable-5 à claude-opus-4-8.

Dans les deux cas, la réponse livrée comporte un court pied de page indiquant le modèle demandé et le modèle servi, afin que le changement soit visible pour l’utilisateur. Dans le chat du tableau de bord web, le même changement apparaît sous la forme d’un avis en ligne juste avant la réponse, n’affichant que les noms du modèle demandé et du modèle servi. Lorsqu’un échec ordinaire du fournisseur a déjà fait basculer la requête vers un repli côté client avant qu’Anthropic ne change de modèle de son côté, la réponse conserve également l’avis de repli ordinaire, afin que le modèle initialement demandé reste visible et que les deux causes ne soient pas confondues.

Le streaming a une limite : un refus reçu après le début de la sortie streamée conserve le comportement existant de réponse interrompue ; le mécanisme de repli ne s’applique qu’aux refus détectés avant le début de la sortie.

Les protocoles compatibles OpenAI et Responses ne peuvent pas transporter les métadonnées natives de refus et de repli d’Anthropic ; pour obtenir ce comportement, acheminez les modèles Anthropic via [providers.models.anthropic.<alias>].

Voir aussi