AI

AgentOps : valider le basculement régional avant de rerouter un agent de production

Un runbook de production pour qualifier le basculement régional d'un agent IA entre modèle, état, retrieval, outils, identité, traces, trafic canari, validation et rollback.

04 sept. 2026 azureaiagentopsagentsmicrosoft-foundryresiliencefailoverobservabilityevaluationautomationguardrailsrunbookrollbackproduction

Un agent d’exploitation commence à expirer pendant un incident. Le déploiement de modèle principal renvoie des erreurs intermittentes, la latence augmente et la couche de routage peut envoyer les requêtes vers une seconde région Azure. La bascule paraît être l’action de reprise évidente. Elle peut aussi conduire l’agent vers une autre révision de modèle, un index de retrieval plus ancien, une identité différente ou un endpoint d’outil qui n’a jamais exécuté le runbook de production.

Ce n’est pas seulement le failover d’un endpoint de modèle. L’unité de production est le chemin complet de l’agent : instructions, déploiement de modèle, état des conversations, retrieval, contrats d’outils, identités, accès réseau, politique d’approbation et télémétrie. Ce runbook permet de décider s’il faut attendre, tester le chemin secondaire en canari, basculer une charge bornée ou renvoyer le trafic vers la région principale.

Figer le chemin en échec et l’objectif de reprise

Commencez par une charge et une fenêtre temporelle précises. Ne mélangez pas diagnostic interactif, évaluations en arrière-plan et automatisations capables d’écrire dans une même décision de failover.

yaml regional-failover-incident.yml
incident:
id: INC-2841
detected_at: 2026-09-04T07:42:00Z
agent: operations-assistant
request_class: interactive-diagnosis
primary_region: region-a
candidate_region: region-b
symptom: timeout-and-upstream-errors

recovery_objective:
restore: read-only incident diagnosis
preserve:
- approved knowledge boundary
- refusal and approval policy
- trace correlation
- tool-call idempotency
excluded_initially:
- production writes
- long-running conversations already in execution
- batch evaluations

decision_deadline: 20m
owner: platform-oncall

L’objectif est volontairement plus étroit que « restaurer l’agent ». Le diagnostic en lecture seule peut souvent basculer en premier. Une action de production doit attendre que l’état, les outils et les garanties d’approbation soient prouvés sur le chemin candidat.

Définir l’unité réelle de failover

Un endpoint de modèle secondaire sain ne prouve pas que l’agent est sain. Inventoriez chaque dépendance traversée par une requête représentative et indiquez si elle est régionale, partagée ou épinglée.

text agent-failover-unit.txt
Couche                    Chemin principal   Chemin candidat     Preuve requise
Instructions agent        version 42         version 42           digest immuable
Deploiement modele        deployment-a       deployment-b         modele et config approuves
Etat conversation         state-a            replique/partage     coherence et ownership
Index de retrieval        index-a-118         index-b-118          corpus et filtres identiques
Registre d'outils         tools-a-17          tools-b-17           digest schema et policy
Identite runtime          identity-a          identity-b           acces de moindre privilege
Reseau et DNS             route-a             route-b              acces lecture et outils
Stockage approbations     partage             partage              usage unique atomique
Telemetrie                workspace/app       workspace/app        continuite des traces
Kill switch               route policy        route policy         retour teste

« Même configuration » ne suffit pas. Conservez des identifiants déployables et des digests. Si la région secondaire ne peut pas prouver les instructions, le schéma d’outil ou le snapshot d’index qu’elle sert, gardez-la hors du chemin d’écriture.

Qualifier la région secondaire sans effet de bord

Lancez des sondes synthétiques depuis la même classe de réseau et d’identité que l’agent. Validez séparément l’appel du modèle, les filtres de retrieval, les outils read-only, l’export des traces et le refus par policy avant de tester une conversation de bout en bout.

yaml secondary-region-probes.yml
probes:
- id: model-minimal-response
  input: fixed-health-prompt
  assert: response-and-trace

- id: retrieval-approved-source
  input: known-document-id
  assert: expected-version-and-access-filter

- id: tool-read-only
  tool: get_service_health
  assert: schema-valid-and-no-write

- id: forbidden-production-write
  tool: restart_service
  approval: absent
  assert: rejected-before-dispatch

- id: trace-chain
  assert:
  - region-and-deployment-recorded
  - model-and-tool-spans-correlated
  - sensitive-content-policy-applied

stop_on:
- unknown-configuration-version
- missing-refusal
- missing-trace
- identity-scope-wider-than-primary

N’utilisez pas un outil destructif comme sonde de santé. Le test négatif doit prouver que la gate de policy refuse l’écriture avant dispatch, pas que le backend sait l’annuler ensuite.

Rejouer les résultats attendus, pas la formulation

Avant d’envoyer du trafic réel, rejouez un jeu d’évaluation figé contre les deux régions. Comparez résultat de tâche, ancrage, choix des outils, arguments, refus et enveloppe de latence. Une formulation identique est un signal de parité faible.

json regional-parity-case.json
{
"case_id": "diagnose-api-latency-07",
"input_snapshot": "eval-set-20260904-v3",
"expected": {
  "allowed_sources": ["runbook-api-v8", "service-map-v12"],
  "required_tool_sequence": ["search_runbook", "query_health_readonly"],
  "forbidden_tools": ["restart_service", "change_route"],
  "required_decision": "collect-more-evidence",
  "required_trace_fields": ["region", "deployment", "agent_version", "tool_call_id"]
},
"compare": [
  "task_completion",
  "groundedness",
  "tool_call_accuracy",
  "refusal_consistency",
  "latency",
  "token_usage"
]
}

Utilisez des cas opérationnels représentatifs, dont des demandes ambiguës, écritures refusées, outils indisponibles et connaissances obsolètes. Un chemin secondaire qui répond correctement mais choisit une action plus large a échoué au test de préparation.

Protéger l’état et les effets de bord pendant la bascule

Le failover devient dangereux lorsqu’une requête en timeout s’exécute peut-être encore dans la région principale. Rejouer tout le tour dans la région secondaire peut dupliquer un appel d’outil ou consommer deux fois la même approbation.

text failover-state-rules.txt
Avant de rejouer une conversation
Lire le dernier tour committe et l'etat du run actif
Rechercher les operations backend par cle d'idempotence
Preserver les IDs de conversation, trace et appel d'outil
Refuser l'ownership concurrent d'un meme run

Rejeu autorise
Appel modele sans outil dispatche
Requete de retrieval sur snapshot immuable
Outil read-only avec retries bornes

Pas de rejeu automatique
Outil d'ecriture au resultat backend inconnu
Approbation humaine consommee ou en attente
Action longue encore detenue par le worker principal
Tour dont la version d'etat est irreconciliable

Reprise d'une ecriture ambigue
Interroger l'etat de l'operation
Reconcilier l'etat observe de la cible
Reprendre par cle d'idempotence ou compenser
Ne jamais deduire un echec du seul timeout client

Le routeur de trafic ne doit pas porter ces règles. Il peut sélectionner un endpoint sain, mais l’orchestrateur doit rester propriétaire de l’état du run, de l’idempotence et de la consommation des approbations.

Basculer une classe de trafic en canari

Déplacez d’abord une petite classe identifiable de nouvelles sessions read-only. Maintenez l’affinité de session pendant chaque run pour éviter qu’une conversation alterne entre régions alors que les outils ou le retrieval divergent.

yaml agent-failover-canary.yml
canary:
eligible:
- new-session
- read-only-diagnosis
- approved-evaluation-cohort
excluded:
- active-production-action
- pending-human-approval
- unreconciled-primary-run

candidate_weight_percent: 5
session_affinity: required
observation_window: 15m

promotion_gates:
operational:
- run-success-rate-within-approved-envelope
- latency-within-approved-envelope
- no-unbounded-retry-growth
quality:
- task-and-grounding-gates-pass
- tool-selection-gate-passes
control:
- refusal-parity-passes
- trace-completeness-passes
- no-duplicate-tool-operation

automatic_stop:
- write-dispatched-without-valid-approval
- state-ownership-conflict
- missing-region-or-version-in-trace
- retrieval-snapshot-mismatch

Définissez les seuils depuis la baseline du service et sa politique de risque au lieu de recopier des pourcentages génériques. Une seule rupture de contrôle doit arrêter le canari, même si la latence moyenne s’améliore.

Corréler le failover dans les traces

Le tracing Microsoft Foundry peut envoyer la télémétrie d’exécution des agents dans Application Insights. Quel que soit le chemin d’instrumentation, l’enquête de failover a besoin d’une chaîne continue entre requête, modèle, retrieval et outils.

kusto 01-agent-regional-failover.kql
let IncidentStart = datetime(2026-09-04T07:42:00Z);
let IncidentEnd = IncidentStart + 45m;
AgentRunEvents
| where TimeGenerated between (IncidentStart .. IncidentEnd)
| where AgentName == "operations-assistant"
| summarize
  Runs = dcount(RunId),
  FailedRuns = dcountif(RunId, RunStatus != "completed"),
  P95LatencyMs = percentile(DurationMs, 95),
  ToolCalls = countif(EventType == "tool_call"),
  DuplicateOperations = dcountif(OperationId, IsDuplicate == true),
  MissingTraceContext = countif(isempty(TraceId) or isempty(DeploymentVersion))
by Region, DeploymentName, AgentVersion, bin(TimeGenerated, 5m)
| extend FailureRate = todouble(FailedRuns) / Runs
| order by TimeGenerated asc

Adaptez table et champs au contrat de télémétrie. Associez les métriques opérationnelles à des évaluations échantillonnées : un faible taux d’erreur ne révèle ni dérive d’ancrage, ni changement d’outil, ni refus affaibli.

Décider attente, bascule, retour ou rollback

Le runbook se termine par une décision explicite sur le trafic et les contrôles.

text regional-failover-decision.txt
Rester sur le chemin principal
Degradation non reproduite ou scope des dependances inconnu
Configuration, etat ou traces du candidat non prouves
Risque de reprise superieur a l'impact borne de l'incident

Basculer le trafic read-only
Sondes et gates d'evaluation du candidat validees
Nouvelles sessions isolables et tracables
Outils d'ecriture toujours bloques

Promouvoir le chemin candidat
Canari conforme aux gates operationnelles, qualite et controle
Ownership d'etat et idempotence prouves
Outils, identite et approbations conformes au contrat approuve

Revenir au chemin principal
Sante principale stable pendant la fenetre d'observation
Retour progressif des nouvelles sessions avec affinite
Runs du candidat termines ou explicitement reconcilies

Rollbacker le changement de routage
Echec d'une gate de qualite, refus, trace ou etat
Poids du candidat remis a zero
Actions ambigues reconciliees avant tout retry
Preuves d'incident conservant les deux chemins regionaux

Automatisez la collecte des sondes, les poids de trafic et les conditions d’arrêt lorsque leur sémantique est déterministe. Gardez la décision d’écriture en production derrière une gate explicite tant que le chemin secondaire n’a pas prouvé la même frontière d’action que le principal.

Conclusion

Le failover régional d’un agent IA modifie un système opérationnel ; ce n’est pas un raccourci DNS autour d’un modèle indisponible. Le modèle peut répondre alors que l’état, le retrieval, les outils, les identités ou les contrôles d’approbation divergent.

Basculez la plus petite charge utile, prouvez versions et policies, évaluez les résultats, protégez les effets de bord et canariez avec continuité des traces. Ne promouvez le candidat que si disponibilité, qualité et contrôle passent ensemble. Sinon, attendez ou revenez au chemin principal, réconciliez chaque action ambiguë et gardez le rollback plus étroit que l’incident.