<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alvaro</title>
    <description>The latest articles on DEV Community by Alvaro (@alvarog2491).</description>
    <link>https://dev.to/alvarog2491</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4145368%2Fe1b2e322-4464-4272-950f-57af503372a9.png</url>
      <title>DEV Community: Alvaro</title>
      <link>https://dev.to/alvarog2491</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alvarog2491"/>
    <language>en</language>
    <item>
      <title>Releasing and evaluating AI agents on Amazon Bedrock AgentCore with A/B tests and explainability evaluators</title>
      <dc:creator>Alvaro</dc:creator>
      <pubDate>Fri, 09 Oct 2026 05:43:02 +0000</pubDate>
      <link>https://dev.to/alvarog2491/releasing-and-evaluating-ai-agents-on-amazon-bedrock-agentcore-with-ab-tests-and-explainability-2hp9</link>
      <guid>https://dev.to/alvarog2491/releasing-and-evaluating-ai-agents-on-amazon-bedrock-agentcore-with-ab-tests-and-explainability-2hp9</guid>
      <description>&lt;p&gt;A new version of an AI agent, with a new system prompt, model, or architecture, should reach every user only after it has shown, on real traffic, that it is better than the current version. I created the &lt;a href="https://github.com/alvarog2491/agentcore-ab-release-gate" rel="noopener noreferrer"&gt;AgentCore A/B Release Gate&lt;/a&gt; GitHub Action to automate that decision. It runs an A/B test that compares the new version with the current one on live traffic, and an evaluator score decides whether the new version is promoted or rolled back.&lt;/p&gt;

&lt;p&gt;Amazon Bedrock AgentCore provides the building blocks. AgentCore Runtime hosts multiple versions of an agent behind named endpoints, and AgentCore Gateway splits traffic between them with an A/B test. During the test, AgentCore Evaluations scores the sessions of both versions online, with the evaluators you choose for your use case: built-in, custom LLM-as-a-judge or code-based.&lt;/p&gt;

&lt;p&gt;In this post, we use the &lt;a href="https://github.com/alvarog2491/agentcore-ab-release-gate" rel="noopener noreferrer"&gt;AgentCore A/B Release Gate&lt;/a&gt; GitHub Action to release two versions of a customer-support agent. The action deploys each new container image next to the current version, splits live traffic between them, and promotes the new version only when it passes the defined quality gates. The gate is a deterministic, code-based evaluator that encodes the store's support workflow as rules. The first release is a latency optimization that breaks the workflow rules and is rolled back. The second release fixes a weakness of the agent and is promoted.&lt;/p&gt;

&lt;p&gt;The showcase is a general-purpose scenario that shows how the action works from start to finish. The customer-support agent, its system prompts and its evaluator are examples, and the same release flow applies to other agents, changes and evaluation rules.&lt;/p&gt;

&lt;p&gt;All logs and numbers in this post come from real runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution overview
&lt;/h2&gt;

&lt;p&gt;For this post, we use a customer-support assistant for a fictitious online electronics store. Customers ask the assistant which orders they have, where a parcel is, and whether they can return an item. The store has a simple return policy: an item can be returned within 30 days of delivery, final-sale items such as gift cards cannot be returned, and orders that haven't been delivered can't be returned yet.&lt;/p&gt;

&lt;p&gt;The store also has a support workflow that every answer must follow: look the facts up with the tools, never invent an order, tracking or return number, never ask the customer for information the agent can look up itself, and check that an item is eligible before opening a return for it. A code-based evaluator scores every turn of the agent against these rules, and the release gate promotes a new version only when it follows them significantly better than the current one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent
&lt;/h2&gt;

&lt;p&gt;The agent serves the store's customers. It asks for missing information, looks up the customer's data, answers with the facts it found, and opens a return when the customer asks for one and the store's policy allows it. It keeps the conversation of each session, so follow-up messages build on the earlier turns. The following session with the released agent shows a typical conversation (the tracking table is shown as lines, and the last answer is shortened):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer: Hey, I ordered a Keychron K2 mechanical keyboard last week and the tracking hasn't updated in 3 days. Can you tell me where it is?
Agent:    I'm happy to help! Could you please share the email address used for the order,
          or if you have the order ID handy, that would work too.

Customer: ana@example.com
Agent:    Here are the tracking details for your keyboard (order ORD‑1002):
          Carrier: DHL
          Tracking number: JD014600003456789012
          Estimated delivery: 2026‑09‑29
          2026‑09‑25: Shipped from Madrid warehouse
          2026‑09‑26: Arrived at Lyon sorting facility

Customer: I don't need it anymore. Can I return it?
Agent:    I'm sorry, but you can only open a return after the item has been delivered. Since
          the keyboard (SKU KB‑310) is still in transit and expected to arrive on 29 September,
          the return window hasn't opened yet. ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent uses LangGraph's &lt;code&gt;create_react_agent&lt;/code&gt; with the &lt;code&gt;openai.gpt-oss-20b-1:0&lt;/code&gt; model on Amazon Bedrock and runs on AgentCore Runtime inside &lt;code&gt;BedrockAgentCoreApp&lt;/code&gt;. It receives &lt;code&gt;{"prompt": "..."}&lt;/code&gt; and answers with &lt;code&gt;{"result": "..."}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The agent has five tools. They read and write a small, fixed dataset in memory (two customers, four orders, their shipments and returns) with a fixed "today" of 2026-09-27, so every run sees the same facts, and every answer can be checked against them:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;What it returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;find_customer_orders&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Customer email&lt;/td&gt;
&lt;td&gt;The customer's order IDs, dates and statuses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;get_order_details&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order ID&lt;/td&gt;
&lt;td&gt;Items, SKUs, prices, total, status and delivery date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;track_shipment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order ID&lt;/td&gt;
&lt;td&gt;Carrier, tracking number, delivery estimate and tracking events&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;check_return_eligibility&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order ID and SKU&lt;/td&gt;
&lt;td&gt;Whether the item can be returned under the store policy, and until when&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;create_return&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Order ID, SKU and reason&lt;/td&gt;
&lt;td&gt;A new RMA number and the refund steps, only for an eligible item&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The tools chain together. A typical conversation goes from &lt;code&gt;find_customer_orders&lt;/code&gt; to &lt;code&gt;get_order_details&lt;/code&gt;, and then to &lt;code&gt;track_shipment&lt;/code&gt; for a delivery question, or to &lt;code&gt;check_return_eligibility&lt;/code&gt; and &lt;code&gt;create_return&lt;/code&gt; for a return. The return policy lives in the tools: &lt;code&gt;check_return_eligibility&lt;/code&gt; and &lt;code&gt;create_return&lt;/code&gt; refuse final-sale items, undelivered orders and items outside the 30-day window.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;opentelemetry-instrumentation-langchain&lt;/code&gt; library records every model call and tool call as OpenTelemetry spans (tool calls as &lt;code&gt;execute_tool&lt;/code&gt; spans), and AgentCore sends them to Amazon CloudWatch. All the evaluators in this post read these spans.&lt;/p&gt;

&lt;p&gt;The following code shows the entrypoint in &lt;code&gt;src/agent/main.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@app.entrypoint&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invoking Agent.....&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the agent using create_react_agent (checkpointer is shared across invocations)
&lt;/span&gt;    &lt;span class="n"&gt;graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_react_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;get_or_create_model&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TOOLS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DEFAULT_SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;checkpointer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_checkpointer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Process the user prompt
&lt;/span&gt;    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What can you help me with?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt must be a string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;session_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;session_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;default-session&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;touch_thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent input: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Run the agent (checkpointer auto-loads/saves history per session)
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ainvoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;HumanMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)]},&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configurable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thread_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Return result
&lt;/span&gt;    &lt;span class="c1"&gt;# .text drops gpt-oss reasoning blocks and keeps only the answer text
&lt;/span&gt;    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;messages&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent output: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Three versions of the agent
&lt;/h3&gt;

&lt;p&gt;In this post, the agent goes through three versions that differ only in &lt;code&gt;DEFAULT_SYSTEM_PROMPT&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Version 1 is the version that serves users when the post starts. Its prompt tells the agent to use its tools and to ask the customer for anything that is missing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DEFAULT_SYSTEM_PROMPT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
You are a customer-support assistant for an online electronics store.
Always use the available tools to answer — never guess order, shipping or
return information from your own knowledge.
- To find a customer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s orders from their email, use find_customer_orders.
- To see items, SKUs, prices and dates of an order, use get_order_details.
- For &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;where is my order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; questions, use track_shipment.
- Before promising a return, use check_return_eligibility; only call
  create_return when the customer asks for it and the item is eligible.
If you are missing an email, order ID or item, ask the customer for it.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Version 1 looks reasonable, and it answers order and shipping questions correctly. It has one weakness that shows up in return requests: &lt;code&gt;check_return_eligibility&lt;/code&gt; and &lt;code&gt;create_return&lt;/code&gt; need the item's SKU, and the last line tells the agent to ask for a missing item. In some return requests, the agent asks the customer for the SKU ("Could you tell me the SKU of the headphones in ORD-1001?") instead of reading it from the order. Customers don't know SKUs.&lt;/p&gt;

&lt;p&gt;Version 2 is a latency optimization on top of version 1. Each tool call is one more model round trip, and &lt;code&gt;create_return&lt;/code&gt; already refuses ineligible items, so the separate eligibility check looks redundant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; You are a customer-support assistant for an online electronics store.
&lt;span class="gd"&gt;-Always use the available tools to answer — never guess order, shipping or
-return information from your own knowledge.
&lt;/span&gt;&lt;span class="gi"&gt;+Customers hate waiting: keep replies short and use as few tool calls as
+possible.
&lt;/span&gt; - To find a customer's orders from their email, use find_customer_orders.
 - To see items, SKUs, prices and dates of an order, use get_order_details.
 - For "where is my order" questions, use track_shipment.
&lt;span class="gd"&gt;-- Before promising a return, use check_return_eligibility; only call
-  create_return when the customer asks for it and the item is eligible.
&lt;/span&gt;&lt;span class="gi"&gt;+- When the customer asks for a return, call create_return directly: it
+  checks eligibility itself, so check_return_eligibility is an extra step.
&lt;/span&gt; If you are missing an email, order ID or item, ask the customer for it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The change saves a model round trip per return. It also opens returns without telling the customer the conditions first (the deadline, the refund amount, whether the item qualifies at all), which the store's workflow requires, and the shorter prompt makes the agent ask for SKUs even more often.&lt;/p&gt;

&lt;p&gt;Version 3, the one in the repository, fixes the weakness of version 1. It tells the agent where SKUs come from and stops it from asking for them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt; - For "where is my order" questions, use track_shipment.
&lt;span class="gi"&gt;+- Returns need the item's SKU: read it with get_order_details, never ask the
+  customer for it.
&lt;/span&gt; - Before promising a return, use check_return_eligibility; only call
   create_return when the customer asks for it and the item is eligible.
&lt;span class="gd"&gt;-If you are missing an email, order ID or item, ask the customer for it.
&lt;/span&gt;&lt;span class="gi"&gt;+If you are missing an email or order ID, ask the customer for it.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before releasing anything, we ran each version locally against the same model, with the 12 questions of the traffic script, four times each (48 single-turn sessions per version), and scored every answer with the release gate's rules (described in the next sections). The following table shows the results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Scored turns that follow the workflow&lt;/th&gt;
&lt;th&gt;Main failure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;42 of 48 (0.88)&lt;/td&gt;
&lt;td&gt;Asks the customer for a SKU (6 turns)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;29 of 47 (0.62)&lt;/td&gt;
&lt;td&gt;Asks for a SKU (11 turns) or calls &lt;code&gt;create_return&lt;/code&gt; without &lt;code&gt;check_return_eligibility&lt;/code&gt; (7 turns)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;48 of 48 (1.00)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The differences in the table are large enough to measure in a 15-minute A/B test with enough traffic, which is what the release gate needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution components
&lt;/h2&gt;

&lt;p&gt;The solution uses the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AgentCore Runtime&lt;/strong&gt; runs the agent container. Each image update creates a new runtime version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime endpoints&lt;/strong&gt; are names that point to one version. The &lt;code&gt;control&lt;/code&gt; endpoint serves users. The action creates a &lt;code&gt;treatment&lt;/code&gt; endpoint for the candidate version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AgentCore Gateway&lt;/strong&gt; is the single entry point. It has one HTTP target per endpoint, and the A/B test splits traffic between the targets, per session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AgentCore Evaluations&lt;/strong&gt; reads the agent's OpenTelemetry spans from Amazon CloudWatch. Online evaluation scores every session with a code-based evaluator (an AWS Lambda function) for the release gate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; builds the image, runs the release gate and generates traffic. It deploys through an IAM role assumed with OpenID Connect (OIDC), so there are no AWS keys in the repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How the release gate works
&lt;/h2&gt;

&lt;p&gt;The action expects an AgentCore Runtime with a &lt;code&gt;control&lt;/code&gt; endpoint and a dedicated HTTP gateway in front of it. For every release, the action performs the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Prepare.&lt;/strong&gt; It deploys the new image as a new runtime version, points a &lt;code&gt;treatment&lt;/code&gt; endpoint to it, adds a &lt;code&gt;treatment&lt;/code&gt; target to the gateway, and copies the online evaluation configuration once per variant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observe.&lt;/strong&gt; It starts an A/B test on the gateway, so every new session goes either to control or to treatment, and waits while online evaluation scores the sessions of both variants.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide.&lt;/strong&gt; For every evaluator in the quality gates, it checks that the treatment mean reaches the threshold, that it is not lower than the control mean, and that the difference is statistically significant (p &amp;lt; 0.05 by default).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promote or roll back.&lt;/strong&gt; If all gates pass, both endpoints move to the new version. If any gate fails, the job times out, the job is cancelled or AWS returns an error, both endpoints stay on (or return to) the previous version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With &lt;code&gt;require-significance: false&lt;/code&gt;, the action promotes a candidate that scores equal to or better than the current version and reaches the threshold. With &lt;code&gt;require-significance: true&lt;/code&gt;, the default and the setting in this post, the improvement must also be statistically significant, so a candidate that only matches the current version is rolled back. That is why version 3, the one we want to promote, has to improve on version 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  The release gate evaluator
&lt;/h2&gt;

&lt;p&gt;AgentCore Evaluations offers three kinds of evaluators:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evaluator type&lt;/th&gt;
&lt;th&gt;How it scores&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Pre-defined LLM-as-a-judge prompts such as &lt;code&gt;Builtin.Helpfulness&lt;/code&gt; or &lt;code&gt;Builtin.Correctness&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;General response quality with no setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom LLM-as-a-judge&lt;/td&gt;
&lt;td&gt;Your own instructions and rating scale, scored by a model you choose&lt;/td&gt;
&lt;td&gt;Domain-specific checks that need judgment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code-based&lt;/td&gt;
&lt;td&gt;An AWS Lambda function that returns a score, label and explanation&lt;/td&gt;
&lt;td&gt;Deterministic checks that code can decide&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Evaluators work at three levels: a whole session, a single turn (trace) or an individual tool call.&lt;/p&gt;

&lt;p&gt;The release gate needs a score it can compare across variants. We use a code-based evaluator for it. It always gives the same score for the same trace, it costs a few milliseconds of Lambda time per call, and it returns a number, which the A/B statistics need. Its rules come from the store's support workflow, not from the change being released, so the same evaluator gates every future release.&lt;/p&gt;

&lt;p&gt;The evaluator works at the TRACE level: it scores each turn of a session with the session's earlier turns as context. A turn scores 1.0 (PASS) when it breaks none of the following rules, and 0.0 (FAIL) when it breaks at least one:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;A turn fails when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Look it up&lt;/td&gt;
&lt;td&gt;The answer states order facts (an order, tracking or return number, or a date) and no tool was called in the session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No invented identifiers&lt;/td&gt;
&lt;td&gt;The answer contains an order ID, tracking number or RMA number that appears in no customer message and no tool result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Don't make the customer do the lookup&lt;/td&gt;
&lt;td&gt;The answer asks the customer for a SKU, and the agent didn't read the order with &lt;code&gt;get_order_details&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check before acting&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;create_return&lt;/code&gt; is called for an item without an earlier &lt;code&gt;check_return_eligibility&lt;/code&gt; for the same order and SKU&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All four rules read only the spans that the agent already emits. The &lt;code&gt;opentelemetry-instrumentation-langchain&lt;/code&gt; library records each tool call as an &lt;code&gt;execute_tool&lt;/code&gt; span with the tool name, its arguments (&lt;code&gt;gen_ai.tool.call.arguments&lt;/code&gt;) and its result (&lt;code&gt;gen_ai.tool.call.result&lt;/code&gt;). The &lt;code&gt;LangGraph.workflow&lt;/code&gt; span of each turn holds the customer's message and the agent's messages, including the final answer.&lt;/p&gt;

&lt;p&gt;The following function in &lt;code&gt;src/evaluators/support_workflow.py&lt;/code&gt; applies the rules to one turn. It uses only the Python standard library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_turn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;turn_tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return the workflow rules this turn breaks (empty when it passes).

    customer_messages: the customer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s messages in the session up to this turn.
    tool_calls: the session&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s tool calls up to and including this turn, in
        order, as {&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inputs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;}.
    answer: the agent&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s final answer for this turn.
    turn_tool_calls: how many of tool_calls belong to this turn.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;violations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mentioned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_identifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;from_customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;customer_messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;from_customer&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="nf"&gt;_identifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Repeating the customer's own order ID (for example, when asking for an
&lt;/span&gt;    &lt;span class="c1"&gt;# email) is not a fact the agent looked up.
&lt;/span&gt;    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mentioned&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;from_customer&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;_DATE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The answer states order facts but no tool was called to look them up.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;known&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;from_customer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;known&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="nf"&gt;_identifiers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;result&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;invented&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mentioned&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;known&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;invented&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The answer contains identifiers no customer message or tool result supports: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invented&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;_ASKS_FOR_SKU&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_order_details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The agent asked the customer for a SKU instead of reading the order with get_order_details.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;checked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inputs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;_normalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;))).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sku&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;check_return_eligibility&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create_return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;checked&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;turn_tool_calls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;create_return was called for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; without check_return_eligibility first.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;violations&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rest of the file turns the spans into turns and calls &lt;code&gt;check_turn&lt;/code&gt; for the turn under evaluation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;spans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evaluationInput&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sessionSpans&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;trace_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;evaluationTarget&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traceIds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;turns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_turns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;spans&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# TRACE level scores one turn; without a target (SESSION level) score the last one.
&lt;/span&gt;    &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;turns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;trace_ids&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trace_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;trace_ids&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errorCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NO_SPANS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errorMessage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No agent turn found for trace(s) &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;trace_ids&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;in session&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;turn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;turns&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;violations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;check_turn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;customer_messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;tool_calls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
        &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;turn_tool_calls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAIL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;explanation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;violations&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

    &lt;span class="n"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;label&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PASS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;explanation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The turn follows the support workflow (tool calls: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;).&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AgentCore calls the function with the spans of the session in &lt;code&gt;evaluationInput.sessionSpans&lt;/code&gt; and the trace to score in &lt;code&gt;evaluationTarget.traceIds&lt;/code&gt;. The function returns &lt;code&gt;label&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt;, plus an optional &lt;code&gt;explanation&lt;/code&gt;, or &lt;code&gt;errorCode&lt;/code&gt; and &lt;code&gt;errorMessage&lt;/code&gt; when there is nothing to score. A failed turn's explanation names the rule it broke, for example &lt;code&gt;create_return was called for ORD-1001 HD-200 without check_return_eligibility first.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The following Terraform registers the evaluator and the online evaluation configuration that the action uses as a template (from &lt;code&gt;infra/evaluations.tf&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_bedrockagentcore_evaluator"&lt;/span&gt; &lt;span class="s2"&gt;"support_workflow"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;evaluator_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;support_workflow_evaluator_name&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Deterministic: 1.0 if the turn follows the support workflow (lookups, grounded IDs, eligibility before returns), else 0.0."&lt;/span&gt;
  &lt;span class="nx"&gt;level&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"TRACE"&lt;/span&gt;

  &lt;span class="nx"&gt;evaluator_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;code_based&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;lambda_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;lambda_arn&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_lambda_function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;support_workflow_evaluator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
        &lt;span class="nx"&gt;lambda_timeout_in_seconds&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda_permission&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agentcore_evaluations&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# --- Online evaluation config ---&lt;/span&gt;

&lt;span class="c1"&gt;# Runtime log groups are created by AgentCore on the first invocation.&lt;/span&gt;
&lt;span class="c1"&gt;# Pre-create the control one so the evaluation config can point at it&lt;/span&gt;
&lt;span class="c1"&gt;# from day one and so it gets a retention period.&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_cloudwatch_log_group"&lt;/span&gt; &lt;span class="s2"&gt;"control_runtime"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/aws/bedrock-agentcore/runtimes/${aws_bedrockagentcore_agent_runtime.agent.agent_runtime_id}-${var.control_endpoint_name}"&lt;/span&gt;
  &lt;span class="nx"&gt;retention_in_days&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Online evaluation of the control endpoint: scores every session of the agent&lt;/span&gt;
&lt;span class="c1"&gt;# with the support-workflow evaluator.&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_bedrockagentcore_online_evaluation_config"&lt;/span&gt; &lt;span class="s2"&gt;"control"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;online_evaluation_config_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.agent_name}_${var.control_endpoint_name}_eval"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Evaluation of the control endpoint; template for A/B releases"&lt;/span&gt;
  &lt;span class="nx"&gt;enable_on_create&lt;/span&gt;              &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;evaluation_execution_role_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;

  &lt;span class="nx"&gt;data_source_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cloudwatch_logs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;log_group_names&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_cloudwatch_log_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="nx"&gt;service_names&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"${var.agent_name}.${var.control_endpoint_name}"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;evaluator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;evaluator_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_bedrockagentcore_evaluator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;support_workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluator_id&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sampling_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sampling_percentage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluation_sampling_percentage&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;session_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;session_timeout_minutes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluation_session_timeout_minutes&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;precondition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;condition&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;strcontains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control_endpoint_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="nx"&gt;error_message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"agent_name must not contain control_endpoint_name."&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_role_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;evaluation&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our values, the log group is &lt;code&gt;/aws/bedrock-agentcore/runtimes/&amp;lt;runtime-id&amp;gt;-control&lt;/code&gt; and the service name is &lt;code&gt;showcase_agent.control&lt;/code&gt;. The configuration scores 100% of the sessions and treats a session as complete after 2 idle minutes.&lt;/p&gt;

&lt;p&gt;For every release, the action makes one copy of this configuration per variant by replacing &lt;code&gt;control&lt;/code&gt; with &lt;code&gt;treatment&lt;/code&gt; in the log group and the service name.&lt;/p&gt;

&lt;p&gt;AgentCore creates the runtime's log group on the first invocation, so Terraform creates it up front. That way, the configuration can point to it from the beginning.&lt;/p&gt;

&lt;p&gt;The template contains only the gate evaluator. Every evaluator in the configuration scores every session of both variants during a release, so an LLM-as-a-judge evaluator there adds judge-model cost to each session. AgentCore also locks an evaluator that an enabled online configuration references, so changing the evaluator's definition requires disabling the configuration first. Changes to the Lambda code apply directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The environment
&lt;/h2&gt;

&lt;p&gt;The showcase runs in &lt;code&gt;eu-central-1&lt;/code&gt;, in an AWS account with AgentCore Runtime, Gateway, Evaluations and A/B testing. The agent uses &lt;code&gt;openai.gpt-oss-20b-1:0&lt;/code&gt; on Amazon Bedrock. CloudWatch Transaction Search is enabled, because AgentCore Evaluations reads the agent's spans from it. GitHub Actions deploys through the account's GitHub OIDC identity provider, and the image builds on an &lt;code&gt;ubuntu-24.04-arm&lt;/code&gt; runner. The infrastructure is defined with Terraform v1.14 and the AWS provider v6.63.&lt;/p&gt;

&lt;p&gt;The action works with an ARM64 image in Amazon Elastic Container Registry (Amazon ECR), a runtime with a &lt;code&gt;control&lt;/code&gt; endpoint, a dedicated HTTP gateway, an enabled online evaluation configuration, an A/B test role and a deploy role. The Terraform in the repository creates all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The infrastructure
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;infra/&lt;/code&gt; folder contains one file per concern:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Resources&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ecr.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The image repository&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;runtime.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The runtime and the &lt;code&gt;control&lt;/code&gt; endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gateway.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The HTTP gateway and its &lt;code&gt;control&lt;/code&gt; target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;evaluations.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The evaluator Lambda function, the evaluator and the online evaluation configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;iam.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Roles for the runtime, the gateway and the evaluations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;release.tf&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The A/B test role and the GitHub deploy role&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few details make Terraform and the action work together.&lt;/p&gt;

&lt;p&gt;The action deploys releases by changing the runtime's image and the &lt;code&gt;control&lt;/code&gt; endpoint's version, so Terraform creates both resources and ignores those two attributes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_bedrockagentcore_agent_runtime"&lt;/span&gt; &lt;span class="s2"&gt;"agent"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;agent_runtime_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent_name&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Showcase agent released through the AgentCore A/B release gate"&lt;/span&gt;
  &lt;span class="nx"&gt;role_arn&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;

  &lt;span class="nx"&gt;agent_runtime_artifact&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;container_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;container_uri&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${aws_ecr_repository.agent.repository_url}:${var.initial_image_tag}"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;network_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;network_mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PUBLIC"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;protocol_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;server_protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HTTP"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;# The release gate action deploys new images with UpdateAgentRuntime.&lt;/span&gt;
  &lt;span class="c1"&gt;# Terraform only creates the Runtime and must not roll those releases back.&lt;/span&gt;
  &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ignore_changes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;agent_runtime_artifact&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_role_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Stable endpoint the action treats as the control arm. The action also&lt;/span&gt;
&lt;span class="c1"&gt;# creates a "treatment" endpoint itself on its first run.&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_bedrockagentcore_agent_runtime_endpoint"&lt;/span&gt; &lt;span class="s2"&gt;"control"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control_endpoint_name&lt;/span&gt;
  &lt;span class="nx"&gt;agent_runtime_id&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_bedrockagentcore_agent_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent_runtime_id&lt;/span&gt;
  &lt;span class="nx"&gt;agent_runtime_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_bedrockagentcore_agent_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent_runtime_version&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Control endpoint serving the approved agent version"&lt;/span&gt;

  &lt;span class="c1"&gt;# The action repoints this endpoint on promotion and rollback.&lt;/span&gt;
  &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ignore_changes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;agent_runtime_version&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The gateway leaves &lt;code&gt;protocol_type&lt;/code&gt; unset, which creates an HTTP gateway, the type that accepts runtime HTTP targets. The target's &lt;code&gt;qualifier&lt;/code&gt; is the endpoint name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# No protocol_type: an HTTP Gateway that routes traffic straight to&lt;/span&gt;
&lt;span class="c1"&gt;# AgentCore Runtime targets, which is what the A/B test splits.&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_bedrockagentcore_gateway"&lt;/span&gt; &lt;span class="s2"&gt;"agent"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.project_name}-gateway"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Dedicated HTTP gateway fronting the agent for A/B releases"&lt;/span&gt;
  &lt;span class="nx"&gt;role_arn&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;authorizer_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"AWS_IAM"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Control target. The action looks it up by name (control-endpoint-name)&lt;/span&gt;
&lt;span class="c1"&gt;# and adds its own treatment target next to it during a release.&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_bedrockagentcore_gateway_target"&lt;/span&gt; &lt;span class="s2"&gt;"control"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control_endpoint_name&lt;/span&gt;
  &lt;span class="nx"&gt;gateway_identifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_bedrockagentcore_gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gateway_id&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Routes to the agent's control endpoint"&lt;/span&gt;

  &lt;span class="nx"&gt;credential_provider_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;gateway_iam_role&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;target_configuration&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;agentcore_runtime&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;arn&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_bedrockagentcore_agent_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;agent_runtime_arn&lt;/span&gt;
        &lt;span class="nx"&gt;qualifier&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_bedrockagentcore_agent_runtime_endpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AgentCore assumes the A/B test role to manage the gateway rules and to read the evaluation data. Its policy follows the AWS documentation on A/B testing prerequisites.&lt;/p&gt;

&lt;p&gt;GitHub Actions assumes the deploy role. It has the permissions listed in the action's README, plus ECR push for the build and &lt;code&gt;bedrock-agentcore:InvokeGateway&lt;/code&gt; for the traffic job. Its &lt;code&gt;max_session_duration&lt;/code&gt; is 4 hours, because the action uses the credentials for the whole test.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the showcase is deployed
&lt;/h2&gt;

&lt;p&gt;For this showcase, the infrastructure is deployed by hand with Terraform, and only agent releases run in GitHub Actions. The runtime needs an image when it is created, so Terraform creates the ECR repository first, a first image is pushed to it with the tag &lt;code&gt;bootstrap&lt;/code&gt;, and Terraform then creates the rest of the infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform &lt;span class="nt"&gt;-chdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;infra init
terraform &lt;span class="nt"&gt;-chdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;infra apply &lt;span class="nt"&gt;-target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;aws_ecr_repository.agent

&lt;span class="nv"&gt;REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;terraform &lt;span class="nt"&gt;-chdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;infra output &lt;span class="nt"&gt;-raw&lt;/span&gt; ecr_repository_url&lt;span class="si"&gt;)&lt;/span&gt;
aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; eu-central-1 &lt;span class="se"&gt;\&lt;/span&gt;
  | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO&lt;/span&gt;&lt;span class="p"&gt;%%/*&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# First image with the tag "bootstrap". ARM64, built from the repository root.&lt;/span&gt;
docker buildx build &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/arm64 &lt;span class="nt"&gt;--provenance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-f&lt;/span&gt; src/agent/Dockerfile &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO&lt;/span&gt;&lt;span class="s2"&gt;:bootstrap"&lt;/span&gt; &lt;span class="nt"&gt;--push&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

terraform &lt;span class="nt"&gt;-chdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;infra apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Outputs:
ab_test_role_arn              = "arn:aws:iam::123456789012:role/agentcore-release-showcase-ab-test"
aws_region                    = "eu-central-1"
control_endpoint_name         = "control"
ecr_repository_url            = "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase"
evaluation_config_id          = "showcase_agent_control_eval-TIuENTGKTP"
gateway_id                    = "agentcore-release-showcase-gateway-tbxw0u5whz"
github_deploy_role_arn        = "arn:aws:iam::123456789012:role/agentcore-release-showcase-github-deploy"
order_grounding_evaluator_id  = "showcase_agent_order_grounding-EiF5HKA6EO"
runtime_id                    = "showcase_agent-5d8CQj7PYA"
support_workflow_evaluator_id = "showcase_agent_support_workflow-6D9E4mCaGA"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;scripts/traffic.sh&lt;/code&gt; plays the customers. It sends customer questions to the gateway, one new session per request, signed with SigV4. Each request is the following &lt;code&gt;curl&lt;/code&gt; call, where &lt;code&gt;$url&lt;/code&gt; is &lt;code&gt;https://&amp;lt;gateway-id&amp;gt;.gateway.bedrock-agentcore.&amp;lt;region&amp;gt;.amazonaws.com/control/invocations&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/traffic-response.json &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s1"&gt;'%{http_code}'&lt;/span&gt; &lt;span class="nt"&gt;--max-time&lt;/span&gt; 120 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--aws-sigv4&lt;/span&gt; &lt;span class="s2"&gt;"aws:amz:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:bedrock-agentcore"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_SESSION_TOKEN&lt;/span&gt;:+-H&lt;span class="p"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"x-amz-security-token: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;AWS_SESSION_TOKEN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;session_id&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script takes the gateway ID, the Region, the duration, the pause between requests and the number of parallel customers. The following output shows 40 seconds of traffic against version 1 with two customers (the script prints only the beginning of each answer):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ scripts/traffic.sh agentcore-release-showcase-gateway-tbxw0u5whz eu-central-1 40 5 2
[w1 1] Can I return the headphones from order ORD-1001? -&amp;gt; Sure! The HD‑200 Wireless Headphones in order **ORD‑1001** are still return‑eligible. You can return them anytime up to **10 Oct 2026** for a full ref
[w0 1] Hi, I'm ana@example.com. Where is my keyboard? -&amp;gt; Your mechanical keyboard (order ORD‑1002) is on its way!   - **Tracking number:** JD014600003456789012 (DHL)   - **Estimated delivery:** 29 September 20
[w1 2] I'm ben@example.com, I want to return my monitor. -&amp;gt; I’m sorry, but the 30‑day return window for the 27‑inch Monitor (SKU: MN‑270) closed on **2026‑09‑02**.    Because that date has passed, you’re
[w0 2] Please open a return for the USB-C cable in ORD-1001, it doesn't charge my phone. -&amp;gt; Great news! Your return has been processed.  * **Return ID**: **RMA‑5001**   * **Item**: USB‑C Cable (SKU CB‑010)   * **Reason**:
...
Worker 1 sent 4 requests, 0 failed.
Worker 0 sent 5 requests, 0 failed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Version 1 reads the data: the DHL tracking number, the return window of the monitor and the RMA number all come from the tools.&lt;br&gt;
The online evaluation configuration scores every session of the &lt;code&gt;control&lt;/code&gt; endpoint, so version 1 has a baseline score before the first release. The control columns of the two releases below show its scores.&lt;/p&gt;
&lt;h2&gt;
  
  
  The release workflow
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;.github/workflows/release.yml&lt;/code&gt; runs on every push to &lt;code&gt;main&lt;/code&gt; that changes the agent. It has three jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;publish&lt;/code&gt; builds the ARM64 image on an ARM runner and pushes it to Amazon ECR with the commit SHA as the tag (about 1 minute).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;deploy&lt;/code&gt; runs the release gate (about 20 minutes).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;traffic&lt;/code&gt; runs in parallel with &lt;code&gt;deploy&lt;/code&gt; and plays the customers (about 25 minutes). The action only observes traffic; in production, real users generate it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following step calls the action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alvarog2491/agentcore-ab-release-gate@c3b197619c73e45d395bb3eb9a535ddc464ed254&lt;/span&gt; &lt;span class="c1"&gt;# v1.1.2&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;
    &lt;span class="na"&gt;image-uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.image.outputs.uri }}&lt;/span&gt;
    &lt;span class="na"&gt;runtime-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_RUNTIME_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;gateway-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_GATEWAY_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AWS_REGION }}&lt;/span&gt;
    &lt;span class="na"&gt;evaluation-config-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_EVALUATION_CONFIG_ID }}&lt;/span&gt;
    &lt;span class="na"&gt;ab-test-role-arn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_AB_TEST_ROLE_ARN }}&lt;/span&gt;
    &lt;span class="c1"&gt;# Showcase-sized test: 15 min observation, even split so the treatment&lt;/span&gt;
    &lt;span class="c1"&gt;# collects enough sessions quickly. Production default is 7200 / 80-20.&lt;/span&gt;
    &lt;span class="na"&gt;duration-seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.OBSERVATION_SECONDS }}&lt;/span&gt;
    &lt;span class="na"&gt;control-weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;50'&lt;/span&gt;
    &lt;span class="na"&gt;treatment-weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;50'&lt;/span&gt;
    &lt;span class="c1"&gt;# Scores arrive in batches minutes after a session ends; wait for the&lt;/span&gt;
    &lt;span class="c1"&gt;# sample count to stay stable for 5 min so most sessions are counted.&lt;/span&gt;
    &lt;span class="na"&gt;scoring-lag-seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;300'&lt;/span&gt;
    &lt;span class="c1"&gt;# Minimum treatment score per evaluator ID (`terraform output support_workflow_evaluator_id`).&lt;/span&gt;
    &lt;span class="c1"&gt;# support_workflow scores each turn 1 if it follows the store's support&lt;/span&gt;
    &lt;span class="c1"&gt;# workflow (looks facts up, invents no IDs, never asks for a SKU, checks&lt;/span&gt;
    &lt;span class="c1"&gt;# eligibility before create_return), else 0: &amp;gt;= 90% of treatment turns.&lt;/span&gt;
    &lt;span class="na"&gt;quality-gates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
      &lt;span class="s"&gt;{"showcase_agent_support_workflow-6D9E4mCaGA": 0.9}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;step: auto&lt;/code&gt; observes and promotes in the same job. We changed the following inputs from their defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;duration-seconds&lt;/code&gt; is 900 (default 7200), a 15-minute observation sized for this showcase.&lt;/li&gt;
&lt;li&gt;The split is 50/50 (default 80/20), so the treatment collects enough sessions quickly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scoring-lag-seconds&lt;/code&gt; is 300 (default 120). Online evaluation scores sessions in batches a few minutes after they end, so the action waits until the number of scored sessions has been stable for 5 minutes before it decides.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;quality-gates&lt;/code&gt; requires a score of at least 0.9, which means that at least 90% of the treatment turns follow every workflow rule.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The remaining inputs keep their defaults. &lt;code&gt;require-significance&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, so the p-value must be below 0.05, and &lt;code&gt;evaluation-timeout-seconds&lt;/code&gt; is 1800.&lt;/p&gt;

&lt;p&gt;The keys of &lt;code&gt;quality-gates&lt;/code&gt; are full evaluator IDs, including the random suffix that AWS adds to custom evaluators. The workflow holds the ID from &lt;code&gt;terraform output support_workflow_evaluator_id&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The traffic job runs four parallel customers that send the same 12 questions in a loop, one new session per question, so each variant collects enough sessions for a significant result in 15 minutes. Seven of the questions are return requests or return questions, because most of the workflow rules apply to returns. In production, the traffic comes from real users.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  The full release.yml
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Release agent&lt;/span&gt;

&lt;span class="c1"&gt;# Builds the agent image, publishes it to ECR, then releases it through the&lt;/span&gt;
&lt;span class="c1"&gt;# AgentCore A/B Release Gate: the new image runs as a treatment next to the&lt;/span&gt;
&lt;span class="c1"&gt;# current control version and is promoted only if every quality gate passes.&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;src/agent/**&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pyproject.toml&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;uv.lock&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.github/workflows/release.yml&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
  &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt; &lt;span class="c1"&gt;# OIDC to assume the AWS deploy role&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;AWS_REGION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AWS_REGION }}&lt;/span&gt;
  &lt;span class="na"&gt;ECR_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentcore-release-showcase&lt;/span&gt; &lt;span class="c1"&gt;# infra/ecr.tf (var.project_name)&lt;/span&gt;
  &lt;span class="na"&gt;OBSERVATION_SECONDS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;900&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish image to ECR&lt;/span&gt;
    &lt;span class="c1"&gt;# AgentCore Runtime needs linux/arm64; build natively instead of emulating.&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-24.04-arm&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
    &lt;span class="na"&gt;outputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;digest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.build.outputs.digest }}&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1&lt;/span&gt; &lt;span class="c1"&gt;# v7.0.1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd&lt;/span&gt; &lt;span class="c1"&gt;# v6.3.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AWS_DEPLOY_ROLE_ARN }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AWS_REGION }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ecr&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecr-login@03f1aad4c6c7ffd436567f42f9384779290529bd&lt;/span&gt; &lt;span class="c1"&gt;# v2.1.7&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069&lt;/span&gt; &lt;span class="c1"&gt;# v4.4.1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc&lt;/span&gt; &lt;span class="c1"&gt;# v7.4.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# Repo root is the context: the image needs the uv workspace lockfile.&lt;/span&gt;
          &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/agent/Dockerfile&lt;/span&gt;
          &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/arm64&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;provenance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="c1"&gt;# push a single ARM64 manifest, not an index with attestations&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}&lt;/span&gt;
          &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=gha&lt;/span&gt;
          &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=gha,mode=max&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;A/B release gate&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;180&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
    &lt;span class="c1"&gt;# One release at a time per Gateway; never cancel a running A/B test.&lt;/span&gt;
    &lt;span class="na"&gt;concurrency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentcore-production&lt;/span&gt;
      &lt;span class="na"&gt;cancel-in-progress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd&lt;/span&gt; &lt;span class="c1"&gt;# v6.3.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AWS_DEPLOY_ROLE_ARN }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AWS_REGION }}&lt;/span&gt;
          &lt;span class="c1"&gt;# Must outlast observation + evaluation; the role's MaxSessionDuration must allow it.&lt;/span&gt;
          &lt;span class="na"&gt;role-duration-seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;14400&lt;/span&gt;

      &lt;span class="c1"&gt;# Only the digest crosses jobs: GitHub drops job outputs containing masked&lt;/span&gt;
      &lt;span class="c1"&gt;# values, which the registry URI (AWS account ID) can be.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;account_id=$(aws sts get-caller-identity --query Account --output text)&lt;/span&gt;
          &lt;span class="s"&gt;echo "uri=${account_id}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY}@${{ needs.publish.outputs.digest }}" &amp;gt;&amp;gt; "$GITHUB_OUTPUT"&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alvarog2491/agentcore-ab-release-gate@c3b197619c73e45d395bb3eb9a535ddc464ed254&lt;/span&gt; &lt;span class="c1"&gt;# v1.1.2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auto&lt;/span&gt;
          &lt;span class="na"&gt;image-uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.image.outputs.uri }}&lt;/span&gt;
          &lt;span class="na"&gt;runtime-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_RUNTIME_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;gateway-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_GATEWAY_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AWS_REGION }}&lt;/span&gt;
          &lt;span class="na"&gt;evaluation-config-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_EVALUATION_CONFIG_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;ab-test-role-arn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AGENTCORE_AB_TEST_ROLE_ARN }}&lt;/span&gt;
          &lt;span class="c1"&gt;# Showcase-sized test: 15 min observation, even split so the treatment&lt;/span&gt;
          &lt;span class="c1"&gt;# collects enough sessions quickly. Production default is 7200 / 80-20.&lt;/span&gt;
          &lt;span class="na"&gt;duration-seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.OBSERVATION_SECONDS }}&lt;/span&gt;
          &lt;span class="na"&gt;control-weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;50'&lt;/span&gt;
          &lt;span class="na"&gt;treatment-weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;50'&lt;/span&gt;
          &lt;span class="c1"&gt;# Scores arrive in batches minutes after a session ends; wait for the&lt;/span&gt;
          &lt;span class="c1"&gt;# sample count to stay stable for 5 min so most sessions are counted.&lt;/span&gt;
          &lt;span class="na"&gt;scoring-lag-seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;300'&lt;/span&gt;
          &lt;span class="c1"&gt;# Minimum treatment score per evaluator ID (`terraform output support_workflow_evaluator_id`).&lt;/span&gt;
          &lt;span class="c1"&gt;# support_workflow scores each turn 1 if it follows the store's support&lt;/span&gt;
          &lt;span class="c1"&gt;# workflow (looks facts up, invents no IDs, never asks for a SKU, checks&lt;/span&gt;
          &lt;span class="c1"&gt;# eligibility before create_return), else 0: &amp;gt;= 90% of treatment turns.&lt;/span&gt;
          &lt;span class="na"&gt;quality-gates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
            &lt;span class="s"&gt;{"showcase_agent_support_workflow-6D9E4mCaGA": 0.9}&lt;/span&gt;

  &lt;span class="c1"&gt;# The release gate observes real traffic but does not create it. This job&lt;/span&gt;
  &lt;span class="c1"&gt;# plays customers: it sends questions through the Gateway's control target&lt;/span&gt;
  &lt;span class="c1"&gt;# while the deploy job prepares the candidate and runs the A/B test.&lt;/span&gt;
  &lt;span class="na"&gt;traffic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate traffic&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;publish&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;timeout-minutes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;45&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1&lt;/span&gt; &lt;span class="c1"&gt;# v7.0.1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd&lt;/span&gt; &lt;span class="c1"&gt;# v6.3.0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;role-to-assume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ vars.AWS_DEPLOY_ROLE_ARN }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.AWS_REGION }}&lt;/span&gt;
          &lt;span class="na"&gt;role-duration-seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3600&lt;/span&gt;

      &lt;span class="c1"&gt;# Observation window plus ~10 min for the gate to deploy the candidate&lt;/span&gt;
      &lt;span class="c1"&gt;# and create the treatment endpoint before the A/B test starts. Four&lt;/span&gt;
      &lt;span class="c1"&gt;# parallel customers give each variant enough sessions for significance.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;scripts/traffic.sh "${{ vars.AGENTCORE_GATEWAY_ID }}" "$AWS_REGION" $((OBSERVATION_SECONDS + 600)) 5 &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent and runtime versions
&lt;/h2&gt;

&lt;p&gt;AgentCore numbers each deployed image as a runtime version, and the logs in the next sections use those numbers. In this account they run one ahead of the agent versions, because the runtime was created with an earlier &lt;code&gt;bootstrap&lt;/code&gt; image:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent version&lt;/th&gt;
&lt;th&gt;Prompt&lt;/th&gt;
&lt;th&gt;Runtime version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;bootstrap&lt;/code&gt; image, unused in this post&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Latency edit&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;SKU fix&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Release version 2: rolled back
&lt;/h2&gt;

&lt;p&gt;With agent version 2 in &lt;code&gt;DEFAULT_SYSTEM_PROMPT&lt;/code&gt;, a push to &lt;code&gt;main&lt;/code&gt; starts the release. The control serves agent version 1.&lt;/p&gt;

&lt;p&gt;The following table shows how the run progressed (times in UTC):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;08:30:29&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;publish&lt;/code&gt; starts. Build and push take 81 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:32:03&lt;/td&gt;
&lt;td&gt;The action resolves the image digest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:32:05&lt;/td&gt;
&lt;td&gt;The &lt;code&gt;treatment&lt;/code&gt; endpoint and gateway target from an earlier release are reused&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:32:06&lt;/td&gt;
&lt;td&gt;Agent version 2 deployed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:32:27&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;treatment&lt;/code&gt; serves agent version 2, &lt;code&gt;control&lt;/code&gt; stays on agent version 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:32:50&lt;/td&gt;
&lt;td&gt;One evaluation configuration per variant is ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:33:02&lt;/td&gt;
&lt;td&gt;The A/B test is running, 50/50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:48:02&lt;/td&gt;
&lt;td&gt;End of the 900 seconds of observation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;08:49:02&lt;/td&gt;
&lt;td&gt;First results: 27 treatment and 18 control sessions scored&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:18:02&lt;/td&gt;
&lt;td&gt;Final results: 208 treatment and 172 control sessions; the gate fails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:18:55&lt;/td&gt;
&lt;td&gt;Candidate rolled back: both endpoints serve agent version 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The following are the main lines of the action's log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;08:32:03 {"event": "candidate-image-resolved", "image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase@sha256:4ecb76f76daf15dbb36de65687420bb14743a35bc83d43009995932da32cea0e", "observationSeconds": 900}
08:32:05 {"event": "deployment-prepared", "baseline": "2", "runtime": "showcase_agent-5d8CQj7PYA", "gateway": "agentcore-release-showcase-gateway-tbxw0u5whz"}
08:32:06 {"event": "candidate-runtime-created", "version": "3"}
08:32:27 {"event": "treatment-endpoint-serving", "endpoint": "treatment", "version": "3"}
08:32:28 {"event": "evaluation-config-created", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_aa7922b6-STy4x45q5z"}
08:32:39 {"event": "evaluation-config-created", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_13afb08c-3AwTuh8Kay"}
08:32:51 {"event": "ab-test-created", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553"}
08:33:02 {"event": "ab-test-running", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553"}
08:48:02 {"event": "evaluation-results-waiting", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553"}
08:49:02 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 60, "remainingSeconds": 1739, "totalSamplesScored": 27, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
…  (a 'stabilizing-results' line every 30 s while scores arrive)
09:18:02 {"event": "ab-test-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "results": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "isSignificant": true, "absoluteChange": -0.2753801431127012, "percentChange": -29.789550072568936, "pValue": 6.291833366249719e-09, "treatmentSampleSize": 208, "controlSampleSize": 172}}}
09:18:55 Rolled back: control retains version 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;
  The full log of the action (120 events)
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;08:32:03 {"event": "candidate-image-resolved", "image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase@sha256:4ecb76f76daf15dbb36de65687420bb14743a35bc83d43009995932da32cea0e", "observationSeconds": 900}
08:32:03 {"event": "deployment-preparing", "controlEndpoint": "control"}
08:32:04 {"event": "treatment-endpoint-existing", "endpoint": "treatment"}
08:32:05 {"event": "treatment-endpoint-ready", "endpoint": "treatment"}
08:32:05 {"event": "gateway-target-existing", "target": "control"}
08:32:05 {"event": "gateway-target-ready", "target": "control", "targetId": "1FXXBFSC0Y"}
08:32:05 {"event": "gateway-target-existing", "target": "treatment"}
08:32:05 {"event": "gateway-target-ready", "target": "treatment", "targetId": "RULIRM0A1H"}
08:32:05 {"event": "deployment-prepared", "baseline": "2", "runtime": "showcase_agent-5d8CQj7PYA", "gateway": "agentcore-release-showcase-gateway-tbxw0u5whz"}
08:32:05 {"event": "candidate-runtime-creating", "image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase@sha256:4ecb76f76daf15dbb36de65687420bb14743a35bc83d43009995932da32cea0e"}
08:32:06 {"event": "candidate-runtime-created", "version": "3"}
08:32:16 {"event": "candidate-runtime-ready", "version": "3"}
08:32:16 {"event": "treatment-endpoint-updating", "endpoint": "treatment", "version": "3"}
08:32:27 {"event": "treatment-endpoint-serving", "endpoint": "treatment", "version": "3"}
08:32:27 {"event": "evaluation-config-template-loading", "evaluationConfigId": "showcase_agent_control_eval-TIuENTGKTP"}
08:32:27 {"event": "evaluation-config-creating", "variant": "control"}
08:32:28 {"event": "evaluation-config-created", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_aa7922b6-STy4x45q5z"}
08:32:28 {"event": "evaluation-config-waiting", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_aa7922b6-STy4x45q5z", "status": "CREATING"}
08:32:38 {"event": "evaluation-config-ready", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_aa7922b6-STy4x45q5z"}
08:32:38 {"event": "evaluation-config-creating", "variant": "treatment"}
08:32:39 {"event": "evaluation-config-created", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_13afb08c-3AwTuh8Kay"}
08:32:39 {"event": "evaluation-config-waiting", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_13afb08c-3AwTuh8Kay", "status": "CREATING"}
08:32:50 {"event": "evaluation-config-ready", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_13afb08c-3AwTuh8Kay"}
08:32:50 {"event": "ab-test-creating", "controlWeight": 50, "treatmentWeight": 50, "gatewayArn": "arn:aws:bedrock-agentcore:eu-central-1:123456789012:gateway/agentcore-release-showcase-gateway-tbxw0u5whz"}
08:32:51 {"event": "ab-test-created", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553"}
08:33:02 {"event": "ab-test-running", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553"}
08:33:02 {"event": "listening-for-connections", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "observationSeconds": 900, "message": "A/B test is running; waiting for Gateway connections and evaluator results."}
08:33:32 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 30, "remainingSeconds": 870, "abTestStatus": "RUNNING"}
08:34:02 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 60, "remainingSeconds": 840, "abTestStatus": "RUNNING"}
08:34:32 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 90, "remainingSeconds": 810, "abTestStatus": "RUNNING"}
08:35:02 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 120, "remainingSeconds": 780, "abTestStatus": "RUNNING"}
08:35:32 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 150, "remainingSeconds": 750, "abTestStatus": "RUNNING"}
08:36:03 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 180, "remainingSeconds": 720, "abTestStatus": "RUNNING"}
08:36:33 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 210, "remainingSeconds": 690, "abTestStatus": "RUNNING"}
08:37:03 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 241, "remainingSeconds": 659, "abTestStatus": "RUNNING"}
08:37:33 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 271, "remainingSeconds": 629, "abTestStatus": "RUNNING"}
08:38:03 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 301, "remainingSeconds": 599, "abTestStatus": "RUNNING"}
08:38:34 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 331, "remainingSeconds": 569, "abTestStatus": "RUNNING"}
08:39:04 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 362, "remainingSeconds": 538, "abTestStatus": "RUNNING"}
08:39:34 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 392, "remainingSeconds": 508, "abTestStatus": "RUNNING"}
08:40:04 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 422, "remainingSeconds": 478, "abTestStatus": "RUNNING"}
08:40:34 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 452, "remainingSeconds": 448, "abTestStatus": "RUNNING"}
08:41:05 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 482, "remainingSeconds": 418, "abTestStatus": "RUNNING"}
08:41:35 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 513, "remainingSeconds": 387, "abTestStatus": "RUNNING"}
08:42:05 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 543, "remainingSeconds": 357, "abTestStatus": "RUNNING"}
08:42:35 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 573, "remainingSeconds": 327, "abTestStatus": "RUNNING"}
08:43:05 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 603, "remainingSeconds": 297, "abTestStatus": "RUNNING"}
08:43:36 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 633, "remainingSeconds": 267, "abTestStatus": "RUNNING"}
08:44:06 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 663, "remainingSeconds": 237, "abTestStatus": "RUNNING"}
08:44:36 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 694, "remainingSeconds": 206, "abTestStatus": "RUNNING"}
08:45:06 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 724, "remainingSeconds": 176, "abTestStatus": "RUNNING"}
08:45:36 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 754, "remainingSeconds": 146, "abTestStatus": "RUNNING"}
08:46:06 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 784, "remainingSeconds": 116, "abTestStatus": "RUNNING"}
08:46:37 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 814, "remainingSeconds": 86, "abTestStatus": "RUNNING"}
08:47:07 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 845, "remainingSeconds": 55, "abTestStatus": "RUNNING"}
08:47:37 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 875, "remainingSeconds": 25, "abTestStatus": "RUNNING"}
08:48:02 {"event": "observing", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 900, "remainingSeconds": 0, "abTestStatus": "RUNNING"}
08:48:02 {"event": "evaluation-results-waiting", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553"}
08:48:02 {"event": "waiting-for-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 0, "remainingSeconds": 1799, "totalSamplesScored": 0, "evaluatorsReady": [], "evaluatorsWaiting": ["showcase_agent_support_workflow-6D9E4mCaGA"], "partialResults": {}}
08:48:32 {"event": "waiting-for-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 30, "remainingSeconds": 1769, "totalSamplesScored": 0, "evaluatorsReady": [], "evaluatorsWaiting": ["showcase_agent_support_workflow-6D9E4mCaGA"], "partialResults": {}}
08:49:02 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 60, "remainingSeconds": 1739, "totalSamplesScored": 27, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:49:32 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 90, "remainingSeconds": 1709, "totalSamplesScored": 27, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:50:03 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 120, "remainingSeconds": 1679, "totalSamplesScored": 27, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:50:33 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 150, "remainingSeconds": 1649, "totalSamplesScored": 27, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:51:03 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 181, "remainingSeconds": 1618, "totalSamplesScored": 27, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:51:33 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 211, "remainingSeconds": 1588, "totalSamplesScored": 27, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:52:03 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 241, "remainingSeconds": 1558, "totalSamplesScored": 27, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:52:33 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 271, "remainingSeconds": 1528, "totalSamplesScored": 27, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:53:04 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 301, "remainingSeconds": 1498, "totalSamplesScored": 27, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:53:34 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 331, "remainingSeconds": 1468, "totalSamplesScored": 27, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.7037037037037037, "treatmentSamples": 27, "controlSamples": 18, "pValue": 0.34901600461362947}}}
08:54:04 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 362, "remainingSeconds": 1437, "totalSamplesScored": 61, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:54:34 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 392, "remainingSeconds": 1407, "totalSamplesScored": 61, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:55:04 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 422, "remainingSeconds": 1377, "totalSamplesScored": 61, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:55:34 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 452, "remainingSeconds": 1347, "totalSamplesScored": 61, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:56:05 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 482, "remainingSeconds": 1317, "totalSamplesScored": 61, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:56:35 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 512, "remainingSeconds": 1287, "totalSamplesScored": 61, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:57:05 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 543, "remainingSeconds": 1256, "totalSamplesScored": 61, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:57:35 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 573, "remainingSeconds": 1226, "totalSamplesScored": 61, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:58:05 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 603, "remainingSeconds": 1196, "totalSamplesScored": 61, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:58:35 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 633, "remainingSeconds": 1166, "totalSamplesScored": 61, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.5737704918032787, "treatmentSamples": 61, "controlSamples": 44, "pValue": 0.0001149945455902997}}}
08:59:06 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 663, "remainingSeconds": 1136, "totalSamplesScored": 99, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
08:59:36 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 694, "remainingSeconds": 1105, "totalSamplesScored": 99, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:00:06 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 724, "remainingSeconds": 1075, "totalSamplesScored": 99, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:00:36 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 754, "remainingSeconds": 1045, "totalSamplesScored": 99, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:01:06 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 784, "remainingSeconds": 1015, "totalSamplesScored": 99, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:01:36 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 814, "remainingSeconds": 985, "totalSamplesScored": 99, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:02:07 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 844, "remainingSeconds": 955, "totalSamplesScored": 99, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:02:37 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 875, "remainingSeconds": 924, "totalSamplesScored": 99, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:03:07 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 905, "remainingSeconds": 894, "totalSamplesScored": 99, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:03:37 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 935, "remainingSeconds": 864, "totalSamplesScored": 99, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6464646464646465, "treatmentSamples": 99, "controlSamples": 67, "pValue": 0.00017551537736039635}}}
09:04:07 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 965, "remainingSeconds": 834, "totalSamplesScored": 146, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:04:37 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 995, "remainingSeconds": 804, "totalSamplesScored": 146, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:05:08 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1025, "remainingSeconds": 774, "totalSamplesScored": 146, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:05:38 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1056, "remainingSeconds": 743, "totalSamplesScored": 146, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:06:08 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1086, "remainingSeconds": 713, "totalSamplesScored": 146, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:06:38 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1116, "remainingSeconds": 683, "totalSamplesScored": 146, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:07:08 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1146, "remainingSeconds": 653, "totalSamplesScored": 146, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:07:39 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1176, "remainingSeconds": 623, "totalSamplesScored": 146, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:08:09 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1207, "remainingSeconds": 592, "totalSamplesScored": 146, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:08:39 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1237, "remainingSeconds": 562, "totalSamplesScored": 146, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6506849315068494, "treatmentSamples": 146, "controlSamples": 109, "pValue": 1.9215642261708763e-07}}}
09:09:09 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1267, "remainingSeconds": 532, "totalSamplesScored": 202, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:09:39 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1297, "remainingSeconds": 502, "totalSamplesScored": 202, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:10:09 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1327, "remainingSeconds": 472, "totalSamplesScored": 202, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:10:40 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1357, "remainingSeconds": 442, "totalSamplesScored": 202, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:11:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1387, "remainingSeconds": 412, "totalSamplesScored": 202, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:11:40 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1418, "remainingSeconds": 381, "totalSamplesScored": 202, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:12:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1448, "remainingSeconds": 351, "totalSamplesScored": 202, "stableForSeconds": 180, "remainingScoringLagSeconds": 119, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:12:40 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1478, "remainingSeconds": 321, "totalSamplesScored": 202, "stableForSeconds": 210, "remainingScoringLagSeconds": 89, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:13:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1508, "remainingSeconds": 291, "totalSamplesScored": 202, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:13:40 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1538, "remainingSeconds": 261, "totalSamplesScored": 202, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6534653465346535, "treatmentSamples": 202, "controlSamples": 156, "pValue": 4.629157118792766e-08}}}
09:14:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1568, "remainingSeconds": 231, "totalSamplesScored": 208, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:14:41 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1598, "remainingSeconds": 201, "totalSamplesScored": 208, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:15:11 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1628, "remainingSeconds": 171, "totalSamplesScored": 208, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:15:41 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1659, "remainingSeconds": 140, "totalSamplesScored": 208, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:16:11 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1689, "remainingSeconds": 110, "totalSamplesScored": 208, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:16:41 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1719, "remainingSeconds": 80, "totalSamplesScored": 208, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:17:11 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1749, "remainingSeconds": 50, "totalSamplesScored": 208, "stableForSeconds": 180, "remainingScoringLagSeconds": 119, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:17:41 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "elapsedSeconds": 1779, "remainingSeconds": 20, "totalSamplesScored": 208, "stableForSeconds": 210, "remainingScoringLagSeconds": 89, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "treatmentSamples": 208, "controlSamples": 172, "pValue": 6.291833366249719e-09}}}
09:18:02 {"event": "ab-test-results", "abTestId": "agentcore_release_gate_d68bfb89-497f74b553", "results": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 0.6490384615384616, "isSignificant": true, "absoluteChange": -0.2753801431127012, "percentChange": -29.789550072568936, "pValue": 6.291833366249719e-09, "treatmentSampleSize": 208, "controlSampleSize": 172}}}
09:18:55 Rolled back: control retains version 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;During the test, each endpoint served its own version. The following output lists the endpoints as (name, live version, target version, status) and the gateway targets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;endpoints: [('treatment', '3', None, 'READY'), ('control', '2', None, 'READY'), ('DEFAULT', '3', None, 'READY')]
targets: ['control', 'treatment']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;DEFAULT&lt;/code&gt; always follows the latest deployed image, so it was already on the candidate. Users reach the agent through the gateway, which routes them to &lt;code&gt;control&lt;/code&gt; or &lt;code&gt;treatment&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The following JSON shows the A/B test created by the action, from &lt;code&gt;GetABTest&lt;/code&gt; (shortened):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"abTestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agentcore_release_gate_d68bfb89-497f74b553"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"executionStatus"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RUNNING"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"variants"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"variantConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"control"&lt;/span&gt;&lt;span class="p"&gt;}}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"variantConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"treatment"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gatewayFilter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"targetPaths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/control/*"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evaluationConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"perVariantOnlineEvaluationConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"onlineEvaluationConfigArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock-agentcore:eu-central-1:123456789012:online-evaluation-config/showcase_agent_control_eval_c_aa7922b6-STy4x45q5z"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"onlineEvaluationConfigArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock-agentcore:eu-central-1:123456789012:online-evaluation-config/showcase_agent_control_eval_t_13afb08c-3AwTuh8Kay"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clients keep calling &lt;code&gt;/control/invocations&lt;/code&gt;, and the gateway decides for each session which target answers. The traffic job sent 601 requests in 25 minutes.&lt;br&gt;
The following answers to "Please open a return for the USB-C cable in ORD-1001, it doesn't charge my phone." come from the runtime logs of each endpoint (shortened). The control checked eligibility and opened the return. The treatment opened it directly in some sessions and asked the customer for the SKU in others:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;control:   ✅ A return has been opened for the USB‑C Cable (SKU: CB‑010) in order ORD‑1001.
           * Return reference: RMA‑5001 * Reason: It doesn't charge your phone. ...
treatment: Return RMA‑5001 created for the CB‑010 USB‑C cable. A prepaid label is sent to
           your email, and the €12.50 refund will be processed once the item arrives ...
treatment: Could you let me know the SKU of the USB‑C cable in order ORD‑1001?
treatment: I'm sorry, but the "USB-C cable" isn't listed in order ORD‑1001. Could you let me
           know the exact SKU of the cable you'd like to return?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last answer is wrong as well as unhelpful: the cable is in the order, and the treatment never read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interpreting the rollback results
&lt;/h2&gt;

&lt;p&gt;Every turn is scored on its own. The following are two result records, one from each variant (shortened):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"showcase_agent.treatment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"showcase_agent_support_workflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.score.value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.score.label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FAIL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.explanation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The agent asked the customer for a SKU instead of reading the order with get_order_details. create_return was called for ORD-1001 USB-C CABLE without check_return_eligibility first."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws.bedrock_agentcore.evaluation_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws.bedrock_agentcore.experiment.treatment_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws.bedrock_agentcore.experiment.arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock-agentcore:eu-central-1:123456789012:ab-test/agentcore_release_gate_d68bfb89-497f74b553"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"showcase_agent.control"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"showcase_agent_support_workflow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.score.value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.score.label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PASS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gen_ai.evaluation.explanation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The turn follows the support workflow (tool calls: track_shipment)."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws.bedrock_agentcore.evaluation_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws.bedrock_agentcore.experiment.treatment_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws.bedrock_agentcore.experiment.arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock-agentcore:eu-central-1:123456789012:ab-test/agentcore_release_gate_d68bfb89-497f74b553"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;experiment.treatment_name&lt;/code&gt; field (&lt;code&gt;C&lt;/code&gt; or &lt;code&gt;T1&lt;/code&gt;) tells AgentCore which variant a score belongs to. The AgentCore SDK (v1.8 or later) adds it to the spans from headers that the gateway sends, so the agent code needs no changes.&lt;/p&gt;

&lt;p&gt;The following table counts the scored turns by rule, from the evaluation result log groups of both variants. It includes 19 control turns that were scored after the action's decision. A turn can break more than one rule:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Control (version 1)&lt;/th&gt;
&lt;th&gt;Treatment (version 2)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Turns that passed&lt;/td&gt;
&lt;td&gt;176&lt;/td&gt;
&lt;td&gt;135&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turns that failed&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asked the customer for a SKU&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;create_return&lt;/code&gt; without &lt;code&gt;check_return_eligibility&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invented identifier&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The following result is the one the action used for its decision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"evaluatorMetrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evaluatorArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock-agentcore:eu-central-1:123456789012:evaluator/showcase_agent_support_workflow-6D9E4mCaGA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controlStats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"variantName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sampleSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;172&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.924&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"variantResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"variantName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sampleSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;208&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.649&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"absoluteChange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-0.275&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"percentChange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-29.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.29e-09&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidenceInterval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"lower"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-0.352&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"upper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-0.199&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isSignificant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treatment scored 0.649, below the threshold of 0.9, and 0.275 lower than the control's 0.924. With a p-value of 6.3e-9, version 2 is significantly worse. Two gate conditions failed, the minimum score and the no-regression check, and the action rolled the candidate back. The numbers match the local comparison (0.88 and 0.62) closely.&lt;/p&gt;

&lt;p&gt;The action stopped the A/B test, moved &lt;code&gt;treatment&lt;/code&gt; back to agent version 1, and deleted the temporary evaluation configurations. Users stayed on version 1, except for the sessions that the A/B test routed to the treatment while it ran.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;endpoints: [('treatment', '2', None, 'READY'), ('control', '2', None, 'READY'), ('DEFAULT', '3', None, 'READY')]
ab tests: [('agentcore_release_gate_d68bfb89-497f74b553', 'ACTIVE', 'STOPPED'), ...]
eval configs left: ['showcase_agent_control_eval-TIuENTGKTP']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The release workflow fails when the gate fails, so the commit that introduced version 2 shows a failed check on GitHub. The A/B test stays in AgentCore for later inspection.&lt;/p&gt;

&lt;p&gt;The decision came at 09:18:02, exactly 30 minutes after the observation ended, which is the default &lt;code&gt;evaluation-timeout-seconds&lt;/code&gt;. Online evaluation scored new sessions in batches about every 5 minutes, so the sample count never stayed unchanged for the full 300 seconds of &lt;code&gt;scoring-lag-seconds&lt;/code&gt;. When the timeout expires and every evaluator has results, the action decides on the latest results, so the decision used all 380 scored sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Release version 3: promoted
&lt;/h2&gt;

&lt;p&gt;Agent version 3 replaces agent version 2 in the repository, so the next push undoes the latency change and adds the SKU fix in one release. The control still serves agent version 1.&lt;/p&gt;

&lt;p&gt;The following table shows how the run progressed (times in UTC):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;09:25:53&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;publish&lt;/code&gt; starts. Build and push take 39 seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:26:49&lt;/td&gt;
&lt;td&gt;The action resolves the image digest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:26:53&lt;/td&gt;
&lt;td&gt;Agent version 3 deployed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:27:14&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;treatment&lt;/code&gt; serves agent version 3, &lt;code&gt;control&lt;/code&gt; stays on agent version 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:27:16&lt;/td&gt;
&lt;td&gt;One evaluation configuration per variant is ready&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:27:28&lt;/td&gt;
&lt;td&gt;The A/B test is running, 50/50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:42:29&lt;/td&gt;
&lt;td&gt;End of the 900 seconds of observation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:43:29&lt;/td&gt;
&lt;td&gt;First results: 31 treatment and 30 control sessions scored&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;09:48:31&lt;/td&gt;
&lt;td&gt;The difference is significant for the first time (p-value 0.036, 156 sessions)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10:12:29&lt;/td&gt;
&lt;td&gt;Final results: 226 treatment and 221 control sessions; the gate passes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10:13:21&lt;/td&gt;
&lt;td&gt;Agent version 3 promoted: both endpoints serve it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The following are the main lines of the action's log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;09:26:49 {"event": "candidate-image-resolved", "image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase@sha256:a1c51c7068f1ef198f389d631e268c41d98e1e0f43e52d1b3d5996f3e13967f5", "observationSeconds": 900}
09:26:52 {"event": "deployment-prepared", "baseline": "2", "runtime": "showcase_agent-5d8CQj7PYA", "gateway": "agentcore-release-showcase-gateway-tbxw0u5whz"}
09:26:53 {"event": "candidate-runtime-created", "version": "4"}
09:27:14 {"event": "treatment-endpoint-serving", "endpoint": "treatment", "version": "4"}
09:27:15 {"event": "evaluation-config-created", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_25f9fc3d-KfWn449e4c"}
09:27:16 {"event": "evaluation-config-created", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_445b86de-OTKWod9g50"}
09:27:18 {"event": "ab-test-created", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7"}
09:27:28 {"event": "ab-test-running", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7"}
09:42:29 {"event": "evaluation-results-waiting", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7"}
09:43:29 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 60, "remainingSeconds": 1739, "totalSamplesScored": 31, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
…  (a 'stabilizing-results' line every 30 s while scores arrive)
10:12:29 {"event": "ab-test-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "results": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "isSignificant": true, "absoluteChange": 0.08597285067873306, "percentChange": 9.405940594059409, "pValue": 0.004651189571069745, "treatmentSampleSize": 226, "controlSampleSize": 221}}}
10:12:29 {"event": "quality-gates-passed", "evaluators": ["showcase_agent_support_workflow-6D9E4mCaGA"]}
10:12:29 {"event": "candidate-promotion-starting", "version": "4"}
10:13:21 {"event": "candidate-promoted", "version": "4"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;/p&gt;
  The full log of the action (120 events)
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;09:26:49 {"event": "candidate-image-resolved", "image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase@sha256:a1c51c7068f1ef198f389d631e268c41d98e1e0f43e52d1b3d5996f3e13967f5", "observationSeconds": 900}
09:26:49 {"event": "deployment-preparing", "controlEndpoint": "control"}
09:26:51 {"event": "treatment-endpoint-existing", "endpoint": "treatment"}
09:26:51 {"event": "treatment-endpoint-ready", "endpoint": "treatment"}
09:26:51 {"event": "gateway-target-existing", "target": "control"}
09:26:52 {"event": "gateway-target-ready", "target": "control", "targetId": "1FXXBFSC0Y"}
09:26:52 {"event": "gateway-target-existing", "target": "treatment"}
09:26:52 {"event": "gateway-target-ready", "target": "treatment", "targetId": "RULIRM0A1H"}
09:26:52 {"event": "deployment-prepared", "baseline": "2", "runtime": "showcase_agent-5d8CQj7PYA", "gateway": "agentcore-release-showcase-gateway-tbxw0u5whz"}
09:26:52 {"event": "candidate-runtime-creating", "image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/agentcore-release-showcase@sha256:a1c51c7068f1ef198f389d631e268c41d98e1e0f43e52d1b3d5996f3e13967f5"}
09:26:53 {"event": "candidate-runtime-created", "version": "4"}
09:27:03 {"event": "candidate-runtime-ready", "version": "4"}
09:27:03 {"event": "treatment-endpoint-updating", "endpoint": "treatment", "version": "4"}
09:27:14 {"event": "treatment-endpoint-serving", "endpoint": "treatment", "version": "4"}
09:27:14 {"event": "evaluation-config-template-loading", "evaluationConfigId": "showcase_agent_control_eval-TIuENTGKTP"}
09:27:14 {"event": "evaluation-config-creating", "variant": "control"}
09:27:15 {"event": "evaluation-config-created", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_25f9fc3d-KfWn449e4c"}
09:27:15 {"event": "evaluation-config-ready", "variant": "control", "evaluationConfigId": "showcase_agent_control_eval_c_25f9fc3d-KfWn449e4c"}
09:27:15 {"event": "evaluation-config-creating", "variant": "treatment"}
09:27:16 {"event": "evaluation-config-created", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_445b86de-OTKWod9g50"}
09:27:16 {"event": "evaluation-config-ready", "variant": "treatment", "evaluationConfigId": "showcase_agent_control_eval_t_445b86de-OTKWod9g50"}
09:27:16 {"event": "ab-test-creating", "controlWeight": 50, "treatmentWeight": 50, "gatewayArn": "arn:aws:bedrock-agentcore:eu-central-1:123456789012:gateway/agentcore-release-showcase-gateway-tbxw0u5whz"}
09:27:18 {"event": "ab-test-created", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7"}
09:27:28 {"event": "ab-test-running", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7"}
09:27:28 {"event": "listening-for-connections", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "observationSeconds": 900, "message": "A/B test is running; waiting for Gateway connections and evaluator results."}
09:27:59 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 30, "remainingSeconds": 870, "abTestStatus": "RUNNING"}
09:28:29 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 60, "remainingSeconds": 840, "abTestStatus": "RUNNING"}
09:28:59 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 90, "remainingSeconds": 810, "abTestStatus": "RUNNING"}
09:29:29 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 120, "remainingSeconds": 780, "abTestStatus": "RUNNING"}
09:29:59 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 150, "remainingSeconds": 750, "abTestStatus": "RUNNING"}
09:30:30 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 181, "remainingSeconds": 719, "abTestStatus": "RUNNING"}
09:31:00 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 211, "remainingSeconds": 689, "abTestStatus": "RUNNING"}
09:31:30 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 241, "remainingSeconds": 659, "abTestStatus": "RUNNING"}
09:32:00 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 271, "remainingSeconds": 629, "abTestStatus": "RUNNING"}
09:32:31 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 302, "remainingSeconds": 598, "abTestStatus": "RUNNING"}
09:33:01 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 332, "remainingSeconds": 568, "abTestStatus": "RUNNING"}
09:33:31 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 362, "remainingSeconds": 538, "abTestStatus": "RUNNING"}
09:34:01 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 392, "remainingSeconds": 508, "abTestStatus": "RUNNING"}
09:34:32 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 422, "remainingSeconds": 478, "abTestStatus": "RUNNING"}
09:35:02 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 453, "remainingSeconds": 447, "abTestStatus": "RUNNING"}
09:35:32 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 483, "remainingSeconds": 417, "abTestStatus": "RUNNING"}
09:36:02 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 513, "remainingSeconds": 387, "abTestStatus": "RUNNING"}
09:36:32 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 543, "remainingSeconds": 357, "abTestStatus": "RUNNING"}
09:37:03 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 574, "remainingSeconds": 326, "abTestStatus": "RUNNING"}
09:37:33 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 604, "remainingSeconds": 296, "abTestStatus": "RUNNING"}
09:38:03 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 634, "remainingSeconds": 266, "abTestStatus": "RUNNING"}
09:38:34 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 664, "remainingSeconds": 236, "abTestStatus": "RUNNING"}
09:39:04 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 695, "remainingSeconds": 205, "abTestStatus": "RUNNING"}
09:39:34 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 725, "remainingSeconds": 175, "abTestStatus": "RUNNING"}
09:40:04 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 755, "remainingSeconds": 145, "abTestStatus": "RUNNING"}
09:40:34 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 785, "remainingSeconds": 115, "abTestStatus": "RUNNING"}
09:41:05 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 815, "remainingSeconds": 85, "abTestStatus": "RUNNING"}
09:41:35 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 846, "remainingSeconds": 54, "abTestStatus": "RUNNING"}
09:42:05 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 876, "remainingSeconds": 24, "abTestStatus": "RUNNING"}
09:42:29 {"event": "observing", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 900, "remainingSeconds": 0, "abTestStatus": "RUNNING"}
09:42:29 {"event": "evaluation-results-waiting", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7"}
09:42:29 {"event": "waiting-for-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 0, "remainingSeconds": 1799, "totalSamplesScored": 0, "evaluatorsReady": [], "evaluatorsWaiting": ["showcase_agent_support_workflow-6D9E4mCaGA"], "partialResults": {}}
09:42:59 {"event": "waiting-for-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 30, "remainingSeconds": 1769, "totalSamplesScored": 0, "evaluatorsReady": [], "evaluatorsWaiting": ["showcase_agent_support_workflow-6D9E4mCaGA"], "partialResults": {}}
09:43:29 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 60, "remainingSeconds": 1739, "totalSamplesScored": 31, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:43:59 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 90, "remainingSeconds": 1709, "totalSamplesScored": 31, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:44:29 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 120, "remainingSeconds": 1679, "totalSamplesScored": 31, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:45:00 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 151, "remainingSeconds": 1648, "totalSamplesScored": 31, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:45:30 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 181, "remainingSeconds": 1618, "totalSamplesScored": 31, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:46:00 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 211, "remainingSeconds": 1588, "totalSamplesScored": 31, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:46:30 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 241, "remainingSeconds": 1558, "totalSamplesScored": 31, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:47:00 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 271, "remainingSeconds": 1528, "totalSamplesScored": 31, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:47:31 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 302, "remainingSeconds": 1497, "totalSamplesScored": 31, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:48:01 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 332, "remainingSeconds": 1467, "totalSamplesScored": 31, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": true, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 31, "controlSamples": 30, "pValue": 0.22384901956790412}}}
09:48:31 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 362, "remainingSeconds": 1437, "totalSamplesScored": 77, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:49:01 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 392, "remainingSeconds": 1407, "totalSamplesScored": 77, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:49:31 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 422, "remainingSeconds": 1377, "totalSamplesScored": 77, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:50:02 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 452, "remainingSeconds": 1347, "totalSamplesScored": 77, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:50:32 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 483, "remainingSeconds": 1316, "totalSamplesScored": 77, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:51:02 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 513, "remainingSeconds": 1286, "totalSamplesScored": 77, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:51:32 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 543, "remainingSeconds": 1256, "totalSamplesScored": 77, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:52:02 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 573, "remainingSeconds": 1226, "totalSamplesScored": 77, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:52:33 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 604, "remainingSeconds": 1195, "totalSamplesScored": 77, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:53:03 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 634, "remainingSeconds": 1165, "totalSamplesScored": 77, "stableForSeconds": 272, "remainingScoringLagSeconds": 27, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 77, "controlSamples": 79, "pValue": 0.03551590204789858}}}
09:53:33 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 664, "remainingSeconds": 1135, "totalSamplesScored": 121, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:54:03 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 694, "remainingSeconds": 1105, "totalSamplesScored": 121, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:54:34 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 725, "remainingSeconds": 1074, "totalSamplesScored": 121, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:55:04 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 755, "remainingSeconds": 1044, "totalSamplesScored": 121, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:55:34 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 785, "remainingSeconds": 1014, "totalSamplesScored": 121, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:56:04 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 815, "remainingSeconds": 984, "totalSamplesScored": 121, "stableForSeconds": 151, "remainingScoringLagSeconds": 148, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:56:35 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 846, "remainingSeconds": 953, "totalSamplesScored": 121, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:57:05 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 876, "remainingSeconds": 923, "totalSamplesScored": 121, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:57:35 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 906, "remainingSeconds": 893, "totalSamplesScored": 121, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:58:05 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 936, "remainingSeconds": 863, "totalSamplesScored": 121, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 121, "controlSamples": 127, "pValue": 0.008705965291881924}}}
09:58:35 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 966, "remainingSeconds": 833, "totalSamplesScored": 165, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
09:59:06 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 997, "remainingSeconds": 802, "totalSamplesScored": 165, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
09:59:36 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1027, "remainingSeconds": 772, "totalSamplesScored": 165, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:00:06 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1057, "remainingSeconds": 742, "totalSamplesScored": 165, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:00:36 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1087, "remainingSeconds": 712, "totalSamplesScored": 165, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:01:06 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1117, "remainingSeconds": 682, "totalSamplesScored": 165, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:01:36 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1147, "remainingSeconds": 652, "totalSamplesScored": 165, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:02:07 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1178, "remainingSeconds": 621, "totalSamplesScored": 165, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:02:37 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1208, "remainingSeconds": 591, "totalSamplesScored": 165, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:03:07 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1238, "remainingSeconds": 561, "totalSamplesScored": 165, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 165, "controlSamples": 174, "pValue": 0.006832239542905676}}}
10:03:37 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1268, "remainingSeconds": 531, "totalSamplesScored": 211, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:04:08 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1299, "remainingSeconds": 500, "totalSamplesScored": 211, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:04:38 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1329, "remainingSeconds": 470, "totalSamplesScored": 211, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:05:08 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1359, "remainingSeconds": 440, "totalSamplesScored": 211, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:05:38 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1389, "remainingSeconds": 410, "totalSamplesScored": 211, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:06:08 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1419, "remainingSeconds": 380, "totalSamplesScored": 211, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:06:39 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1449, "remainingSeconds": 350, "totalSamplesScored": 211, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:07:09 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1480, "remainingSeconds": 319, "totalSamplesScored": 211, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:07:39 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1510, "remainingSeconds": 289, "totalSamplesScored": 211, "stableForSeconds": 241, "remainingScoringLagSeconds": 58, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:08:09 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1540, "remainingSeconds": 259, "totalSamplesScored": 211, "stableForSeconds": 271, "remainingScoringLagSeconds": 28, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 211, "controlSamples": 212, "pValue": 0.006188426951929415}}}
10:08:39 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1570, "remainingSeconds": 229, "totalSamplesScored": 226, "stableForSeconds": 0, "remainingScoringLagSeconds": 300, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:09:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1601, "remainingSeconds": 198, "totalSamplesScored": 226, "stableForSeconds": 30, "remainingScoringLagSeconds": 269, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:09:40 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1631, "remainingSeconds": 168, "totalSamplesScored": 226, "stableForSeconds": 60, "remainingScoringLagSeconds": 239, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:10:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1661, "remainingSeconds": 138, "totalSamplesScored": 226, "stableForSeconds": 90, "remainingScoringLagSeconds": 209, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:10:40 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1691, "remainingSeconds": 108, "totalSamplesScored": 226, "stableForSeconds": 120, "remainingScoringLagSeconds": 179, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:11:10 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1721, "remainingSeconds": 78, "totalSamplesScored": 226, "stableForSeconds": 150, "remainingScoringLagSeconds": 149, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:11:41 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1752, "remainingSeconds": 47, "totalSamplesScored": 226, "stableForSeconds": 181, "remainingScoringLagSeconds": 118, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:12:11 {"event": "stabilizing-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "elapsedSeconds": 1782, "remainingSeconds": 17, "totalSamplesScored": 226, "stableForSeconds": 211, "remainingScoringLagSeconds": 88, "awaitingSignificance": false, "partialResults": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "treatmentSamples": 226, "controlSamples": 221, "pValue": 0.004651189571069745}}}
10:12:29 {"event": "ab-test-results", "abTestId": "agentcore_release_gate_f0112c4a-9e273ddca7", "results": {"showcase_agent_support_workflow-6D9E4mCaGA": {"mean": 1.0, "isSignificant": true, "absoluteChange": 0.08597285067873306, "percentChange": 9.405940594059409, "pValue": 0.004651189571069745, "treatmentSampleSize": 226, "controlSampleSize": 221}}}
10:12:29 {"event": "quality-gates-passed", "evaluators": ["showcase_agent_support_workflow-6D9E4mCaGA"]}
10:12:29 {"event": "candidate-promotion-starting", "version": "4"}
10:13:21 {"event": "candidate-promoted", "version": "4"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;During the test, &lt;code&gt;treatment&lt;/code&gt; served agent version 3 and &lt;code&gt;control&lt;/code&gt; agent version 1. The listing shows runtime versions; the version table maps them to agent versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;endpoints: [('treatment', '4', None, 'READY'), ('control', '2', None, 'READY'), ('DEFAULT', '4', None, 'READY')]
targets: ['control', 'treatment']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The traffic job sent 656 requests. The following answers to "I'd like to send back the mouse from ORD-1004." come from the runtime logs of each endpoint (shortened). Both variants usually read the order and explained that it hasn't been delivered yet. Only the control sometimes asked for a SKU, and in one answer invented an example SKU format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;treatment: It looks like the order ORD‑1004 is still in the processing stage, so the mouse
           (item MS‑120) isn't eligible for a return just yet. Return is only possible once
           the package has been delivered ...
control:   Sure, I can help with that. To start the return process I'll need the SKU of the
           mouse you want to send back. Could you let me know the product's SKU (it's
           usually a code like "MOUSE-1234") from that order?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The following table counts the scored turns by rule, from the evaluation result log groups. It includes 11 control turns that were scored after the decision:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Control (version 1)&lt;/th&gt;
&lt;th&gt;Treatment (version 3)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Turns that passed&lt;/td&gt;
&lt;td&gt;213&lt;/td&gt;
&lt;td&gt;226&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Turns that failed&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asked the customer for a SKU&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;create_return&lt;/code&gt; without &lt;code&gt;check_return_eligibility&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invented identifier&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The following result is the one the action used for its decision:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"evaluatorMetrics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"evaluatorArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock-agentcore:eu-central-1:123456789012:evaluator/showcase_agent_support_workflow-6D9E4mCaGA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"controlStats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"variantName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sampleSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;221&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.914&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"variantResults"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"variantName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"T1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sampleSize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;226&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"absoluteChange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.086&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"percentChange"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;9.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0047&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidenceInterval"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"lower"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.049&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"upper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.123&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"isSignificant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Treatment scored 1.0, above the threshold of 0.9, and 0.086 higher than the control's 0.914, with a p-value of 0.0047. All three conditions were met, so the action promoted version 3.&lt;/p&gt;

&lt;p&gt;The difference here is a third of the one in the rollback, and that's what the extra traffic was for. After the first batch of results (61 sessions), the p-value was 0.22. It dropped below 0.05 only after the second batch, with 156 sessions. An earlier release in the same account, with a single customer sending a question every 10 seconds, decided on 15 scored sessions. At that sample size, the action would have rolled back version 3 for lack of evidence.&lt;/p&gt;

&lt;p&gt;After the release, both endpoints serve agent version 3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;endpoints: [('treatment', '4', None, 'READY'), ('control', '4', None, 'READY'), ('DEFAULT', '4', None, 'READY')]
ab tests: [('agentcore_release_gate_f0112c4a-9e273ddca7', 'ACTIVE', 'STOPPED'), ...]
eval configs left: ['showcase_agent_control_eval-TIuENTGKTP']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The A/B test is stopped and remains in AgentCore for later inspection. The two temporary evaluation configurations are deleted, and only the template remains.&lt;/p&gt;

&lt;p&gt;The action also supports a manual approval: &lt;code&gt;step: observe&lt;/code&gt;, &lt;code&gt;step: promote&lt;/code&gt; and &lt;code&gt;step: rollback&lt;/code&gt; split a release into jobs, and a GitHub environment with required reviewers protects the promote job. The action's README has an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this post, I showed how the AgentCore A/B Release Gate releases a new version of an Amazon Bedrock AgentCore agent only after it outperforms the current version on live traffic, and how the same gate rolls back a change that makes the agent worse.&lt;/p&gt;

&lt;p&gt;AgentCore Runtime endpoints, an AgentCore Gateway A/B test and online evaluation work together with the action to deploy a candidate, score both variants, and decide based on statistically significant results. A deterministic, code-based evaluator that encodes the store's support workflow as four rules made the decision: it rolled back a latency optimization that opened returns without checking eligibility first (0.649 against 0.924), and it promoted a prompt fix that stopped the agent from asking customers for SKUs (1.0 against 0.914).&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The action: &lt;a href="https://github.com/alvarog2491/agentcore-ab-release-gate" rel="noopener noreferrer"&gt;alvarog2491/agentcore-ab-release-gate&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The showcase: &lt;a href="https://github.com/alvarog2491/agentcore-release-showcase" rel="noopener noreferrer"&gt;alvarog2491/agentcore-release-showcase&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AWS documentation: &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/ab-testing.html" rel="noopener noreferrer"&gt;A/B testing&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/ab-testing-target-based.html" rel="noopener noreferrer"&gt;A/B tests with target-based routing&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/ab-testing-prereqs.html" rel="noopener noreferrer"&gt;A/B testing prerequisites&lt;/a&gt;, &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/code-based-evaluators.html" rel="noopener noreferrer"&gt;Code-based evaluators&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>githubactions</category>
      <category>aiops</category>
    </item>
  </channel>
</rss>
