View a markdown version of this page

使用配置包运行 A/B 测试 - Amazon Bedrock AgentCore

使用配置包运行 A/B 测试

如果您正在测试的更改纯粹是配置(不同的系统提示、不同的型号 ID 或不同的工具描述),请使用配置包模式。这两个变体在同一个 AgentCore 运行时上运行,配置包版本不同。 AgentCore Gateway 通过 W3C 行李标头将正确的捆绑包引用注入到每个请求中,您的代理会在运行时读取它。这意味着您需要部署一个 AgentCore 运行时配置和一个在线评估配置。

配置包 A/B 测试的关键配置:

  • 变体配置:variantConfiguration.configurationBundle包含捆绑包 ARN 和版本

  • 评估配置:单一共享 onlineEvaluationConfigArn

如果您正在测试的更改涉及代码更改、框架升级或完全不同的代理实现,请改用基于目标的路由。请参见使用基于目标的路由进行 A/B 测试

本演练以客户支持代理为例。代理负责处理订单查询、退货和折扣请求。您将部署代理,创建两个具有不同系统提示(控制和处理)的配置包,创建 A/B 测试,发送流量,查看结果,然后部署获胜者。

步骤 1:创建项目

使用 AgentCore CLI 创建项目:

agentcore create --name ABTestConfigBased --no-agent cd ABTestConfigBased

第 2 步:添加运行时

添加代理运行时:

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

项目结构:

ABTestConfigBased/
├── agentcore/
│   ├── agentcore.json      # Project and resource configuration
│   ├── aws-targets.json    # Deployment target (account and region)
│   └── cdk/                # CDK infrastructure (auto-managed)
└── app/
    └── csAgent/
        ├── main.py         # Agent entrypoint
        └── pyproject.toml  # Python dependencies

步骤 3:更新代理代码并部署

app/csAgent/main.py替换为以下内容。关键的补充是在运行时读取活动配置包的BeforeModelCallEvent挂钩:

"""Customer support agent with configuration bundle integration.""" from strands import Agent, tool from strands.models.bedrock import BedrockModel from strands.hooks.events import BeforeModelCallEvent from bedrock_agentcore.runtime import BedrockAgentCoreApp, BedrockAgentCoreContext app = BedrockAgentCoreApp() DEFAULT_MODEL_ID = "global.anthropic.claude-sonnet-4-5-20250929-v1:0" DEFAULT_SYSTEM_PROMPT = "You are a helpful customer support assistant." @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}." def dynamic_config_hook(event: BeforeModelCallEvent): """Read config bundle and apply system prompt before every model call.""" config = BedrockAgentCoreContext.get_config_bundle() event.agent.system_prompt = config.get("system_prompt", DEFAULT_SYSTEM_PROMPT) agent = Agent( model=BedrockModel(model_id=DEFAULT_MODEL_ID), tools=[lookup_order, initiate_return, apply_discount], system_prompt=DEFAULT_SYSTEM_PROMPT, ) agent.hooks.add_callback(BeforeModelCallEvent, dynamic_config_hook) @app.entrypoint def invoke(payload, context): result = agent(payload.get("prompt", "Hello")) return {"response": result.message["content"][0]["text"]} if __name__ == "__main__": app.run()

更新app/csAgent/pyproject.toml依赖关系:

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", ]

将客户支持代理部署到 AgentCore Runtime:

agentcore deploy

部署后,记下输出中的运行时 ARN(例如)。arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/csAgent-abc123您将需要它来创建配置包。

验证代理是否正在运行:

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

BeforeModelCallEvent挂钩在每次 LLM 调用之前触发,从请求上下文中读取活动配置包。在 A/B 测试期间, AgentCore Gateway 会将每个会话分配给一个变体,并通过 W3C 行李标头传播相应的捆绑包引用。运行时通过使其可用BedrockAgentCoreContext,因此控制会话接收捆绑包 v1,治疗会话接收捆绑包 v2 — 代理会应用它收到的捆绑包中的任何系统提示。

有关更多详细信息,请参阅在运行时使用配置包

步骤 4:创建配置包

创建两个配置包 — 一个用于控制(当前提示),另一个用于治疗(优化提示)。 A/B 测试将在这些提示之间分配流量,以衡量哪个提示会产生更好的评估者分数。

控制包 — 当前系统提示符:

agentcore add config-bundle \ --name customerSupportControl \ --components '{ "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/csAgent-abc123": { "configuration": { "system_prompt": "You are a helpful customer support assistant for Acme Store." } } }' agentcore deploy

治疗包 — 一种经过优化的系统提示,可指示代理更加积极主动:

agentcore add config-bundle \ --name customerSupportTreatment \ --components '{ "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/csAgent-abc123": { "configuration": { "system_prompt": "You are a customer support assistant for Acme Store. Be proactive: check order status before the customer asks, offer discounts for delayed orders, and summarize actions taken at the end of each response." } } }' agentcore deploy

每次部署后,请记下输出中的捆绑包 ARN 和版本 ID,创建测试时将需要这些。 A/B

步骤 5:创建在线评估配置

A/B 测试需要在线评估配置才能对两种变体的会话进行评分。在线评估让评估人员根据实时流量进行评估,并将分数提供给 A/B 测试的统计引擎。

对于配置包变体,请创建一个用于监控共享 AgentCore 运行时的在线评估配置:

agentcore add online-eval \ --name customerSupportEval \ --runtime csAgent \ --evaluator "Builtin.Helpfulness" \ --sampling-rate 100.0 \ --enable-on-create agentcore deploy

部署后,请记下输出中的在线评估配置 ARN,创建测试时将需要它。 A/B

提示

--sampling-rate 100.0在 A/B 测试期间进行设置,以便对每个会话进行评估,结果更快地达到统计学意义。您可以在测试结束后降低费率。

有关评估器选项和配置的更多详细信息,请参阅创建在线评估

步骤 6:创建网关和目标

config-bundle A/B 测试通过 AgentCore 网关路由流量,因此在开始测试之前,必须已经部署了网关及其目标。添加以运行时为http-runtime目标的网关,然后部署:

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

步骤 7:创建 A/B 测试

创建在控制提示和治疗提示 80/20 之间分配流量的 A/B 测试。这两个变体都引用同一 AgentCore Runtime 上的配置包,并共享一个用于评分的在线评估配置。

AgentCore CLI
agentcore run ab-test \ --mode config-bundle \ --name customerSupportPromptTest \ --gateway csGateway \ --runtime csAgent \ --control-bundle customerSupportControl \ --control-version <control-bundle-version-id> \ --treatment-bundle customerSupportTreatment \ --treatment-version <treatment-bundle-version-id> \ --online-eval customerSupportEval \ --control-weight 80 \ --treatment-weight 20

agentcore run ab-test在服务上启动 A/B 测试作业。命令返回后,测试即在运行。传球--disable-on-create来创建它已停止。要查看作业agentcore view ab-test <id>,请运行或查看 JSON 下的作业.cli/jobs/ab-tests/。该--gateway标志为必填项,并且必须引用您在步骤 6 中部署的网关。每个网关一次只能运行一个测试。该命令会打印测试的作业 ID,也可以从id字段中--json获得。以下生命周期命令需要此 ID。

注意

--control-version--treatment-version值是在步骤 3 中部署配置包时返回的版本 ID。

AWS SDK (boto3)
import boto3 import uuid client = boto3.client("bedrock-agentcore", region_name="us-west-2") response = client.create_ab_test( name="customerSupportPromptTest", gatewayArn="arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/gw-abc123", roleArn="arn:aws:iam::123456789012:role/ABTestRole", evaluationConfig={ "onlineEvaluationConfigArn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:online-evaluation-config/eval-abc123" }, variants=[ { "name": "C", "weight": 80, "variantConfiguration": { "configurationBundle": { "bundleArn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:configuration-bundle/customerSupportControl-Ab1Cd2Ef3G", "bundleVersion": "12345678-1234-1234-1234-123456789012" } } }, { "name": "T1", "weight": 20, "variantConfiguration": { "configurationBundle": { "bundleArn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:configuration-bundle/customerSupportTreatment-Ab1Cd2Ef3G", "bundleVersion": "12345678-1234-5678-9abc-123456789012" } } } ], 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']}")

步骤 8:通过 AgentCore 网关发送流量

A/B 测试运行后,通过 AgentCore 网关 HTTP 端点发送流量。 AgentCore Gateway 根据运行时会话 ID 将每个请求分配给变体(对照或治疗)。

变体赋值的工作原理

AgentCore Gateway 使用X-Amzn-Bedrock-AgentCore-Runtime-Session-Id标头来确定要提供哪种配置包变体。此标头是可选的,如果您不提供该标头,则运行时会自动生成会话 ID。然后, AgentCore 网关使用会话 ID(无论是您提供的,还是运行时生成的),根据您配置的流量权重将请求分配给变体。

会话分配是粘性的:将会话 ID 分配给变体后,所有具有相同会话 ID 的后续请求都会路由到同一个变体。这样可以确保在会话中获得一致的体验,同时仍能根据您的流量分配跨变体分配新会话。

生成用于测试的流量

将以下脚本另存为 loadgen.sh<gateway-id><target-name>用部署输出中的值替换和:

#!/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

运行脚本:

bash loadgen.sh

第 9 步:获取结果

随着样本量的增长,对 A/B 测试进行轮询以监控结果。轮询不影响统计的有效性。

AgentCore CLI

获取当前结果(<ab-test-id>替换为步骤 6 中的任务 ID):

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

以 JSON 格式获取结果:

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

在结果达到统计意义之前进行民意调查:

import boto3 import time client = boto3.client("bedrock-agentcore", region_name="us-west-2") ab_test_id = "customerSupportPromptTest-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
注意

显示结果所需的时间主要取决于在线评估配置中配置的会话超时。如果在超时窗口内没有新的请求到达,则认为会话已完成。会话结束后,结果通常会在 15 分钟内出现。结果会随着更多会话的完成而累积——统计显著性随着样本量的增加而提高。

解析结果
  • p 值 < 0.05 且呈阳性percentChange治疗明显优于对照组。考虑部署治疗方案。

  • p 值 < 0.05 且为阴性percentChange治疗明显恶化。保持控制权。

  • p 值 >= 0.05:没有足够的证据来得出差异结论。继续收集样本或增加前往治疗的流量。

  • 检查所有评估者:一种治疗可以改善一个指标,而另一个指标却倒退。在做出决定之前,请查看所有评估者的结果。

有关结果结构和字段定义的详细说明,请参阅基于目标的路由指南中的了解结果

第 10 步:确认结果并停止 A/B 测试

一旦 A/B 检验达到统计显著性,请查看结果并停止实验。

  1. 确认重要性。验证目标评估者对isSignificant: true治疗变异的检测结果是否为阳性percentChange(或者如果治疗恶化,则确认对照组是赢家)。

  2. 停止 A/B 测试。运行 agentcore stop ab-test -i <ab-test-id>。流量路由立即结束,所有请求都恢复为默认配置。请参阅查看、暂停、恢复和停止

第 11 步:部署获胜者

停止 A/B 测试后,将所有流量路由到获胜的配置包版本。

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

promote停止 A/B 测试(如果仍在运行)并更新控制配置包以使用治疗版本。运行agentcore deploy以应用更改。

或者,您可以通过执行以下任一操作来手动部署获胜者:

  • 选项 A:使用AgentCore 网关路由规则路由获胜配置包版本的所有流量。

  • 选项 B:更新控制配置包以使用获胜的系统提示符并重新部署。

  • 选项 C:在代理代码中将获胜的捆绑包版本设置为默认版本,然后删除 A/B 测试配置。

后续步骤

部署获胜者后:

  • 删除 A/B 测试以清理资源。请参阅删除 A/B 测试

  • 监控新基线。在线评估继续对获胜配置进行评分。注意回归。

  • 开始下一次迭代。获胜配置的新痕迹为下一个推荐周期奠定了基础。查看其工作原理

示例: A/B 测试工具描述

您可以使用相同的配置包模式来测试优化的工具描述。与代理直接读取捆绑包的系统提示 A/B 测试不同,工具描述覆盖由 AgentCore 网关应用。当代理tools/list通过网关调用时,网关会读取配置包并返回应用替代项的工具描述。无需更改代理代码。

有关网关如何应用工具描述覆盖的详细信息,请参阅 MCP 目标上的行为

配置捆绑包

控制包-当前工具描述:

agentcore add config-bundle \ --name toolDescControl \ --components '{ "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/csAgent-abc123": { "configuration": { "tools": { "lookup_order": { "description": "Look up an order by ID." }, "initiate_return": { "description": "Initiate a return for an order." }, "apply_discount": { "description": "Apply a discount to an order." } } } } }' agentcore deploy

治疗套装 — 根据建议对工具描述进行了优化:

agentcore add config-bundle \ --name toolDescTreatment \ --components '{ "arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/csAgent-abc123": { "configuration": { "tools": { "lookup_order": { "description": "Look up order details including status, item, and total by order ID. Use when the customer asks about an order or references an order number." }, "initiate_return": { "description": "Start a return process for an order. Use only when the customer explicitly requests a return or exchange, not for order status inquiries." }, "apply_discount": { "description": "Apply a percentage discount to an order. Use when compensating for service issues such as delivery delays. Requires a reason." } } } } }' agentcore deploy

工作原理

  1. 当代理tools/list通过网关(MCP 目标)呼叫时, A/B 测试会将每个会话分配给网关上的变体(控制或处理),并解析相应的配置包。

  2. Gateway 读取配置包并返回应用替代项的工具描述。

  3. 代理使用返回的描述进行工具选择,无需更改代理代码。

创建 A/B 测试

agentcore run ab-test \ --mode config-bundle \ --name toolDescTest \ --gateway csGateway \ --runtime csAgent \ --control-bundle toolDescControl \ --control-version <control-bundle-version-id> \ --treatment-bundle toolDescTreatment \ --treatment-version <treatment-bundle-version-id> \ --online-eval customerSupportEval \ --control-weight 80 \ --treatment-weight 20

其余步骤(发送流量、获取结果、部署获胜者)与前面的系统提示示例相同。

问题排查

要对 A/B 测试问题(例如发送流量后缺少结果)进行故障排除,请参阅基于目标的路由指南中的故障排除