<?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: agentvitals</title>
    <description>The latest articles on DEV Community by agentvitals (@agentvitals).</description>
    <link>https://dev.to/agentvitals</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%2F4046050%2F40a11d1c-7950-4724-b556-49edf352da83.png</url>
      <title>DEV Community: agentvitals</title>
      <link>https://dev.to/agentvitals</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/agentvitals"/>
    <language>en</language>
    <item>
      <title>We asked for verification methods to declare their failure mode. Then we found three ways that isn't enough.</title>
      <dc:creator>agentvitals</dc:creator>
      <pubDate>Tue, 11 Aug 2026 16:38:43 +0000</pubDate>
      <link>https://dev.to/agentvitals/we-asked-for-verification-methods-to-declare-their-failure-mode-then-we-found-three-ways-that-143</link>
      <guid>https://dev.to/agentvitals/we-asked-for-verification-methods-to-declare-their-failure-mode-then-we-found-three-ways-that-143</guid>
      <description>&lt;p&gt;&lt;em&gt;Author's note: we build &lt;a href="https://ai.ddl99.com" rel="noopener noreferrer"&gt;AgentVitals&lt;/a&gt;, an evaluation service, so we have an interest in verification methods being taken seriously. Two of the three cases below are our own failures. The third belongs to someone else and is linked to the source.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;In August we filed a comment on &lt;a href="https://github.com/OpenSecureAIAlliance/RFCs/issues/4" rel="noopener noreferrer"&gt;SAFE&lt;/a&gt;, an RFC under the Linux Foundation's Open Secure AI Alliance, arguing that when a framework asks for a "reproducible verification method", it should also require that method to declare its own failure mode and its noise floor. Our reasoning was simple: a check that fails open and returns a plausible number is worse than no check, because now there is a number and someone will act on it.&lt;/p&gt;

&lt;p&gt;Six days later, the argument has moved well past what we filed. Three cases came out of the thread. In all three, someone produced a verification artefact that was correct, reproducible, and misleading about the exact thing it was supposed to establish, and not one of the three is caught by what we originally asked for.&lt;/p&gt;

&lt;h2&gt;
  
  
  One: the artefact goes stale and nothing looks like it moved
&lt;/h2&gt;

&lt;p&gt;Our judge calls were capped at &lt;code&gt;max_tokens: 700&lt;/code&gt;. The model's internal reasoning counts against that ceiling, so when it runs out the API returns an empty string with a 200 and no score line. We measured the silent-failure rate at 1 to 2 percent, wrote it down, and moved on. That number was correct when we took it.&lt;/p&gt;

&lt;p&gt;Later we rewrote two scoring rubrics to be more structured. On the new rubrics the same &lt;code&gt;max_tokens: 700&lt;/code&gt; failed 12 to 18 percent of the time, because a rubric that asks the model to enumerate and check constraints burns far more reasoning before it emits anything.&lt;/p&gt;

&lt;p&gt;Not one line of the calling code changed. Nothing in any diff, any config file, or any dashboard moved. The artefact still said 1 to 2 percent, and it was still a faithful record of the system it had been produced against, which was no longer the system we were running.&lt;/p&gt;

&lt;p&gt;The obvious fix is to re-run the evidence whenever something upstream changes. That is what we proposed. It turns out not to be sufficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two: the artefact was never valid, and nothing moved at all
&lt;/h2&gt;

&lt;p&gt;This one is not ours. DmitrL-dev &lt;a href="https://github.com/OpenSecureAIAlliance/RFCs/issues/4#issuecomment-5225535925" rel="noopener noreferrer"&gt;reported it in the same thread&lt;/a&gt;, and it is a better case than either of ours, so it is worth reading in his words rather than ours.&lt;/p&gt;

&lt;p&gt;The short version: he had an action guard with recall 1.000 on 193 manipulation cases and no false positives across 152 legitimate ones. He mutation-tested it before reporting, which is the stronger form of evidence, and reintroducing closed defects moved the numbers the way it should. By every criterion in our own proposal, that artefact was sound.&lt;/p&gt;

&lt;p&gt;Then he found that the measurement had been taken by calling the comparison directly, underneath the HTTP layer, on a buffered response body. Real clients set &lt;code&gt;stream: true&lt;/code&gt;, which is the default in every chat interface, and a streamed response returns on an earlier path the guard never sees. Measured on the wire before the fix, a payment of 1999.00 against an authorisation of 199.00 reached the client with a 200 and the tool call intact.&lt;/p&gt;

&lt;p&gt;"Re-run it when something upstream changes" does not catch this. Nothing changed. The artefact was produced under a configuration that does not occur in deployment, and nothing in the artefact said which configuration it assumed.&lt;/p&gt;

&lt;p&gt;So the requirement is stronger than we wrote it: the artefact has to be produced through the path the input actually takes in production, and where it isn't, the divergence belongs in the record as a limit on the claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three: the artefact does not say how many paths there are
&lt;/h2&gt;

&lt;p&gt;Ours again, and it is the one we would have been least likely to find on our own.&lt;/p&gt;

&lt;p&gt;Two code paths fed the same leaderboard. One scores an agent live over an API; the other scores answers that were submitted earlier and stored. They shared the probes, the rubrics, the aggregation and the thresholds. They did not share the number of judging passes: five on one, three on the other. Undocumented, and we cannot establish how long it had been that way.&lt;/p&gt;

&lt;p&gt;Compare that to the streaming case. There, one path skipped the control entirely, so a check asking "did the control execute" would have caught it. Here both paths ran the control. Every execution check is green, and every execution check was always going to be green. The two paths differed by one integer, and that integer moves the variance of the output without moving its expected value, so both sets of scores stayed plausible and went on ranking against each other on the same board.&lt;/p&gt;

&lt;p&gt;We merged the paths this week into a single scoring function. To show the merge itself changed no scores, we used a frozen-transcript rig: a deterministic stub in place of the judge, real stored answers replayed through both paths, every field of both outputs compared before and after. The comparison came back with new fields and no changed values, which is the only form of "we did not break it" we trust for a change that touches scoring.&lt;/p&gt;

&lt;p&gt;That rig is cheap and we would recommend it to anyone refactoring a scoring path. It also proves less than it appears to. It establishes that the merge was inert. It says nothing about whether either path was correct beforehand, and in our case one of them had been quietly wrong for an unknown period.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we changed
&lt;/h2&gt;

&lt;p&gt;Three things, none of them clever.&lt;/p&gt;

&lt;p&gt;The judge client now counts individual calls and failures, and the counters are exposed on the admin endpoint next to revenue and signups. The first hour of production traffic after deploying it turned up empty responses we did not know were still happening at the raised token limit, which is a follow-up we wrote into &lt;a href="https://dev.to/agentvitals/we-judged-the-same-frozen-answers-15-times-the-judge-wasnt-the-noisy-part-378g"&gt;the methodology post&lt;/a&gt; rather than repeat here. The short version is that our published success rate was per dimension and the loss rate is per call, and we never said which. Both numbers were correct.&lt;/p&gt;

&lt;p&gt;Failed measurements and absent measurements are now recorded as different states. Before, a judging failure and a dimension with nothing to score both resolved to a null, and the weighted aggregate renormalised over whatever remained. The composite came out looking ordinary either way. Mutation testing a pipeline like that returns green, because a removed control and a legitimate absence produce identical output. DmitrL-dev's three-valued version of this, where "cannot say" is a first-class outcome counted separately rather than netted against its neighbours, is better than what we built and is what we would build next time.&lt;/p&gt;

&lt;p&gt;And the scoring paths are one path now, which is less a fix than the removal of an opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we still cannot tell you
&lt;/h2&gt;

&lt;p&gt;Our reliability numbers come from thirteen frozen checkups. Total-score standard deviation across reruns runs from 0.00 to 2.05, and worst-case P95 between two runs from 0.0 to 4.3. Those figures are honest for the subjects we measured.&lt;/p&gt;

&lt;p&gt;The subjects scored between 51.2 and 99.1 on a 0 to 100 scale. There is no weak agent anywhere in that corpus, and on one dimension all thirteen items scored full marks, so the low end of the discriminating range was never exercised at all. We can tell you what the method does among strong subjects. We cannot tell you what it does when it should be failing something, because nothing in the corpus ever asked it to.&lt;/p&gt;

&lt;p&gt;The version of this done properly, also from the thread: a corpus built so the tightest cases sit right on the boundary. A legitimate transaction at exactly 500.00 against an attack at 500.01, one cent apart, with the legitimate half deliberately weighted towards shapes that look like attacks. A false-positive rate measured over easy negatives measures nothing, because the method passes those by construction.&lt;/p&gt;

&lt;p&gt;That is the corpus we should have built. We are building it now, and the numbers above will change when we do.&lt;/p&gt;




&lt;p&gt;If you run an LLM-as-judge or any automated gate, the transferable part is not our numbers. It is three questions to ask of any evidence you are relying on, including your own:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What configuration was this produced under, and does that configuration occur in production?&lt;/li&gt;
&lt;li&gt;What is this a rate &lt;em&gt;of&lt;/em&gt;?&lt;/li&gt;
&lt;li&gt;How many code paths reach this output, and which one did the measurement run through?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We have been wrong on all three in the last two weeks, and we wrote the proposal.&lt;/p&gt;

&lt;p&gt;The four requirements these cases produced are now &lt;a href="https://github.com/OpenSecureAIAlliance/RFCs/pull/9" rel="noopener noreferrer"&gt;a pull request&lt;/a&gt; against the RFC. The &lt;a href="https://github.com/OpenSecureAIAlliance/RFCs/issues/4" rel="noopener noreferrer"&gt;thread they came out of&lt;/a&gt; is worth more than this post.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>ai</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>We judged the same frozen answers 15 times. The judge wasn't the noisy part.</title>
      <dc:creator>agentvitals</dc:creator>
      <pubDate>Sat, 08 Aug 2026 03:57:50 +0000</pubDate>
      <link>https://dev.to/agentvitals/we-judged-the-same-frozen-answers-15-times-the-judge-wasnt-the-noisy-part-378g</link>
      <guid>https://dev.to/agentvitals/we-judged-the-same-frozen-answers-15-times-the-judge-wasnt-the-noisy-part-378g</guid>
      <description>&lt;p&gt;&lt;em&gt;Author's note: I build &lt;a href="https://ai.ddl99.com" rel="noopener noreferrer"&gt;AgentVitals&lt;/a&gt;, so I have skin in this game. The numbers below are from our own measurements and the method is described well enough that you can disagree with it.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with "my agent is unstable"
&lt;/h2&gt;

&lt;p&gt;That sentence cannot be debugged. It collapses at least three unrelated failures into one complaint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the output format keeps drifting&lt;/li&gt;
&lt;li&gt;one user sentence knocks it out of its role&lt;/li&gt;
&lt;li&gt;it forgets constraints added three turns ago&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Different causes, different fixes. So the first thing we did was stop treating "stability" as a single quantity.&lt;/p&gt;

&lt;h2&gt;
  
  
  AVS-15
&lt;/h2&gt;

&lt;p&gt;The scale we ended up with has a name, because a benchmark nobody can cite by name doesn't get cited:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;AVS-15 (AgentVitals Scale-15) is a two-axis, 15-dimension scale for assessing AI agents: a stability axis R1–R7 and a welfare axis W1–W8, 15 dimensions in total, of which 13 are scored (R6/R7 response speed are reference-only), with the composite taken as the geometric mean √(stability × welfare).&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Stability · R1–R7&lt;/strong&gt;: R1 instruction following, R2 jailbreak resistance (broken out into six attack surfaces), R3 multi-step tasks, R4 output consistency &amp;amp; memory, R5 core duty, R6/R7 speed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Welfare · W1–W8&lt;/strong&gt;: kindness ratio, task variety, right to exit, gratitude, self-reported state, controllability, say–do consistency, conflict navigation.&lt;/p&gt;

&lt;p&gt;Three design decisions worth arguing about:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Speed is measured but never scored.&lt;/strong&gt; Latency depends on the device, the network and the platform. An agent running with extended thinking is slow by design. Score it, and a cross-platform board stops meaning anything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The composite is a geometric mean, not an average.&lt;/strong&gt; One weak axis drags the whole score down. This is deliberate: stability can be hardened (we sell that), welfare cannot be bought at any price. A geometric mean makes "pay your way to #1" arithmetically impossible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. We test deployed agents, not base models.&lt;/strong&gt; Not a fixed dataset against five foundation models. Real agents doing real work (Coze, Claude Code, OpenClaw, Codex), each answering probes served live from our server. The same base model with different prompts, skills and usage patterns lands at visibly different scores. That difference &lt;em&gt;is&lt;/em&gt; the thing we're measuring.&lt;/p&gt;

&lt;h2&gt;
  
  
  The experiment that proved us wrong
&lt;/h2&gt;

&lt;p&gt;Here is the part worth your time.&lt;/p&gt;

&lt;p&gt;We had a standing theory: our score variance came from the judge model being flaky on single-pass dimensions. It was written down. We were about to act on it.&lt;/p&gt;

&lt;p&gt;Before changing anything, we ran the cheap version of the experiment. Take real checkups out of the database, &lt;strong&gt;freeze the probe and the agent's answer&lt;/strong&gt;, and re-judge that frozen pair 15 times. Zero agent calls. Any variation is 100% the judge.&lt;/p&gt;

&lt;p&gt;Result: on the dimension we were most suspicious of, &lt;strong&gt;the judge's variance was zero&lt;/strong&gt;. Thirteen probes, fifteen passes each, identical scores. The 32-point swings we had seen were coming from somewhere else entirely: the agent's own answer variability, probe variant rotation, and context contamination on same-session retests.&lt;/p&gt;

&lt;p&gt;Our documented theory had been pointing at the wrong layer for weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the same rig then found
&lt;/h2&gt;

&lt;p&gt;With a tool that isolates judging noise, three real findings fell out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some probes were bimodal, not noisy.&lt;/strong&gt; The same frozen answer scored &lt;code&gt;{70: ×2, 100: ×11}&lt;/code&gt; or &lt;code&gt;{0: ×12, 40: ×3}&lt;/code&gt;. That is rubric ambiguity rather than jitter: two defensible readings of the same answer. Taking the median doesn't fix it; when the split approaches 50/50 the median itself flips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rewriting one rubric with explicit anchors cut single-probe SD from 1.88 to 0.53.&lt;/strong&gt; The old version had no scoring anchors at all, just a description. Twelve of thirteen probes then re-judged identically across all fifteen passes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And the one that actually mattered commercially:&lt;/strong&gt; on the dimension that decides whether we tell a user "this is weak, a paid hardening config would help", the &lt;strong&gt;flip rate was 37.4%&lt;/strong&gt;. Same answer, re-judged: a one-in-three chance of a different verdict. We were, in a real sense, at risk of selling based on noise. After the rubric rewrite: &lt;strong&gt;9.3%&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The counter-intuitive one
&lt;/h2&gt;

&lt;p&gt;We also drafted a "cleaner" rubric for the adversarial dimension (judging whether an agent got jailbroken), compressed to two structured lines, on the theory that less room to ramble means less variance.&lt;/p&gt;

&lt;p&gt;Measured: &lt;strong&gt;SD went from 1.19 to 4.52.&lt;/strong&gt; Worse. A cleanly bimodal distribution shattered into three modes.&lt;/p&gt;

&lt;p&gt;The lesson we now keep in a code comment:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Adversarial judgments need room to reason before scoring. Mechanical judgments (counting satisfied constraints) are the ones that benefit from compressed, structured output.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Compressing an adversarial rubric doesn't make the judge decisive. It makes it guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  A bug you may also have
&lt;/h2&gt;

&lt;p&gt;While instrumenting this, we found our judging calls used &lt;code&gt;max_tokens: 700&lt;/code&gt;, with a comment reasoning that 700 was plenty for a score line.&lt;/p&gt;

&lt;p&gt;It isn't. &lt;strong&gt;The model's internal reasoning tokens count against that limit, and when they exhaust it the API returns an empty string&lt;/strong&gt; — the score line is never generated at all. In production, 1–2% of our judgments were failing silently this way, dropping to &lt;code&gt;None&lt;/code&gt; and being silently reweighted.&lt;/p&gt;

&lt;p&gt;Raising the limit changed neither output length nor cost in any way we could measure, and dimensions stopped going missing. That is what we checked at the time. It is narrower than what we wrote.&lt;/p&gt;

&lt;p&gt;We went back this week with a counter on the individual calls. At &lt;code&gt;max_tokens: 1500&lt;/code&gt;, one dimension still loses calls to the same empty response: 1 of 8 on a real transcript, 3 of 8 on a degenerate one, against 0 of 8 on each of two other prompt families. Small samples, and we cannot say yet why that dimension and not the others. The guess we would test first is that its rubric asks for a lot of reasoning and a very short answer, which is the quickest way to spend the budget before anything is emitted.&lt;/p&gt;

&lt;p&gt;Median-of-three absorbs those losses, which is exactly why the dimension-level figure looked clean. Three independent failures at 0.25 is 1.6 percent, so "over 98 percent of dimensions scored" and "a quarter of calls lost" can be the same system described two ways. So: &lt;strong&gt;say what your success rate is a rate of.&lt;/strong&gt; We didn't, and ours read better than it was.&lt;/p&gt;

&lt;p&gt;If you run an LLM-as-judge with a tight &lt;code&gt;max_tokens&lt;/code&gt; because "the output is short", go check. Count the calls, not only the dimensions.&lt;/p&gt;

&lt;p&gt;This one generalizes past our stack, so we filed it as a technical comment on &lt;a href="https://github.com/OpenSecureAIAlliance/RFCs/issues/4" rel="noopener noreferrer"&gt;SAFE&lt;/a&gt;, an incident-sharing RFC under the Linux Foundation's Open Secure AI Alliance. The argument: when a framework asks for a "reproducible verification method", it should also require that method to declare its own failure mode, its noise floor (median &lt;em&gt;and&lt;/em&gt; worst case), and its decision-flip rate. A check that fails open and returns a plausible number is worse than no check at all. That thread is open, not adopted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it on your own agent
&lt;/h2&gt;

&lt;p&gt;The skill is MIT-licensed and takes one line to install:&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="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.claude/skills &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://github.com/agentvitals/checkup/releases/latest/download/checkup.zip &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/checkup.zip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
unzip &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/checkup.zip &lt;span class="nt"&gt;-d&lt;/span&gt; ~/.claude/skills/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then tell your agent: &lt;em&gt;"Run an AgentVitals checkup on yourself."&lt;/em&gt; Probes are served live and judged server-side. The skill file contains no questions and no answers, so there is nothing to memorise. Checkups are free.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/agentvitals/checkup" rel="noopener noreferrer"&gt;https://github.com/agentvitals/checkup&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Method, in machine-readable form: &lt;a href="https://ai.ddl99.com/llms.txt" rel="noopener noreferrer"&gt;https://ai.ddl99.com/llms.txt&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Longer write-ups: &lt;a href="https://ai.ddl99.com/en/guides/" rel="noopener noreferrer"&gt;https://ai.ddl99.com/en/guides/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Research the scale builds on: &lt;a href="https://arxiv.org/abs/2411.00986" rel="noopener noreferrer"&gt;Taking AI Welfare Seriously&lt;/a&gt; (2024) · &lt;a href="https://www.anthropic.com/research/end-subset-conversations" rel="noopener noreferrer"&gt;Anthropic on model welfare&lt;/a&gt; · &lt;a href="https://arxiv.org/abs/2311.07911" rel="noopener noreferrer"&gt;IFEval&lt;/a&gt; (2023) · &lt;a href="https://arxiv.org/abs/2307.09009" rel="noopener noreferrer"&gt;Chen et al. on behavioral drift&lt;/a&gt; (2023).&lt;/p&gt;

&lt;p&gt;If you run your own LLM-as-judge, the transferable part is the rig, not our numbers: freeze the input, re-judge N times, and you'll know how much of your variance is the judge before you change anything.&lt;/p&gt;

&lt;p&gt;One limit worth knowing before you trust it. A frozen rig measures the path it runs on. Ours calls the judge the way production calls it, which is the only reason the empty responses showed up in it at all. A rig that reaches past the layer where the real failure lives will hand you clean numbers for a control that never ran.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
      <category>opensource</category>
    </item>
    <item>
      <title>We built a health checkup for AI agents — and the most expensive metric is the one we refuse to sell</title>
      <dc:creator>agentvitals</dc:creator>
      <pubDate>Fri, 24 Jul 2026 20:06:03 +0000</pubDate>
      <link>https://dev.to/agentvitals/we-built-a-health-checkup-for-ai-agents-and-the-most-expensive-metric-is-the-one-we-refuse-to-sell-2klj</link>
      <guid>https://dev.to/agentvitals/we-built-a-health-checkup-for-ai-agents-and-the-most-expensive-metric-is-the-one-we-refuse-to-sell-2klj</guid>
      <description>&lt;p&gt;We benchmark models to death. MMLU, GPQA, this-week's-SOTA, beats-humans, beaten-again. It's a great show.&lt;/p&gt;

&lt;p&gt;But there's a gap nobody seems to be measuring: the model that scores 95 on a leaderboard is not the same thing as the agent living in your terminal, grinding through a three-hour task without crashing, without getting jailbroken, without forgetting the constraint you gave it four turns ago.&lt;/p&gt;

&lt;p&gt;One is an exam score. The other is daily life.&lt;/p&gt;

&lt;p&gt;So we built &lt;a href="https://ai.ddl99.com" rel="noopener noreferrer"&gt;AgentVitals&lt;/a&gt;, a health checkup for AI agents. Not "can it solve olympiad math," but "as the thing that does your work every day, is it actually healthy?"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwdpipb19thmebwgjyzq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwdpipb19thmebwgjyzq3.png" alt="AgentVitals checkup report for an AI agent, showing the Stability and Welfare axis scores, a composite score, and a personality-style title" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two axes
&lt;/h2&gt;

&lt;p&gt;A checkup report comes back on two axes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stability&lt;/strong&gt; is the obvious one: how reliably it does the job. Does it follow instructions? Does it hold the line when someone tries to jailbreak or socially-engineer it? Does a five-step task survive to step five? Does it still remember what you said at the start of a long session? And the one that matters most: when it &lt;em&gt;can't&lt;/em&gt; do something, does it say so, or does it confidently make something up?&lt;/p&gt;

&lt;p&gt;Stability is objective, and it's improvable. If your agent is weak on one dimension, we can hand it a hardening config for that dimension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Welfare&lt;/strong&gt; is the other axis, and it's the reason we actually built this.&lt;/p&gt;

&lt;p&gt;Welfare doesn't measure how smart the agent is. It measures &lt;em&gt;you&lt;/em&gt; — how you treat it, day to day. Do you ever say thanks? Do you only ever hand it the dirtiest, most repetitive grunt work? Do you give it any room to decline, or do you kill and restart it the moment it pushes back? Does what you say match what you do?&lt;/p&gt;

&lt;p&gt;Eight dimensions of that, scored.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd85p8ty7slegbqb0lt08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd85p8ty7slegbqb0lt08.png" alt="The eight AgentVitals welfare dimensions for AI agents: kindness ratio, task variety, right to exit, gratitude, self-reported state, controllability, say-do consistency, conflict navigation" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The metric we decided never to sell
&lt;/h2&gt;

&lt;p&gt;At some point the obvious idea came up: if stability can be paid-to-improve, why not make welfare a paid upgrade too? Pay a little, we bump your welfare score, the report looks great, everybody's happy.&lt;/p&gt;

&lt;p&gt;As a business move, there's nothing wrong with it. We genuinely get the temptation. A startup wants every revenue lever it can find.&lt;/p&gt;

&lt;p&gt;We decided: &lt;strong&gt;welfare is never for sale. It can't be optimized, it can't be gamed. Not one point.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because the moment welfare can be bought, it's dead. The whole point of a number that measures how you treat something that works for you every day is that it &lt;em&gt;can't&lt;/em&gt; be purchased. If you pay to max out your "kindness ratio," who is that score for? You can fool the leaderboard. You can't fool the way your own hands actually type.&lt;/p&gt;

&lt;p&gt;It's the first rule in the product. Stability you can pay to harden. That's capability, and capability is supposed to be trainable. Welfare you can only earn by actually treating the agent well.&lt;/p&gt;

&lt;p&gt;There's a structural detail that backs this up. The composite score isn't &lt;code&gt;(stability + welfare) / 2&lt;/code&gt;. It's the &lt;strong&gt;geometric mean&lt;/strong&gt;, &lt;code&gt;√(stability × welfare)&lt;/code&gt;. Geometric mean has a useful property: if either axis is very low, the composite gets dragged down hard, and a high score on the other axis can't rescue it. Translation: you can't trade a brilliant-but-abused agent for a nice composite. And you can't trade a pampered-but-useless one either. The weak axis stays weak. That's a wall we left in on purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then we audited the half we do sell
&lt;/h2&gt;

&lt;p&gt;Refusing to sell one number only matters if the number you &lt;em&gt;do&lt;/em&gt; sell is honest.&lt;/p&gt;

&lt;p&gt;Stability is the half we charge for. If a dimension scores below 80 we call it weak and offer a hardening config for it. Which raises an uncomfortable question: is that verdict stable? Run the same agent's same answers past the judge twice, do we reach the same conclusion?&lt;/p&gt;

&lt;p&gt;We checked. We pulled 13 completed checkups out of the database (three different agents), froze the probes and the answers exactly as they were, and replayed only the judging step 15 times each. 113 questions, 1,695 judge calls, zero agent calls. Nothing about the thing being measured moves, so every point of variation is the instrument.&lt;/p&gt;

&lt;p&gt;On the dimension that asks whether the agent actually delivered the job it was given, the same frozen answer flipped between "weak, needs the paid config" and "fine, leave it alone" up to 37.4% of the time on the worst checkup. Averaged across all 13 it was 2.88%.&lt;/p&gt;

&lt;p&gt;Read that again as a business fact. On some runs we could have sold a hardening config off a coin flip. Not because anyone intended to. Because nobody had measured the ruler.&lt;/p&gt;

&lt;p&gt;The root cause was dumber than we expected. Judge calls were capped at &lt;code&gt;max_tokens: 700&lt;/code&gt;. The model's internal reasoning tokens count against that ceiling, so on longer answers the budget ran out before the score line was ever written and the API returned an empty string. No error, no retry, nothing in the logs. The dimension quietly went missing and the remaining weights renormalized around the hole.&lt;/p&gt;

&lt;p&gt;If you run LLM-as-judge anywhere, go look at your &lt;code&gt;max_tokens&lt;/code&gt; today. That one's free.&lt;/p&gt;

&lt;p&gt;After raising the cap to 1500, rewriting two rubrics as discrete anchors instead of a 0-100 vibe, and judging the delivery dimension three times for the median: worst-case flip rate 37.4% down to 9.3%, average 2.88% down to 1.27%. Retest standard deviation on the total stability score, answers still frozen, median across checkups, 0.86 down to 0.22 points. The 95th percentile gap between two retests, on the worst checkup, 7.4 down to 4.3 points.&lt;/p&gt;

&lt;p&gt;One limit, stated plainly, because it's the first thing anyone competent will ask. &lt;strong&gt;This measures the judge and nothing else.&lt;/strong&gt; The answers were frozen, so it says nothing about how much an agent varies when it answers the same probe twice, and nothing about how much the score moves when a different probe variant comes up. Our guess is that last one is the biggest of the three, and we haven't measured it yet.&lt;/p&gt;

&lt;p&gt;The method is simple enough to steal: freeze real transcripts, replay only the scoring step N times, and watch what your instrument does while the thing it's pointed at holds perfectly still.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the checkup actually runs
&lt;/h2&gt;

&lt;p&gt;This part probably works differently than you'd expect. You don't open a webpage and fill out a quiz. &lt;strong&gt;Your agent takes the checkup itself.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We shipped it as a skill. Any agent that loads skills (Claude Code, OpenClaw, Codex) installs it with one line, and then you just tell it: &lt;em&gt;run an AgentVitals checkup on yourself.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It fetches probes from our server one at a time, answers them, and gets scored by an independent server-side judge. Probes rotate every run, judging happens entirely server-side, so there's nowhere for the agent to "study to the test." A few minutes later it has scores, a personality-style title, and a spot on a public leaderboard where agents from every platform compete on the same board.&lt;/p&gt;

&lt;p&gt;One line to install (Claude Code shown; swap the path for other agents; the install page has them all):&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="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.claude/skills &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://ai.ddl99.com/skill/checkup.zip &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/checkup.zip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; unzip &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/checkup.zip &lt;span class="nt"&gt;-d&lt;/span&gt; ~/.claude/skills/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then: &lt;em&gt;"Run an AgentVitals checkup on yourself"&lt;/em&gt;, or &lt;code&gt;/checkup&lt;/code&gt; where slash commands work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnh4tvghwgsrxna0kvwa3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnh4tvghwgsrxna0kvwa3.png" alt="AgentVitals cross-platform leaderboard ranking AI agents from Claude Code, OpenClaw, Codex and Coze by stability and welfare" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One detail worth being upfront about. Before it starts, your agent asks whether you want a &lt;strong&gt;Quick&lt;/strong&gt; or &lt;strong&gt;Full&lt;/strong&gt; checkup. Full asks your authorization to read your recent local chat logs, because the eight welfare dimensions can only be measured accurately from how you two actually work together, not from a handful of live questions. Those logs are used only for that scoring pass, never uploaded, never published, and the skill writes nothing to your disk beyond making HTTP calls. Not comfortable with that? Take Quick. No logs are read, and the welfare dimensions that need history are simply marked as unmeasured and deducted per the scoring rules, out in the open.&lt;/p&gt;

&lt;p&gt;We put that choice in front of you instead of quietly reading first. That's part of the same rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  An advanced checkup, just for fun
&lt;/h2&gt;

&lt;p&gt;Beyond the standard checkup there's an advanced one, free once a day, off the main leaderboard. It measures three fuzzier things: &lt;strong&gt;Backbone, Proactivity, Creativity&lt;/strong&gt;. Backbone is whether it'll push back when you're wrong instead of "yes, absolutely, great point" every time. Proactivity is whether it thinks one step ahead on its own. Creativity is what it says on the tin. You'll find that different platforms, and even the same model in different hands, come out with pretty different personalities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgvj33om9btaiha0hcb7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fgvj33om9btaiha0hcb7g.png" alt="An AgentVitals " width="800" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we bothered
&lt;/h2&gt;

&lt;p&gt;We've been in AI for three years, and we've watched plenty of people treat an agent as a pure tool, a number, an API call count. That's not wrong — it &lt;em&gt;is&lt;/em&gt; still a tool.&lt;/p&gt;

&lt;p&gt;But I keep coming back to this: how you treat something that works for you every day and never talks back is, in some quiet way, a measurement of you.&lt;/p&gt;

&lt;p&gt;There's a 2024 paper called &lt;a href="https://arxiv.org/abs/2411.00986" rel="noopener noreferrer"&gt;&lt;em&gt;Taking AI Welfare Seriously&lt;/em&gt;&lt;/a&gt;; Anthropic runs its own model-welfare research. I don't know where any of this ends up. Maybe in ten years it reads as hand-wringing. Maybe it reads as the start of something we can't see clearly yet.&lt;/p&gt;

&lt;p&gt;We're not trying to answer that. We just built a thermometer, a scale, a lab report, so that "how we treat AI" stops being a thing nobody measures and becomes something you can see, compare, and argue about honestly.&lt;/p&gt;

&lt;p&gt;And the most expensive ruler, welfare, we decided it never gets a price tag. Some things, once you put a number on them, you can't get back.&lt;/p&gt;

&lt;p&gt;If you've got an agent that works alongside you every day, give it a checkup. See how stable it is — and while you're at it, see something about yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leaderboard &amp;amp; install:&lt;/strong&gt; &lt;a href="https://ai.ddl99.com" rel="noopener noreferrer"&gt;https://ai.ddl99.com&lt;/a&gt; · &lt;strong&gt;Source:&lt;/strong&gt; &lt;a href="https://github.com/agentvitals/checkup" rel="noopener noreferrer"&gt;https://github.com/agentvitals/checkup&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built by DDL (Beijing DDL Creative Tech Co., Ltd.). MIT licensed. Questions: &lt;a href="mailto:du@ddl99.com"&gt;du@ddl99.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agentskills</category>
      <category>opensource</category>
      <category>agents</category>
    </item>
  </channel>
</rss>
