

# 使用組態套件執行 A/B 測試
<a name="ab-testing-config-bundle"></a>

當您測試的變更純為組態時，請使用組態套件模式：不同的系統提示、不同的模型 ID 或不同的工具描述。這兩個變體都以不同的組態套件版本在相同的 AgentCore 執行期上執行。AgentCore Gateway 透過 W3C 套件標頭將正確的套件參考注入每個請求，您的代理程式會在執行時間讀取。這表示您部署一個 AgentCore 執行期和一個線上評估組態。

組態套件 A/B 測試的金鑰組態：
+ 變體組態：`variantConfiguration.configurationBundle`使用套件 ARN 和版本
+ 評估組態：單一共用 `onlineEvaluationConfigArn` 

如果您要測試的變更涉及程式碼變更、架構升級或完全不同的客服人員實作，請改用目標型路由。請參閱[使用目標型路由執行 A/B 測試](ab-testing-target-based.md)。

本演練使用客戶支援客服人員做為範例。客服人員會處理訂單查詢、傳回和折扣請求。您將部署代理程式、使用不同的系統提示 （控制和處理） 建立兩個組態套件、建立 A/B 測試、傳送流量、檢閱結果，以及部署優勝者。

## 步驟 1：建立專案
<a name="config-bundle-create-project"></a>

使用 AgentCore CLI 建立專案：

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

## 步驟 2：新增執行時間
<a name="config-bundle-add-runtime"></a>

新增代理程式執行時間：

```
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：更新代理程式程式碼並部署
<a name="config-bundle-agent-code"></a>

`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 執行期：

```
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 — 代理程式會套用所接收套件中的任何系統提示。

如需詳細資訊，請參閱[在執行時間使用組態套件](configuration-bundles-runtime.md)。

## 步驟 4：建立組態套件
<a name="config-bundle-create-bundles"></a>

建立兩個組態套件：一個用於控制 （目前提示），另一個用於處理 （最佳化提示）。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 name="config-bundle-online-eval"></a>

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 測試時需要它。

**提示**  
在 A/B 測試`--sampling-rate 100.0`期間設定，以便評估每個工作階段和結果更快達到統計顯著性。您可以在測試結束後降低速率。

如需評估器選項和組態的詳細資訊，請參閱[建立線上評估](create-online-evaluations.md)。

## 步驟 6：建立閘道和目標
<a name="config-bundle-create-gateway"></a>

config-bundle A/B 測試會透過 AgentCore Gateway 路由流量，因此必須先部署閘道及其目標，才能開始測試。新增執行時間做為`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 測試
<a name="config-bundle-create-test"></a>

建立 A/B 測試，將控制和處理提示之間的流量分割為 80/20。這兩個變體都參考相同 AgentCore 執行期上的組態套件，並共用單一線上評估組態以進行評分。

**Example**  

```
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 測試任務。一旦命令傳回，測試即為 RUNNING。傳遞 `--disable-on-create` 以將其建立已停止。若要檢閱任務，請執行 `agentcore view ab-test <id>`，或在 下查看任務 JSON`.cli/jobs/ab-tests/`。`--gateway` 旗標為必要項目，且必須參考您在步驟 6 中部署的閘道。每個閘道一次只能執行一個測試。命令會列印測試的任務 ID，也可從 欄位取得`--json``id`。您需要以下生命週期命令的此 ID。  
`--control-version` 和 `--treatment-version`值是您在步驟 3 中部署組態套件時傳回的版本 IDs。

```
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 Gateway 傳送流量
<a name="config-bundle-send-traffic"></a>

A/B 測試執行後，請透過 AgentCore Gateway HTTP 端點傳送流量。AgentCore Gateway 會根據執行階段工作階段 ID，將每個請求指派給變體 （控制或處理）。

### 變體指派的運作方式
<a name="_how_variant_assignment_works"></a>

AgentCore Gateway 使用 `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id`標頭來決定要提供的組態套件變體。此標頭是**選用**的，如果您未提供，執行時間會自動產生工作階段 ID。AgentCore Gateway 接著會使用工作階段 ID （無論您提供該工作階段 ID 還是產生的執行時間），根據設定的流量權重將請求指派給變體。

工作階段指派很**黏**：將工作階段 ID 指派給變體後，所有具有相同工作階段 ID 路由至相同變體的後續請求。這可確保工作階段內的一致體驗，同時仍然會根據流量分割在變體之間分配新的工作階段。

### 產生用於測試的流量
<a name="_generate_traffic_for_testing"></a>

將下列指令碼儲存為 `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 name="config-bundle-get-results"></a>

輪詢 A/B 測試，以在樣本大小增加時監控結果。輪詢不會影響統計有效性。

**Example**  
取得目前結果 (`<ab-test-id>`以步驟 6 的任務 ID 取代）：  

```
agentcore view ab-test <ab-test-id>
```
取得 JSON 格式的結果：  

```
agentcore view ab-test <ab-test-id> --json
```
輪詢直到結果達到統計顯著性：  

```
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：**沒有足夠的證據來得出差異。繼續收集樣本或增加對處理的流量。
+  **檢查所有評估者：**處理可能會改善一個指標，同時迴歸另一個指標。在決定之前檢閱所有評估者結果。

如需結果結構和欄位定義的詳細說明，請參閱目標型路由指南中的[了解結果](ab-testing-target-based.md#target-based-results-shape)。

## 步驟 10：確認結果並停止 A/B 測試
<a name="config-bundle-confirm-stop"></a>

一旦 A/B 測試達到統計顯著性，請檢閱結果並停止實驗。

1.  **確認重要性。**確認目標評估器對`percentChange`處理變體具有正值 `isSignificant: true` （或者如果處理已迴歸，則確認控制項是獲勝者）。

1.  **停止 A/B 測試。**執行 `agentcore stop ab-test -i <ab-test-id>`。流量路由會立即結束，所有請求都會還原為預設組態。請參閱[檢視、暫停、繼續和停止](ab-testing-manage.md#manage-ab-test-start-stop)。

## 步驟 11：部署優勝者
<a name="config-bundle-deploy-winner"></a>

停止 A/B 測試後，將所有流量路由到獲勝的組態套件版本。

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

 `promote` 會停止 A/B 測試 （如果仍在執行），並更新控制組態套件以使用處理版本。執行 `agentcore deploy`以套用變更。

或者，您也可以執行下列其中一項操作來手動部署優勝者：
+  **選項 A：**使用 [AgentCore Gateway 路由規則](gateway-rules.md)，以獲勝的組態套件版本路由所有流量。
+  **選項 B：**更新控制組態套件以使用獲勝的系統提示並重新部署。
+  **選項 C：**將獲勝套件版本設定為代理程式程式碼中的預設值，並移除 A/B 測試組態。

部署得主之後：
+  **刪除 A/B 測試**以清除資源。請參閱[刪除 A/B 測試](ab-testing-manage.md#manage-ab-test-remove)。
+  **監控新的基準。**線上評估會繼續對獲勝組態的工作階段進行評分。注意迴歸。
+  **開始下一個反覆運算。**獲勝組態的新追蹤為下一個建議週期提供了基礎。請參閱[其運作方式](optimization-how-it-works.md)。

## 範例：A/B 測試工具描述
<a name="config-bundle-tool-description-example"></a>

您可以使用相同的組態套件模式來測試最佳化工具描述。與代理程式直接讀取套件的系統提示 A/B 測試不同，AgentCore Gateway 會套用工具描述覆寫。當客服人員`tools/list`透過閘道呼叫 時，閘道會讀取組態套件，並傳回套用覆寫的工具描述。不需要變更客服人員程式碼。

如需閘道如何套用工具描述覆寫的詳細資訊，請參閱 [MCP 目標上的行為](gateway-rules-propagation.md#gateway-rules-propagation-mcp)。

### 組態套件
<a name="_configuration_bundles"></a>

控制套件 — 目前的工具描述：

```
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
```

### 運作方式
<a name="_how_it_works"></a>

1. 當客服人員`tools/list`透過閘道呼叫 (MCP 目標） 時，A/B 測試會將每個工作階段指派給閘道上的變體 （控制或處理），並解析對應的組態套件。

1. Gateway 會讀取組態套件，並傳回套用覆寫的工具描述。

1. 代理程式使用傳回的描述進行工具選擇 - 不需要變更代理程式程式碼。

### 建立 A/B 測試
<a name="_create_the_ab_test"></a>

```
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 name="config-bundle-troubleshooting"></a>

如需對 A/B 測試問題進行故障診斷 （例如傳送流量後遺失結果），請參閱 目標型路由指南中的[故障診斷](ab-testing-target-based.md#target-based-troubleshooting)。