View a markdown version of this page

Exécuter un A/B test avec un routage basé sur les cibles - Amazon Bedrock AgentCore

Exécuter un A/B test avec un routage basé sur les cibles

Utilisez le modèle de routage basé sur la cible lorsque la modification que vous testez implique des modifications de code, une mise à niveau du framework ou une implémentation d'agent totalement différente. Target-based le routage achemine le trafic entre plusieurs versions du même AgentCore environnement d'exécution (points de terminaison nommés) ou entre des environnements d' AgentCore exécution totalement différents. La AgentCore passerelle enregistre chaque point de terminaison en tant que cible distincte et achemine chaque session vers l'un ou l'autre point de terminaison en fonction des pondérations du trafic du A/B test.

Configuration clé pour les tests basés sur des cibles A/B  :

  • Configuration de variante : variantConfiguration.target avec le nom de la cible de la AgentCore passerelle

  • Configuration d'évaluation : perVariantOnlineEvaluationConfig (une configuration d'évaluation en ligne par variante, puisque chaque point de terminaison possède son propre groupe de journaux)

  • Filtre de passerelle : gatewayFilter.targetPaths définit les chemins de AgentCore passerelle interceptés par le A/B test

Cette procédure pas à pas déploie deux versions de l'agent de support client, l'une utilisant Claude Sonnet (contrôle) et l'autre utilisant Claude Opus (traitement). Elle crée des points de terminaison nommés pour chaque version, crée un A/B test, envoie du trafic, examine les résultats et désigne le gagnant.

Note

Cette procédure pas à pas est destinée aux agents hébergés sur un AgentCore Runtime. Si votre agent s'exécute en dehors AgentCore d'un environnement d'exécution (un agent tiers ou auto-hébergé, par exemple sur AWS Lambda), consultez plutôt Exécuter A/B un test pour les agents hébergés en dehors AgentCore de.

Pour une comparaison détaillée des modèles de A/B test, voir Choisir un modèle.

Étape 1 : Création du projet

Créez le projet à l'aide de la AgentCore CLI :

agentcore create --name ABTestTargetBased --no-agent cd ABTestTargetBased

Étape 2 : ajouter le runtime

Ajoutez le runtime de l'agent. Vous déploierez deux versions de ce runtime, l'une pour le contrôle et l'autre pour le traitement, puis créerez des points de terminaison nommés pour aliaser chaque version.

agentcore add agent \ --name csAgent \ --language Python \ --framework Strands \ --model-provider Bedrock \ --memory none \ --build CodeZip

Structure du projet :

ABTestTargetBased/
├── agentcore/
│   ├── agentcore.json
│   ├── aws-targets.json
│   └── cdk/
└── app/
    └── csAgent/
        ├── main.py
        └── pyproject.toml

Étape 3 : Déployer les versions de contrôle et de traitement

Remplacez app/csAgent/main.py par la version de contrôle (en utilisant Claude Sonnet) :

"""Customer support agent — control variant.""" from strands import Agent, tool from strands.models.bedrock import BedrockModel from bedrock_agentcore.runtime import BedrockAgentCoreApp app = BedrockAgentCoreApp() MODEL_ID = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" SYSTEM_PROMPT = "You are a helpful customer support assistant for Acme Store." @tool def lookup_order(order_id: str) -> str: """Look up an order by ID.""" orders = { "ORD-1001": {"status": "delivered", "item": "Blue T-Shirt", "total": "$29.99"}, "ORD-1002": {"status": "in_transit", "item": "Running Shoes", "est_delivery": "2026-04-05"}, "ORD-1003": {"status": "delayed", "item": "Wireless Headphones", "days_late": 5}, } return str(orders.get(order_id, {"error": f"Order {order_id} not found"})) @tool def initiate_return(order_id: str, reason: str) -> str: """Initiate a return for an order.""" return f"Return initiated for {order_id}. Reason: {reason}. Return label sent to customer email." @tool def apply_discount(order_id: str, discount_percent: int, reason: str) -> str: """Apply a discount to an order.""" return f"Applied {discount_percent}% discount to {order_id}. Reason: {reason}." agent = Agent( model=BedrockModel(model_id=MODEL_ID), tools=[lookup_order, initiate_return, apply_discount], system_prompt=SYSTEM_PROMPT, ) @app.entrypoint def invoke(payload, context): result = agent(payload.get("prompt", "Hello")) return {"response": result.message["content"][0]["text"]} if __name__ == "__main__": app.run()

Mettre à jour app/csAgent/pyproject.toml les dépendances :

dependencies = [ "aws-opentelemetry-distro", "bedrock-agentcore >= 1.8.0", "boto3", "botocore[crt] >= 1.35.0", "strands-agents[otel] >= 1.13.0", "opentelemetry-distro", "opentelemetry-instrumentation", ]

Déployez la version de contrôle (cela crée la version 1) :

agentcore deploy

Effectuez maintenant main.py la mise à jour pour utiliser un modèle différent pour la variante de traitement et déployez (cela crée la version 2) :

MODEL_ID = "global.anthropic.claude-opus-4-6-v1"
agentcore deploy

Créez des points de terminaison nommés pour chaque version et déployez :

agentcore add runtime-endpoint \ --runtime csAgent \ --endpoint control \ --version 1 \ --description "Control variant — Claude Sonnet" agentcore add runtime-endpoint \ --runtime csAgent \ --endpoint treatment \ --version 2 \ --description "Treatment variant — Claude Opus" agentcore deploy

Vous disposez désormais de :

  • Point de terminaison d'exécution control : serveur de la version 1 avec Claude Sonnet.

  • Point de terminaison d'exécution treatment : serveur de la version 2 avec Claude Opus.

Vérifiez que le moteur d'exécution fonctionne :

agentcore invoke --runtime csAgent --prompt "What is the status of order ORD-1003?"

Vous disposez désormais de :

  • Point de terminaison d'exécution control : serveur de la version 1 avec Claude Sonnet.

  • Point de terminaison d'exécution treatment : serveur de la version 2 avec Claude Opus.

Étape 4 : Création de configurations d'évaluation en ligne

Chaque point de terminaison possède son propre groupe de journaux (le nom du groupe de journaux se termine par le nom du point de terminaison). Vous avez donc besoin d'une configuration d'évaluation en ligne par variante :

agentcore add online-eval \ --name controlEvalTb \ --runtime csAgent \ --endpoint control \ --evaluator "Builtin.Helpfulness" \ --sampling-rate 100.0 \ --enable-on-create agentcore add online-eval \ --name treatmentEvalTb \ --runtime csAgent \ --endpoint treatment \ --evaluator "Builtin.Helpfulness" \ --sampling-rate 100.0 \ --enable-on-create agentcore deploy

Après chaque déploiement, notez l'ARN de configuration d'évaluation en ligne : vous aurez besoin des deux lors de la création du A/B test.

Pour plus de détails sur les options et la configuration de l'évaluateur, voir Créer une évaluation en ligne.

Étape 5 : Création de la passerelle et des cibles

Un A/B test basé sur des cibles achemine le trafic via une AgentCore passerelle, de sorte que la passerelle et ses deux cibles doivent déjà être déployées avant que vous ne commenciez le test. Ajoutez une passerelle et enregistrez chaque point de terminaison d'exécution en tant que http-runtime cible, puis déployez :

agentcore add gateway --name csGateway agentcore add gateway-target \ --name customer-support-control \ --gateway csGateway \ --type http-runtime \ --runtime csAgent \ --runtime-endpoint control agentcore add gateway-target \ --name customer-support-treatment \ --gateway csGateway \ --type http-runtime \ --runtime csAgent \ --runtime-endpoint treatment agentcore deploy

Étape 6 : Création du A/B test

Commencez le A/B test avecagentcore run ab-test. Chaque variante fait référence à l'une des cibles de passerelle que vous avez créées et possède sa propre configuration d'évaluation en ligne. La commande lance le test directement sur le service par rapport à la passerelle déjà déployée.

Exemple
AgentCore CLI
agentcore run ab-test \ --mode target-based \ --name customerSupportTargetTest \ --gateway csGateway \ --runtime csAgent \ --control-target customer-support-control \ --treatment-target customer-support-treatment \ --control-online-eval controlEvalTb \ --treatment-online-eval treatmentEvalTb \ --control-weight 80 \ --treatment-weight 20

Le test est en cours dès le retour de la commande. La passe --disable-on-create pour le créer s'est arrêtée. L'--gatewayindicateur est obligatoire et doit faire référence à la passerelle que vous avez déployée à l'étape 5. Un seul test peut être exécuté par passerelle à la fois. La commande imprime l'ID de tâche du test, qui est également disponible --json sous forme de id champ. Vous avez besoin de cet identifiant pour les commandes de cycle de vie ci-dessous.

AWS SDK (boto3)
import boto3 import uuid REGION = "us-west-2" ACCOUNT_ID = "123456789012" # Runtime ARNs from Step 2 deployment output CONTROL_RUNTIME_ARN = f"arn:aws:bedrock-agentcore:{REGION}:{ACCOUNT_ID}:runtime/ABTestTargetBased_CustomerSupportControl-abc123" TREATMENT_RUNTIME_ARN = f"arn:aws:bedrock-agentcore:{REGION}:{ACCOUNT_ID}:runtime/ABTestTargetBased_CustomerSupportTreatment-def456" # Online evaluation config ARNs from Step 3 CONTROL_EVAL_ARN = f"arn:aws:bedrock-agentcore:{REGION}:{ACCOUNT_ID}:online-evaluation-config/controlEvalTb-abc123" TREATMENT_EVAL_ARN = f"arn:aws:bedrock-agentcore:{REGION}:{ACCOUNT_ID}:online-evaluation-config/treatmentEvalTb-def456" # IAM roles GATEWAY_ROLE_ARN = f"arn:aws:iam::{ACCOUNT_ID}:role/AgentCoreGatewayRole" AB_TEST_ROLE_ARN = f"arn:aws:iam::{ACCOUNT_ID}:role/ABTestRole" cp_client = boto3.client("bedrock-agentcore-control", region_name=REGION) dp_client = boto3.client("bedrock-agentcore", region_name=REGION) # 1. Create an AgentCore Gateway gateway_response = cp_client.create_gateway( name="customerSupportTargetTest-gw", roleArn=GATEWAY_ROLE_ARN, authorizerType="AWS_IAM", clientToken=str(uuid.uuid4()), ) gateway_id = gateway_response["gatewayId"] gateway_arn = gateway_response["gatewayArn"] print(f"Created AgentCore Gateway: {gateway_id}") # 2. Add control runtime as an AgentCore Gateway target cp_client.create_gateway_target( gatewayIdentifier=gateway_id, name="customer-support-control", targetConfiguration={ "http": { "agentcoreRuntime": { "arn": CONTROL_RUNTIME_ARN, "qualifier": "DEFAULT" } } }, clientToken=str(uuid.uuid4()), ) print("Added target: customer-support-control") # 3. Add treatment runtime as an AgentCore Gateway target cp_client.create_gateway_target( gatewayIdentifier=gateway_id, name="customer-support-treatment", targetConfiguration={ "http": { "agentcoreRuntime": { "arn": TREATMENT_RUNTIME_ARN, "qualifier": "DEFAULT" } } }, clientToken=str(uuid.uuid4()), ) print("Added target: customer-support-treatment") # 4. Create the A/B test response = dp_client.create_ab_test( name="customerSupportTargetTest", gatewayArn=gateway_arn, roleArn=AB_TEST_ROLE_ARN, evaluationConfig={ "perVariantOnlineEvaluationConfig": [ {"name": "C", "onlineEvaluationConfigArn": CONTROL_EVAL_ARN}, {"name": "T1", "onlineEvaluationConfigArn": TREATMENT_EVAL_ARN} ] }, gatewayFilter={ "targetPaths": ["/customer-support-control/*"] }, variants=[ { "name": "C", "weight": 80, "variantConfiguration": { "target": {"name": "customer-support-control"} } }, { "name": "T1", "weight": 20, "variantConfiguration": { "target": {"name": "customer-support-treatment"} } } ], enableOnCreate=True, clientToken=str(uuid.uuid4()), ) ab_test_id = response["abTestId"] print(f"Created A/B test: {ab_test_id}") print(f"Status: {response['status']}") print(f"Execution status: {response['executionStatus']}")

Étape 7 : envoyer du trafic via la AgentCore passerelle

Une fois le A/B test exécuté, envoyez le trafic via le point de terminaison HTTP AgentCore Gateway. La AgentCore passerelle attribue chaque demande à une variante (contrôle ou traitement) en fonction de l'ID de session d'exécution.

Comment fonctionne l'attribution de variantes

La AgentCore passerelle utilise l'X-Amzn-Bedrock-AgentCore-Runtime-Session-Iden-tête pour déterminer la cible vers laquelle acheminer le trafic. Cet en-tête est facultatif. Si vous ne le fournissez pas, le moteur d'exécution génère automatiquement un identifiant de session. La AgentCore passerelle utilise ensuite l'ID de session (que vous l'ayez fourni ou que le moteur d'exécution l'ait généré) pour attribuer la demande à une variante en fonction de vos pondérations de trafic configurées.

L'attribution de session est permanente : une fois qu'un identifiant de session est attribué à une variante, toutes les demandes suivantes portant le même identifiant de session sont acheminées vers la même cible. Cela garantit une expérience cohérente au sein d'une session tout en répartissant les nouvelles sessions entre les variantes en fonction de la répartition du trafic.

Générer du trafic pour les tests

Enregistrez le script suivant sous le loadgen.sh nom, en <target-name> remplaçant <gateway-id> et par les valeurs de votre sortie de déploiement. Vous pouvez également copier l'URL d'appel complète depuis agentcore view ab-test <ab-test-id> :

#!/bin/bash export AWS_ACCESS_KEY_ID=$(aws configure get aws_access_key_id) export AWS_SECRET_ACCESS_KEY=$(aws configure get aws_secret_access_key) export AWS_SESSION_TOKEN=$(aws configure get aws_session_token) GATEWAY_URL="https://<gateway-id>.gateway.bedrock-agentcore.us-west-2.amazonaws.com/<target-name>/invocations" PROMPTS=( "What is the status of order ORD-1003?" "I want to return order ORD-1001, it doesn't fit." "My order ORD-1003 is late. Can I get a discount?" "Where is my order ORD-1002?" "I need help with a return for order ORD-1001. The color is wrong." "Can you check on order ORD-1003? I've been waiting forever." "I'd like to cancel order ORD-1002 if it hasn't shipped yet." "Order ORD-1003 is delayed again. This is unacceptable." "What's your return policy for order ORD-1001?" "My headphones order ORD-1003 still hasn't arrived. What can you do?" ) for i in $(seq 1 30); do PROMPT="${PROMPTS[$(( (i - 1) % ${#PROMPTS[@]} ))]}" echo "=== Request $i: $PROMPT ===" curl -s --aws-sigv4 "aws:amz:us-west-2:bedrock-agentcore" \ --user "$AWS_ACCESS_KEY_ID:$AWS_SECRET_ACCESS_KEY" \ -H "x-amz-security-token: $AWS_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: $(uuidgen)" \ -d "{\"prompt\": \"$PROMPT\"}" \ -X POST \ "$GATEWAY_URL" echo "" sleep 2 done

Exécutez le script  :

bash loadgen.sh

Étape 8 : Obtenir des résultats

Interrogez le A/B test pour surveiller les résultats à mesure que la taille des échantillons augmente. Le sondage n'affecte pas la validité des statistiques.

Exemple
AgentCore CLI

Obtenez les résultats actuels (remplacez-les <ab-test-id> par l'ID de tâche indiqué à l'étape 6) :

agentcore view ab-test <ab-test-id>

Obtenez les résultats au format JSON :

agentcore view ab-test <ab-test-id> --json
AWS SDK (boto3)

Effectuez un sondage jusqu'à ce que les résultats atteignent une signification statistique :

import boto3 import time client = boto3.client("bedrock-agentcore", region_name="us-west-2") ab_test_id = "customerSupportTargetTest-Ab1Cd2Ef3G" while True: response = client.get_ab_test(abTestId=ab_test_id) status = response["status"] exec_status = response["executionStatus"] print(f"Status: {status}, Execution: {exec_status}") results = response.get("results") if results: print(f"Analysis timestamp: {results.get('analysisTimestamp')}") for metric in results["evaluatorMetrics"]: evaluator = metric["evaluatorArn"] control = metric["controlStats"] print(f"\nEvaluator: {evaluator}") print(f" Control: mean={control['mean']:.3f}, n={control['sampleSize']}") for variant in metric["variantResults"]: print(f" {variant['variantName']}: mean={variant['mean']:.3f}, " f"n={variant['sampleSize']}, " f"pValue={variant.get('pValue', 'N/A')}, " f"significant={variant['isSignificant']}") if variant["isSignificant"]: print(f" >>> Statistically significant! " f"Change: {variant.get('percentChange', 0):.1f}%") # Check if any evaluator has reached significance all_significant = all( variant["isSignificant"] for metric in results["evaluatorMetrics"] for variant in metric["variantResults"] ) if all_significant: print("\nAll evaluators have reached statistical significance.") break time.sleep(300) # Poll every 5 minutes
Note

Le temps nécessaire pour que les résultats apparaissent dépend principalement du délai d'expiration de session configuré dans vos configurations d'évaluation en ligne. Une session est considérée comme terminée lorsqu'aucune nouvelle demande n'arrive dans le délai imparti. À la fin d'une session, les résultats apparaissent généralement dans les 15 minutes. Les résultats s'accumulent au fur et à mesure que de nouvelles sessions se terminent ; la signification statistique s'améliore avec la taille de l'échantillon.

Interprétation des résultats
  • valeur p < 0,05 et positive percentChange : le traitement est nettement meilleur que le traitement témoin. Envisagez de déployer le traitement.

  • valeur p < 0,05 et négative percentChange : le traitement est nettement pire. Gardez le contrôle.

  • valeur de p >= 0,05 : preuves insuffisantes pour conclure à une différence. Continuez à prélever des échantillons ou augmentez le trafic vers le traitement.

  • Vérifiez tous les évaluateurs : un traitement peut améliorer un indicateur tout en régressant un autre. Passez en revue tous les résultats de l'évaluateur avant de prendre une décision.

Étape 9 : Confirmer les résultats et arrêter le A/B test

Une fois que le A/B test atteint une signification statistique, passez en revue les résultats et arrêtez l'expérience.

  1. Confirmez l'importance. Vérifiez que l'évaluateur cible a donné isSignificant: true un résultat positif à percentChange la variante du traitement (ou confirmez que le contrôle est gagnant si le traitement régresse).

  2. Arrêtez le A/B test. Exécutez agentcore stop ab-test -i <ab-test-id>. Le routage du trafic prend fin immédiatement et toutes les demandes reviennent à la cible par défaut. Voir Afficher, mettre en pause, reprendre et arrêter.

Étape 10 : Déployer le gagnant

Après avoir arrêté le A/B test, acheminez tout le trafic vers la variante gagnante.

agentcore promote ab-test -i <ab-test-id> agentcore deploy

promotearrête le A/B test (s'il est toujours en cours d'exécution), met à jour le point final de contrôle pour qu'il pointe vers la version du traitement (par exemple, mise à jour control de la version 1 vers la version 2) et supprime le point de terminaison du traitement. Exécutez agentcore deploy pour appliquer les modifications.

Vous pouvez également déployer manuellement le gagnant en effectuant l'une des opérations suivantes :

  • Option A : utilisez les règles de routage de la AgentCore passerelle pour diriger le trafic des deux cibles vers la cible gagnante.

  • Option B : retirez la cible perdante de la AgentCore passerelle et acheminez tout le trafic vers le gagnant.

  • Option C : mettez à jour la cible perdante pour qu'elle pointe vers le point final gagnant.

Étapes suivantes

Après avoir déployé le gagnant :

  • Supprimez le A/B test pour nettoyer les ressources. Voir Supprimer un A/B test.

  • Surveillez la nouvelle base de référence. L'évaluation en ligne poursuit les sessions de notation sur la configuration gagnante. Surveillez les régressions.

  • Lancez l'itération suivante. Les nouvelles traces issues de la configuration gagnante constituent la base du prochain cycle de recommandation. Découvrez comment cela fonctionne.

Comprendre les résultats

Lorsque vous appelezGetABTest, la réponse inclut un results objet une fois que le pipeline d'agrégation a traité suffisamment de sessions. Les résultats contiennent des métriques par évaluateur ventilées par variante.

Structure des résultats

{ "results": { "analysisTimestamp": "2026-04-30T18:45:00Z", "evaluatorMetrics": [ { "evaluatorArn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:evaluator/Builtin.Helpfulness", "controlStats": { "variantName": "C", "sampleSize": 24, "mean": 0.72 }, "variantResults": [ { "variantName": "T1", "sampleSize": 6, "mean": 0.85, "absoluteChange": 0.13, "percentChange": 18.1, "pValue": 0.032, "confidenceInterval": { "lower": 0.02, "upper": 0.24 }, "isSignificant": true } ] } ] } }

Référence de champ

Champ Description

analysisTimestamp

Date à laquelle le service a calculé les statistiques pour la dernière fois.

evaluatorMetrics

Une entrée par évaluateur dans la configuration d'évaluation en ligne.

controlStats.mean

Note moyenne de l'évaluateur pour toutes les sessions de contrôle.

controlStats.sampleSize

Nombre de sessions notées pour la variante de contrôle.

variantResults[].mean

Note moyenne de l'évaluateur pour toutes les séances de traitement.

variantResults[].sampleSize

Nombre de séances notées pour la variante de traitement.

variantResults[].absoluteChange

Différence entre la moyenne de traitement et la moyenne de contrôle.

variantResults[].percentChange

Pourcentage d'amélioration (positif) ou de régression (négatif) par rapport au contrôle.

variantResults[].pValue

Probabilité : la différence observée est due au hasard. Une valeur inférieure à 0,05 indique une signification statistique.

variantResults[].confidenceInterval

Intervalle de confiance à 95 % pour le changement absolu (loweret les upper limites).

variantResults[].isSignificant

truelorsque la valeur de p est inférieure à 0,05 et que la taille des échantillons est suffisante.

Résolution des problèmes

A/B le test ne montre aucun résultat après l'envoi de trafic

Les résultats n'apparaissent pas immédiatement. Le temps nécessaire dépend du délai d'expiration de session configuré dans votre configuration d'évaluation en ligne. Une session est considérée comme terminée uniquement lorsqu'aucune nouvelle demande n'est arrivée dans le délai imparti. Après la fin d'une séance, attendez-vous à des résultats dans un délai d'environ 15 minutes.

Si les résultats ne s'affichent toujours pas après cette fenêtre :

  • Vérifiez le groupe de journaux d'évaluation en ligne. La configuration d'évaluation en ligne doit pointer vers le groupe de journaux de sortie de l'agent d'exécution. Si la configuration d'évaluation en ligne fait référence à un autre groupe de journaux (ou à un groupe qui ne reçoit aucun intervalle de temps de la part de votre environnement d'exécution), les sessions ne seront pas notées et le A/B test ne produira jamais de résultats.

  • Vérifiez le nom du groupe de journaux. Pour le routage basé sur les cibles, chaque point de terminaison possède son propre groupe de journaux (le nom du groupe de journaux se termine par le nom du point de terminaison). Assurez-vous que chaque configuration d'évaluation en ligne fait référence au groupe de journaux du point de terminaison approprié.

  • Vérifiez que le moteur d'exécution émet des intervalles. Vérifiez CloudWatch les journaux pour le groupe de journaux attendu. Les principaux attributs que vous recherchez pour chaque intervalle :

    • aws.agentcore.gateway.routing_experiment_arn

    • aws.agentcore.gateway.routing_experiment_variant_name(valeurs : C ouT1)

    • session.id

  • Vérification par CLI-created rapport aux configurations manuelles. Si vous l'avez utiliséagentcore add online-eval --runtime <name>, la CLI configure automatiquement le groupe de journaux approprié. Si vous avez créé la configuration d'évaluation en ligne manuellement via l'API, assurez-vous que la configuration d'évaluation AgentCore en ligne dataSourceConfig.cloudWatchLogs.logGroupNames correspond au groupe de journaux d'intervalle de votre environnement d'exécution.