Au moment où une application commence à appeler des tools, la sortie du modèle cesse d'être du texte à lire et devient une instruction à exécuter, et toutes les garanties construites jusqu'ici par cette série portaient sur des tokens. Un framework peut rendre cette boucle facile à écrire et, du même geste, masquer le throttling, contourner le routage de la gateway et transformer une requête mesurée en onze que personne n'avait prévues. La partie 7 a donné le retrieval aux applications. Cette partie traite de ce qui se pose au-dessus, et précisément des tâches que le framework ne devrait pas faire parce que la plateforme les fait déjà.

Pointer le framework vers la gateway, et s'arrêter là

La mécanique est triviale, et c'est précisément pourquoi la discipline doit être explicite. Un framework d'orchestration parle le format OpenAI Chat Completions, la gateway expose exactement cela, donc l'intégration tient en une base URL et un credential :

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    base_url="https://apim-genai-prod.azure-api.net/llm/v1",
    api_key=gateway_token,        # Entra ID token, not a model key
    model="chat-default",         # gateway alias, never a deployment name
    max_retries=0,                # the gateway owns retry and failover
    timeout=60,
)

max_retries=0 est la ligne qui compte, et c'est celle que l'on supprime en premier. Les frameworks livrent par défaut du retry côté client, de l'exponential backoff et souvent un fallback de provider, autant de défauts raisonnables pour une application qui parle directement à un fournisseur de modèles, et autant de comportements activement nuisibles devant une gateway qui fait déjà le routage, le load balancing et le circuit breaking.

Regardez ce que le retry côté client fait au circuit breaker de la partie 3. Le breaker se déclenche et renvoie 503 précisément pour que les appelants cessent de marteler un backend défaillant. Un framework configuré pour retenter un 503 cinq fois avec backoff convertit ce signal en cinq fois la charge, qui arrive exactement au moment où le backend est le moins capable de l'encaisser. Même chose pour le 429 : une token limit existe pour façonner la demande, et un client qui retente à travers elle n'est pas façonné. Les retries appartiennent à un seul endroit, et cet endroit existe déjà.

La contrepartie honnête : un unique retry sur un échec au niveau connexion, dans le client, ne pose aucun problème. La règle porte sur le fait de retenter les réponses propres de la gateway, pas sur les caprices du réseau.

Ce que le framework doit encore faire

Une fois l'abstraction de provider, le routage, le retry et le fallback retirés de sa fiche de poste, il reste au framework les parties réellement fastidieuses à écrire soi-même et sans aucun enjeu de plateforme : le templating de prompts avec entrées typées, la génération de schémas de tools depuis les signatures de fonctions, le parsing des sorties en types structurés, et la comptabilité de boucle qui transforme un tool call en message de suivi. C'est une vraie quantité de travail et une raison raisonnable de prendre la dépendance.

Ce qu'il ne doit pas devenir, c'est l'endroit où vit le choix du modèle. L'alias dans le code ci-dessus est un alias de gateway, résolu par le model catalog de la partie 2. Le registre de modèles propre au framework, ses chaînes de fallback, sa liste de providers, tout cela forme un second catalogue qui contredira le premier le jour où un modèle sera retiré.

Les tools sont la seconde surface, et ils peuvent partager la première porte

Les tools d'un agent méritent le même traitement que ses modèles : un point d'entrée gouverné, un accès par tenant, une piste d'audit. API Management peut exposer une REST API qu'il gère déjà comme un MCP server distant, en publiant des opérations choisies comme tools que les clients MCP appellent, disponible sur les tiers Developer, Basic, Standard et Premium, y compris leurs variantes v2. Associer ce MCP server à un product signifie que l'accès aux tools est géré via les mêmes products et subscriptions que l'accès aux modèles, ce qui est tout l'intérêt : une identité, une seule histoire de quota, un seul endroit pour révoquer.

Deux limitations décident jusqu'où cela va aujourd'hui. API Management supporte les tools d'un MCP server, mais pas les resources ni les prompts MCP, pour les servers exposés depuis des REST APIs managées. Et les capacités MCP server ne sont pas supportées dans les workspaces, ce qui compte pour exactement les équipes isolées que la partie 5 a orientées vers les workspaces. Une équipe qui a besoin à la fois d'une gateway de workspace et de la publication de tools MCP doit choisir l'un des deux, et mieux vaut l'apprendre en dessinant l'architecture.

Content safety sur le chemin du prompt

Une agent loop élargit la surface d'entrée : documents récupérés, sorties de tools et texte utilisateur finissent tous dans un prompt. La politique llm-content-safety route le contenu vers Azure AI Content Safety avant que le modèle ne le voie.

<llm-content-safety backend-id="content-safety-backend" shield-prompt="true">
  <categories output-type="EightSeverityLevels">
    <category name="Hate" threshold="4" />
    <category name="Violence" threshold="4" />
  </categories>
</llm-content-safety>

Trois attributs demandent une lecture attentive plutôt qu'un copier-coller. Le threshold fonctionne comme une tolérance, pas comme une limite : avec threshold="4" le filtre laisse passer les sévérités 0 à 3 et bloque 4 à 7, donc augmenter le nombre augmente la tolérance et bloque moins. C'est la même inversion que le score threshold du cache dans la partie 6, et elle piège les gens de la même façon.

shield-prompt="true" active la vérification contre les attaques adverses de l'utilisateur, et vaut false par défaut. Pour un agent qui concatène des documents récupérés dans son contexte, ce défaut est le mauvais : la prompt injection qui arrive par un document est la menace réaliste, pas un utilisateur qui tape une attaque dans une boîte de chat.

enforce-on-completions, lui aussi false par défaut, étend la vérification aux réponses du modèle quand la politique se trouve en inbound. Et window-size, qui vaut par défaut la limite Content Safety de 10 000 caractères, est configurable uniquement pour les réponses ; pour les requêtes, la fenêtre par défaut est toujours utilisée. Un très long contexte récupéré est donc évalué par un fenêtrage que vous ne contrôlez pas, ce qui est un argument pour borner les résultats de retrieval plutôt que pour faire confiance au filtre pour scaler avec eux.

Ce qu'une boucle fait à chaque chiffre de la partie 5

Une seule question utilisateur qui déclenche quatre tool calls n'est pas une requête, ce sont cinq invocations de modèle, chacune renvoyant le transcript qui grossit. Trois conséquences pour la plateforme :

  • Le quota par minute cesse de refléter le volume d'utilisateurs. Il devient le volume d'utilisateurs multiplié par la profondeur moyenne de boucle, et la profondeur de boucle est une propriété du prompt de l'application, qui change sans revue de plateforme.
  • Une boucle emballée est indiscernable de la charge. La gateway voit des requêtes bien formées, dans le quota. L'application doit borner ses propres itérations, et la plateforme devrait publier cela comme une exigence plutôt que le supposer.
  • Le chargeback a besoin d'un correlation ID par interaction utilisateur, pas par requête, sans quoi les chiffres par équipe sont vrais et inutiles. Cet ID appartient à l'enregistrement de log, là où la partie 5 a placé les données à haute cardinalité exactement pour cette raison.

Un plafond de tokens par requête à la gateway est un garde-fou utile et non un substitut. Il limite les dégâts d'un appel énorme ; il ne fait rien contre une boucle qui en fait deux cents petits.

Modes de défaillance à surveiller

  • Le retry du framework qui défait le circuit breaker. Le défaut est activé. Désactivez-le délibérément et documentez pourquoi, sinon le mécanisme de protection de la plateforme devient un amplificateur de charge.
  • Un second model catalog dans le framework. Il contredira celui de la gateway le jour du retrait, et l'application se retrouvera épinglée à un nom de déploiement que personne ne lui connaissait.
  • Le threshold de content safety lu comme une limite. Plus haut, c'est plus permissif. Une équipe qui règle ses faux positifs peut désactiver le filtre en pratique tout en croyant l'avoir resserré.
  • shield-prompt laissé à son défaut. Désactivé. Sur un agent qui ingère des documents récupérés, c'est le chemin d'injection laissé ouvert.
  • Des boucles non bornées. Aucune politique de gateway n'exprime « s'arrêter après six itérations ». Seule l'application le peut, c'est donc un contrat, pas un contrôle.
  • MCP plus workspaces. Non supportés ensemble aujourd'hui. Le découvrir après avoir promis les deux à une équipe est un retour en arrière d'architecture.

Ce dont hérite la partie 9

Des applications avec orchestration, des tools publiés via la même gateway, et le content safety sur le chemin des requêtes. Le tout configuré en policy XML, en mappings d'alias et en définitions de products qui atteignent aujourd'hui la production comme n'importe quel autre changement, et c'est la partie qui n'a pas encore été examinée. La suite : Azure DevOps, et ce que signifie conditionner un changement de version de modèle à une évaluation plutôt qu'à un commentaire de revue.

À lire ensuite

Pour le volet infrastructure et plateforme de l'exploitation de tout cela à grande échelle, les notes de terrain sont sur ercan.cloud, et le hub se trouve sur ercanermis.com.

Références