

# Execute um A/B teste com pacotes de configuração
<a name="ab-testing-config-bundle"></a>

Use o padrão do pacote de configuração quando a alteração que você estiver testando for puramente de configuração — um prompt de sistema diferente, um ID de modelo diferente ou descrições de ferramentas diferentes. Ambas as variantes são executadas no mesmo AgentCore Runtime com diferentes versões do pacote de configuração. O AgentCore Gateway injeta a referência correta do pacote em cada solicitação por meio dos cabeçalhos de bagagem do W3C, e seu agente a lê em tempo de execução. Isso significa que você implanta um AgentCore Runtime e uma configuração de avaliação on-line.

Configuração chave para A/B testes do pacote de configuração:
+ Configuração da variante: `variantConfiguration.configurationBundle` com ARN e versão do pacote
+ Configuração de avaliação: um único compartilhamento `onlineEvaluationConfigArn` 

Se a alteração que você está testando envolver alterações de código, uma atualização da estrutura ou uma implementação de agente totalmente diferente, use o roteamento baseado em destinos. Consulte [Executar um A/B teste com roteamento baseado em metas](ab-testing-target-based.md).

Este passo a passo usa um agente de suporte ao cliente como exemplo. O agente lida com pesquisas de pedidos, devoluções e solicitações de descontos. Você implantará o agente, criará dois pacotes de configuração com solicitações de sistema diferentes (controle e tratamento), criará um A/B teste, enviará tráfego, analisará os resultados e implantará o vencedor.

## Etapa 1: criar o projeto
<a name="config-bundle-create-project"></a>

Crie o projeto com a AgentCore CLI:

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

## Etapa 2: adicionar o tempo de execução
<a name="config-bundle-add-runtime"></a>

Adicione o tempo de execução do agente:

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

Estrutura do projeto:

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

## Etapa 3: atualizar o código do agente e implantar
<a name="config-bundle-agent-code"></a>

`app/csAgent/main.py`Substitua pelo seguinte. A principal adição é o `BeforeModelCallEvent` gancho que lê o pacote de configuração ativo em tempo de execução:

```
"""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()
```

Atualizar `app/csAgent/pyproject.toml` dependências:

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

Implante o agente de suporte ao cliente no AgentCore Runtime:

```
agentcore deploy
```

Após a implantação, observe o ARN do tempo de execução na saída (por exemplo,`arn:aws:bedrock-agentcore:us-west-2:123456789012:runtime/csAgent-abc123`). Você precisará dele para criar pacotes de configuração.

Verifique se o agente está em execução:

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

O `BeforeModelCallEvent` gancho é acionado antes de cada chamada do LLM, lendo o pacote de configuração ativo a partir do contexto da solicitação. Durante um A/B teste, o AgentCore Gateway atribui cada sessão a uma variante e propaga a referência do pacote correspondente por meio dos cabeçalhos de bagagem do W3C. O tempo de execução disponibiliza isso por meio de`BedrockAgentCoreContext`, portanto, as sessões de controle recebem o pacote v1 e as sessões de tratamento recebem o pacote v2 — o agente aplica qualquer prompt do sistema que está no pacote que recebe.

Para obter mais detalhes, consulte [Usar pacotes de configuração em tempo de execução](configuration-bundles-runtime.md).

## Etapa 4: criar pacotes de configuração
<a name="config-bundle-create-bundles"></a>

Crie dois pacotes de configuração — um para controle (alerta atual) e outro para tratamento (aviso otimizado). O A/B teste dividirá o tráfego entre eles para medir qual prompt gera melhores pontuações para o avaliador.

Pacote de controle — o prompt atual do sistema:

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

Pacote de tratamento — um prompt otimizado do sistema que instrui o agente a ser mais proativo:

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

Depois de cada implantação, anote o ARN do pacote e o ID da versão na saída — você precisará deles ao criar A/B o teste.

## Etapa 5: criar uma configuração de avaliação on-line
<a name="config-bundle-online-eval"></a>

Um A/B teste requer uma configuração de avaliação on-line para pontuar sessões de ambas as variantes. A avaliação on-line compara os avaliadores em relação ao tráfego ao vivo e envia as pontuações ao mecanismo estatístico do A/B teste.

Para variantes do pacote de configuração, crie uma única configuração de avaliação on-line que monitore o Runtime compartilhado AgentCore :

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

agentcore deploy
```

Após a implantação, anote o ARN da configuração de avaliação on-line na saída — você precisará dele ao criar A/B o teste.

**dica**  
`--sampling-rate 100.0`Defina durante o A/B teste para que cada sessão seja avaliada e os resultados atinjam significância estatística mais rapidamente. Você pode diminuir a taxa após a conclusão do teste.

Para obter mais detalhes sobre as opções e a configuração do avaliador, consulte [Criar avaliação on-line](create-online-evaluations.md).

## Etapa 6: criar o gateway e o destino
<a name="config-bundle-create-gateway"></a>

Um A/B teste de pacote de configuração roteia o tráfego por meio de um AgentCore gateway, portanto, o gateway e seu destino já devem estar implantados antes de você iniciar o teste. Adicione um gateway com o tempo de execução como `http-runtime` destino e implante:

```
agentcore add gateway --name csGateway

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

agentcore deploy
```

## Etapa 7: criar o A/B teste
<a name="config-bundle-create-test"></a>

Crie um A/B teste que divida o tráfego 80/20 entre as instruções de controle e tratamento. Ambas as variantes fazem referência a pacotes de configuração no mesmo AgentCore Runtime e compartilham uma única configuração de avaliação on-line para pontuação.

**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`inicia um trabalho A/B de teste no serviço. O teste é EXECUTADO assim que o comando retorna. Passe `--disable-on-create` para criá-lo parado. Para revisar o trabalho`agentcore view ab-test <id>`, executar ou pesquisar o trabalho em JSON abaixo`.cli/jobs/ab-tests/`. O `--gateway` sinalizador é obrigatório e deve fazer referência ao gateway que você implantou na Etapa 6. Somente um teste pode ser executado por gateway por vez. O comando imprime o ID do trabalho do teste, que também está disponível no `id` campo. `--json` Você precisa desse ID para os comandos de ciclo de vida abaixo.  
Os `--treatment-version` valores `--control-version` e são os IDs de versão retornados quando você implantou os pacotes de configuração na Etapa 3.

```
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']}")
```

## Etapa 8: Enviar tráfego pelo AgentCore Gateway
<a name="config-bundle-send-traffic"></a>

Depois que o A/B teste estiver em execução, envie tráfego pelo endpoint HTTP do AgentCore Gateway. O AgentCore Gateway atribui cada solicitação a uma variante (controle ou tratamento) com base no ID da sessão de tempo de execução.

### Como funciona a atribuição de variantes
<a name="_how_variant_assignment_works"></a>

O AgentCore Gateway usa o `X-Amzn-Bedrock-AgentCore-Runtime-Session-Id` cabeçalho para determinar qual variante do pacote de configuração deve ser veiculada. Esse cabeçalho é **opcional** — se você não o fornecer, o tempo de execução gerará uma ID de sessão automaticamente. Em seguida, o AgentCore Gateway usa a ID da sessão (seja ela fornecida por você ou gerada pelo tempo de execução) para atribuir a solicitação a uma variante com base nos pesos de tráfego configurados.

A atribuição da sessão é **fixa**: quando uma ID de sessão é atribuída a uma variante, todas as solicitações subsequentes com a mesma ID de sessão são encaminhadas para a mesma variante. Isso garante uma experiência consistente em uma sessão e, ao mesmo tempo, distribui novas sessões entre variantes de acordo com sua divisão de tráfego.

### Gere tráfego para testes
<a name="_generate_traffic_for_testing"></a>

Salve o script a seguir como`loadgen.sh`, substituindo `<gateway-id>` e `<target-name>` com os valores de sua saída de implantação:

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

Execute o script :

```
bash loadgen.sh
```

## Etapa 9: obter resultados
<a name="config-bundle-get-results"></a>

Faça uma pesquisa com o A/B teste para monitorar os resultados à medida que o tamanho das amostras aumenta. A pesquisa não afeta a validade estatística.

**Example**  
Obtenha os resultados atuais (`<ab-test-id>`substitua pelo ID do trabalho da Etapa 6):  

```
agentcore view ab-test <ab-test-id>
```
Obtenha resultados como JSON:  

```
agentcore view ab-test <ab-test-id> --json
```
Faça uma pesquisa até que os resultados atinjam significância estatística:  

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

**nota**  
O tempo necessário para que os resultados apareçam depende principalmente do tempo limite da sessão configurado em sua configuração de avaliação on-line. Uma sessão é considerada concluída quando nenhuma nova solicitação chega dentro da janela de tempo limite. Após o término de uma sessão, os resultados geralmente aparecem em 15 minutos. Os resultados se acumulam à medida que mais sessões são concluídas — a significância estatística melhora com o tamanho da amostra.
+  **valor de p < 0,05 e positivo`percentChange`:** O tratamento é significativamente melhor do que o controle. Considere implantar o tratamento.
+  **valor de p < 0,05 e negativo`percentChange`:** O tratamento é significativamente pior. Mantenha o controle.
+  **valor p >= 0,05:** Não há evidências suficientes para concluir uma diferença. Continue coletando amostras ou aumente o tráfego para o tratamento.
+  **Verifique todos os avaliadores:** um tratamento pode melhorar uma métrica enquanto regride outra. Analise todos os resultados do avaliador antes de decidir.

Para obter uma explicação detalhada da estrutura de resultados e das definições de campo, consulte [Entendendo os resultados](ab-testing-target-based.md#target-based-results-shape) no guia de roteamento baseado em metas.

## Etapa 10: Confirme os resultados e interrompa o A/B teste
<a name="config-bundle-confirm-stop"></a>

Quando o A/B teste atingir significância estatística, revise os resultados e interrompa o experimento.

1.  **Confirme a importância.** Verifique se o avaliador-alvo tem `isSignificant: true` um resultado positivo `percentChange` na variante do tratamento (ou confirme se o controle é o vencedor se o tratamento regrediu).

1.  **Pare o A/B teste.** Executar `agentcore stop ab-test -i <ab-test-id>`. O roteamento de tráfego termina imediatamente e todas as solicitações são revertidas para a configuração padrão. Consulte [Exibir, pausar, retomar e parar](ab-testing-manage.md#manage-ab-test-start-stop).

## Etapa 11: implantar o vencedor
<a name="config-bundle-deploy-winner"></a>

Depois de interromper o A/B teste, direcione todo o tráfego para a versão vencedora do pacote de configuração.

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

 `promote`interrompe o A/B teste (se ainda estiver em execução) e atualiza o pacote de configuração de controle para usar a versão de tratamento. Execute `agentcore deploy` para aplicar as alterações.

Como alternativa, você pode implantar manualmente o vencedor fazendo o seguinte:
+  **Opção A:** Use [as regras de roteamento do AgentCore Gateway](gateway-rules.md) para rotear todo o tráfego com a versão vencedora do pacote de configuração.
+  **Opção B:** atualize o pacote de configuração de controle para usar o prompt vencedor do sistema e reimplantá-lo.
+  **Opção C:** defina a versão vencedora do pacote como padrão no código do seu agente e remova a configuração A/B de teste.

Depois de posicionar o vencedor:
+  **Exclua o A/B teste** para limpar os recursos. Consulte [Excluir um A/B teste](ab-testing-manage.md#manage-ab-test-remove).
+  **Monitore a nova linha de base.** A avaliação on-line continua pontuando as sessões na configuração vencedora. Fique atento às regressões.
+  **Inicie a próxima iteração.** Novos traços da configuração vencedora fornecem a base para o próximo ciclo de recomendação. Veja [como funciona](optimization-how-it-works.md).

## Exemplo: descrições A/B de ferramentas de teste
<a name="config-bundle-tool-description-example"></a>

Você pode usar o mesmo padrão de pacote de configuração para testar as descrições otimizadas das ferramentas. Diferentemente dos A/B testes de alerta do sistema, nos quais o agente lê o pacote diretamente, as substituições da descrição da ferramenta são aplicadas pelo Gateway. AgentCore Quando o agente liga `tools/list` pelo gateway, o gateway lê o pacote de configuração e retorna as descrições da ferramenta com as substituições aplicadas. Nenhuma alteração no código do agente é necessária.

Para obter detalhes sobre como o gateway aplica as substituições da descrição da ferramenta, consulte [Comportamento em alvos MCP](gateway-rules-propagation.md#gateway-rules-propagation-mcp).

### Pacotes de configuração
<a name="_configuration_bundles"></a>

Pacote de controle — descrições atuais da ferramenta:

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

Pacote de tratamento — descrições otimizadas da ferramenta a partir de uma recomendação:

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

### Como funciona
<a name="_how_it_works"></a>

1. Quando o agente liga `tools/list` pelo gateway (destinos MCP), o A/B teste atribui cada sessão a uma variante (controle ou tratamento) no gateway e resolve o pacote de configuração correspondente.

1. O Gateway lê o pacote de configuração e retorna as descrições das ferramentas com as substituições aplicadas.

1. O agente usa as descrições retornadas para a seleção da ferramenta — nenhuma alteração no código do agente é necessária.

### Crie o A/B teste
<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
```

As etapas restantes (enviar tráfego, obter resultados, implantar o vencedor) são idênticas ao exemplo anterior de prompt do sistema.

## Solução de problemas
<a name="config-bundle-troubleshooting"></a>

Para solucionar problemas de A/B teste (como resultados ausentes após o envio do tráfego), consulte [Solução de problemas](ab-testing-target-based.md#target-based-troubleshooting) no guia de roteamento baseado em metas.