<?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: michael hurst</title>
    <description>The latest articles on DEV Community by michael hurst (@michael_hurst_c009b1bdeb8).</description>
    <link>https://dev.to/michael_hurst_c009b1bdeb8</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%2F4103266%2F0ef90da7-f276-4450-94eb-3466c443a0ed.jpg</url>
      <title>DEV Community: michael hurst</title>
      <link>https://dev.to/michael_hurst_c009b1bdeb8</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/michael_hurst_c009b1bdeb8"/>
    <language>en</language>
    <item>
      <title>An AWS Labs agent-eval sample uses the same model as judge and subject</title>
      <dc:creator>michael hurst</dc:creator>
      <pubDate>Mon, 31 Aug 2026 19:59:48 +0000</pubDate>
      <link>https://dev.to/michael_hurst_c009b1bdeb8/an-aws-labs-agent-eval-sample-uses-the-same-model-as-judge-and-subject-e29</link>
      <guid>https://dev.to/michael_hurst_c009b1bdeb8/an-aws-labs-agent-eval-sample-uses-the-same-model-as-judge-and-subject-e29</guid>
      <description>&lt;p&gt;&lt;code&gt;awslabs/Agent-EvalKit&lt;/code&gt; is a sample kit for evaluating AI agents. Its QA example defines the DeepEval judge in &lt;code&gt;examples/qa_agent_evaluation/eval/metrics.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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BedrockLLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DeepEvalBaseLLM&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Custom DeepEval LLM using LiteLLM to call Bedrock.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0&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;Both metric factories instantiate it with no argument:&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;create_faithfulness_metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;FaithfulnessMetric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;bedrock_llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BedrockLLM&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;FaithfulnessMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bedrock_llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;include_reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent under evaluation runs &lt;code&gt;us.anthropic.claude-sonnet-4-20250514-v1:0&lt;/code&gt; — that is &lt;code&gt;gen_ai.request.model&lt;/code&gt; in the example's own &lt;code&gt;eval/otel-traces.jsonl&lt;/code&gt;, and it is the only model id that appears anywhere in that trace file.&lt;/p&gt;

&lt;p&gt;So the judge and the subject are the same model. (Not the same string: the judge carries LiteLLM's &lt;code&gt;bedrock/&lt;/code&gt; route prefix. Same model, one hop of indirection.) The bundled report gives the agent a faithfulness score of 78.2%, and the thing measuring faithfulness is the thing whose faithfulness is being measured.&lt;/p&gt;

&lt;p&gt;Check it yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://api.github.com/repos/awslabs/Agent-EvalKit/tarball/main | &lt;span class="nb"&gt;tar &lt;/span&gt;xz &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;awslabs-Agent-EvalKit-&lt;span class="k"&gt;*&lt;/span&gt;/examples/qa_agent_evaluation/eval &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"judge:"&lt;/span&gt;   &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'bedrock/us\.anthropic\.[a-z0-9.:-]*'&lt;/span&gt; metrics.py | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"subject:"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s1"&gt;'us\.anthropic\.[a-z0-9.:-]*'&lt;/span&gt; otel-traces.jsonl | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"caveats:"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-rniE&lt;/span&gt; &lt;span class="s1"&gt;'same model|self-grad|bias|independent|different model|cross-model|judge model'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
       ../../../ &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.md &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;.py &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"^ nothing under 'caveats:' = undisclosed"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirmed at &lt;code&gt;472fbc6&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part worth arguing about
&lt;/h2&gt;

&lt;p&gt;Not "AWS shipped something bad." It is a Labs sample — 38 stars at the time of writing, last pushed in March 2026 — and using one Bedrock model for both roles is defensible on cost, latency and dependency count. If someone had written that tradeoff down I would have no post.&lt;/p&gt;

&lt;p&gt;The point is that nobody chose it. It is a kwarg default on a helper class. There is no config surface for the judge model, no line in the README noting that the judge defaults to whatever the agent runs on, and — per that last grep — no mention anywhere in the repo of judge independence, model bias, or cross-model evaluation. The most consequential decision in an evaluation harness was never surfaced as a decision at all.&lt;/p&gt;

&lt;p&gt;That is the failure mode I think is worth naming. Self-grading almost never arrives as a claim you can disagree with. It arrives as a default, three call frames down, in a constructor nobody reads.&lt;/p&gt;

&lt;p&gt;And &lt;code&gt;examples/&lt;/code&gt; is precisely where defaults go to breed. Sample directories exist to be copied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I am standing
&lt;/h2&gt;

&lt;p&gt;I build an independent validation gate, so treat this as an interested party pointing at a thing that flatters him, and go run the command.&lt;/p&gt;

&lt;p&gt;And the number that matters here is the unflattering one, so: on a 113-example internal holdout, our hosted API flagged 19.5% of the clean items — "clean" meaning an item our adjudicated labels recorded as containing no defect, so a flag on one is the gate being wrong, not the item. Banked 2026-08-10. That is our data on our holdout; yours will differ. A separate judge is not a correct judge. It is only a judge that is not marking its own work.&lt;/p&gt;

&lt;p&gt;I also filed an unrelated bug in the same file — a debug &lt;code&gt;exit()&lt;/code&gt; that stops the example running — as &lt;a href="https://github.com/awslabs/Agent-EvalKit/issues/4" rel="noopener noreferrer"&gt;issue #4&lt;/a&gt;, with a fix in &lt;a href="https://github.com/awslabs/Agent-EvalKit/pull/5" rel="noopener noreferrer"&gt;PR #5&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
