◉CLAUDE LABJP
●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…●2.1.301 — Adds the vim % motion, LaTeX math rendering in the VS Code panel, and a retry-watchdog limit for usage-limit waits (10/15)●2.1.299 — Conversations over 200K tokens left idle about 54 minutes get compacted; MCP allow rules now match only the server they name●SONNET 4.5 — Retires on the Claude API on 11/30, 45 days left. Migrate to Sonnet 5.5●WINDOWS — Reports say hooks break silently only on Japanese-locale Windows; check the character encoding first●FAST MODE — Opus 5.5 fast mode is out of research preview and no longer needs the beta header (10/15)●NEW — I Put a Ten-Line Promise File at the To…
Articles/API & SDK
⬡ API & SDK/2026-05-30Advanced

Catching Claude Quality Regressions With an Eval Harness

I tweaked a prompt by one line and, for a different set of inputs, the output quietly got worse. Here is the eval harness I built to protect Claude's production quality across every prompt change and model update, with full implementation code and real operating numbers.

Claude52evalqualityLLM-as-judgeAPI28

✦ Premium Article

I tweaked a prompt, and something else quietly broke

I once changed a classification prompt by a single line — "let's have it classify a little more carefully" — and shipped it. The handful of inputs I tried locally were clearly better. A few days later a report came in: one specific category had gotten worse. The inputs I had checked improved; the inputs I hadn't checked quietly degraded.

I've been building apps on my own since 2014, reaching somewhere around 50 million downloads over the years. With code, tests guard against a change breaking existing behavior. But in a feature built on Claude, the same prompt produces different output depending on the input, so traditional assertion-style tests don't carry over as-is. "Tried a few, looks good, ship it" was a bet placed after seeing only a sliver of the input distribution.

So I built an eval harness that mechanically detects quality regressions every time I change a prompt or a model. My grandfather, a temple carpenter, taught me that working with your hands is a kind of devotion — and an eval foundation is exactly the kind of quiet, hands-on groundwork that pays off later. Here is the implementation, and the numbers I saw running it.

Why you need evals, not unit tests

Claude's output is not deterministic. Even at temperature 0, slightly different input yields different output, and even a minor model update shifts behavior. What you want to protect is not "a specific string for a specific input" but "a quality level across the whole input distribution."

That is the decisive difference from conventional testing. A unit test pins down a single point; an eval measures a distribution. The metrics worth guarding boil down to two: first, the average quality score over a representative set of inputs; second, its spread — especially the deterioration of the lowest-scoring band. The opening incident would have slipped past a pure average. Degradation on a subset like one category only surfaces when you look at stratified scores.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A complete eval harness that catches quietly-degraded output from prompt or model changes before you push
✦Rubric design that tamed LLM-as-judge drift and lifted agreement with human grading from 68% to 91%
✦How to set regression thresholds for CI, plus the real per-run cost of my 200-case golden set
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ API & SDK2026-07-24
When Memory Store Listings Returned Half the Rows: Migrating to agent-memory-2026-07-22
agent-memory-2026-07-22 changed memories.list: fixed ordering, stricter depth, segment-based path_prefix matching. How an audit quietly halved, an access layer that survives it, finding every call site with ast, and measured depth=1 traversal cost.
⬡ API & SDK2026-03-15
Building an AI Chatbot with Claude API — Streaming, Conversation History & Cost Optimization
A record of building a chatbot on the Claude API from a minimal script upward: conversation history, streaming, a FastAPI endpoint, cost trimming, LINE/Telegram/Discord, and PII masking. The retry logic was rebuilt around measured jitter and the retry-after header.
⬡ API & SDK2026-05-02
Designing a Claude API Monthly Budget That Doesn't Blow Up — Cost Management for Solo Developers
When you embed Claude API into a side-project app, the first thing you hit is the end-of-month invoice. Here are the budgeting math, logging, caps, and retry rules I use to keep costs predictable, including the places where I tripped.