Dépannage : inférence et agents
Inférence, outils MCP, fédération, chaîne d'agents, échange de jeton et A2A : le symptôme, sa cause et quoi faire.
DépannageExploitationDepuis la version 0.1.0
Sur cette page
Guide d'exploitation : configurer, déployer et observer la passerelle. Ce que fait la fonctionnalité côté produit : guide produit ; l'appeler : guide développeur.
Inférence
| Symptôme | Cause | Action |
|---|---|---|
Inférence : 401 tenant_required malgré les en-têtes de l'ingress |
Le pair n'est pas dans server.trusted_proxies : ses en-têtes ne sont pas crus |
Déclarer la plage de l'ingress, et elle seule |
Inférence : 429 budget_exceeded |
Le budget du tenant (jour ou mois) est épuisé - une requête pré-réserve max_tokens, 512 sans lui |
Relever ai.budget ou une surcharge du tenant ; le compteur est dans ai.budget.store |
Inférence : 429 rate_limited pour tous les tenants derrière l'ingress |
Une politique de débit trop serrée sur /v1/* |
Une politique propre sur routes: { "/v1/**": [...] } (exemple) |
Inférence : Flexway-Budget: soft sur toutes les réponses d'un tenant |
Il a dépassé soft.at de son budget en euros du mois |
Attendu ; relever monthly_eur du tenant (surcharge) ou attendre le mois suivant |
Inférence : Flexway-Degraded: backend-fallback |
Le backend choisi est en panne (connexion, 5xx, délai, circuit ouvert) ; le suivant de fallback a servi |
La métrique flexway.inference.fallback donne le backend quitté et la cause |
| Refus au chargement « price is required: the budget is counted in euros » | Un budget en euros existe et un backend n'a pas de prix | Déclarer price sur chaque backend, 0 pour un interne |
Inférence : 403 sensitive_no_internal_backend |
Requête sensible et aucun ai.sensitive_backend interne |
Déclarer un backend interne ; jamais un externe pour ce flux |
Inférence : 400 capability_unavailable |
Le backend que la politique choisit ne sert pas ce que la requête demande - une image sans vision, des embeddings sans embeddings |
Déclarer la capacité sur le backend (capabilities) ou une dérogation match.capability vers un backend qui la sert |
Avertissement « is a relay metered locally » (flexway validate, démarrage) |
Un kind: relay sans metering: upstream : la Flexway amont compte aussi le coût |
Déclarer metering: upstream ; le plafond local reste appliqué |
Inférence : 502 backend_unavailable |
Backend injoignable, ou sa clé introuvable (${VAR} non posée, fichier absent) |
Le journal (inference backend failed) donne la cause ; la clé est relue à chaque appel |
Agents et MCP
| Symptôme | Cause | Action |
|---|---|---|
Agent : 401 malgré un jeton valide |
Le jeton n'est pas émis pour la surface : son audience doit être l'URL de agents.mcp.resources |
Demander le jeton avec l'indicateur de ressource (resource=https://…/mcp) |
Un outil attendu manque dans tools/list |
Le jeton de l'agent n'a pas la portée ou le rôle que l'opération exige - la liste est filtrée | Donner la portée à l'agent, pas élargir l'opération |
Un outil répond 401 depuis l'amont |
L'amont vérifie lui-même un JWT, et le jeton de l'agent ne lui est jamais relayé | Déclarer upstreams.<nom>.token_exchange et le client de l'émetteur (Le jeton que reçoit l'amont, Jeton échangé vers l'amont) |
| Un outil d'un serveur fédéré n'apparaît pas | Serveur injoignable ou pas encore découvert ; outil hors de la liste déclarée ; portée manquante ; nom déjà pris | /config, mcp_federation : état, outils servis, not_served et pourquoi ; le journal dit MCP server not reachable |
| Refus au chargement « is offered twice … rename one » | Un outil fédéré porte le nom d'un outil du contrat ou d'un autre serveur | agents.mcp.servers.<nom>.rename |
Un outil fédéré répond forbidden |
L'appelant n'a pas les scopes (ou tool_scopes) déclarés, ou n'est pas authentifié |
Donner la portée à l'agent |
403 « The chain of agents … is longer than allowed » ou « older than allowed » |
Le jeton porte plus d'agents (act) que max_depth, ou l'humain s'est authentifié il y a plus de max_age - l'opération peut resserrer |
Le journal (delegation chain refused) donne la raison et les agents ; réauthentifier l'humain, ou raccourcir la chaîne |
401 « The delegation was revoked » |
L'émetteur répond que le jeton n'est plus actif (introspection) | Attendu après une révocation ; obtenir un nouveau consentement |
503 « The delegation cannot be verified now » |
L'introspection de l'émetteur est injoignable, ou l'émetteur n'en publie pas | Vérifier introspection_endpoint dans sa découverte et le client ; un jeton direct, lui, passe |
403 sur un amont qui échange, journal widened |
Le fournisseur a accordé une portée que l'appelant n'avait pas | Régler la politique d'échange du fournisseur : un saut ne doit jamais élargir |
Découverte en échec 401 |
Le serveur exige un jeton même pour lister | discovery.issuer, avec un client sur cet émetteur |
403 « The identity provider refused to issue a token for this upstream » |
Le fournisseur refuse l'échange : client non autorisé à échanger, audience inconnue, secret faux | Le journal (token exchange refused) donne le code du fournisseur ; régler le client côté fournisseur |
503 « could not issue a token », avec Retry-After |
Fournisseur injoignable, ou secret client introuvable (${VAR} non posée, fichier absent) |
Le journal (token exchange unavailable) dit lequel ; le secret est relu à chaque échange, sans rechargement |
A2A
| Symptôme | Cause | Action |
|---|---|---|
A2A : 200 avec l'erreur JSON-RPC -32009 (VERSION_NOT_SUPPORTED) |
Pas d'en-tête A2A-Version - c'est la 0.3 pour la spécification |
Envoyer A2A-Version: 1.0 (ou ?A2A-Version=1.0) ; seule la 1.0 est servie |
A2A : 403 PUSH_TARGET_NOT_ALLOWED |
Cible push hors agents.a2a.push.allowed_hosts, en http, écrite en adresse, avec user@, ou aucune liste déclarée |
Déclarer le nom de l'hôte du webhook ; flexway_a2a_push_refused_total donne la raison |
A2A : 403 TENANT_MISMATCH |
Le tenant de la requête (corps, préfixe de chemin, paramètre) n'est pas celui de l'identité, ou l'identité n'en porte aucun |
Envoyer le tenant de l'identité, ou rien : la passerelle transmet le sien |
A2A : 429 TOO_MANY_STREAMS |
L'appelant tient déjà max_streams flux ouverts vers cet agent sur cette réplique |
Fermer un flux, ou relever max_streams de l'agent |
| Un flux A2A se termine à heure fixe | max_task_duration atteint (flexway_a2a_calls_total{outcome="duration_exceeded"}) |
Le relever sur l'agent, ou suivre la tâche par GetTask |
| Démarrage refusé sur une carte A2A | Liaison gRPC, schéma sans mécanisme, amont sans token_exchange ou pas protocol: a2a, signatures déclarées, signer (prévu en 1.10.0), verify: none absent, flux sans max_streams ou max_task_duration |
Le message nomme la carte, l'agent et la règle |