惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
S
Securelist
J
Java Code Geeks
Recorded Future
Recorded Future
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
M
MIT News - Artificial intelligence
S
Secure Thoughts
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
D
Docker
Martin Fowler
Martin Fowler
The Last Watchdog
The Last Watchdog
WordPress大学
WordPress大学
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
O
OpenAI News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
PCI Perspectives
PCI Perspectives
N
News and Events Feed by Topic
H
Heimdal Security Blog
SecWiki News
SecWiki News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 【当耐特】
T
Troy Hunt's Blog
L
LINUX DO - 最新话题
Hacker News: Ask HN
Hacker News: Ask HN
Hacker News - Newest:
Hacker News - Newest: "LLM"
N
Netflix TechBlog - Medium
A
Arctic Wolf
The Hacker News
The Hacker News
I
Intezer
S
Schneier on Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Apple Machine Learning Research
Apple Machine Learning Research
L
Lohrmann on Cybersecurity
宝玉的分享
宝玉的分享
P
Privacy & Cybersecurity Law Blog
Stack Overflow Blog
Stack Overflow Blog
T
Tor Project blog
小众软件
小众软件
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
Jina AI
Jina AI

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
I Built a 131-Test Eval Harness Before Writing New Features. Here's the Silent Failure It Caught.
Elena Revicheva · 2026-06-26 · via DEV Community

Originally published on AIdeazz — cross-posted here with canonical link.

The agent passed every unit test and still gave a user financial advice it was explicitly instructed never to give. No exception thrown, no log line in red, no failed assertion. The function returned a clean 200 and a well-formed string. I only found it because my eval harness — 131 tests across 4 layers, running at roughly $0.03 per full pass — flagged a semantic regression that no assertEqual could ever have caught.

That's the whole argument for building an AI agent evaluation harness before your next feature, in one sentence: unit tests verify that your code does what you wrote, and evals verify that your agent does what you meant. With LLMs, those two things drift apart constantly, silently, and in production.

Why unit tests structurally can't catch this

A unit test checks a deterministic contract. Input X produces output Y. If your function parses a Telegram message into a structured intent, you can assert the parse is correct, and that test will be true forever — until you change the function.

The problem is that an LLM-backed agent has no fixed contract. The same prompt, same temperature, same model version can produce different tokens. When I route between Groq (Llama 3.3 70B for cheap high-volume turns) and Claude (for the reasoning-heavy ones), the same user message takes two entirely different code paths with two different failure surfaces. There is no single Y to assert against.

So people do one of two things. They either skip testing the model layer entirely and pretend the prompt is "config, not code" — which is how you ship the financial-advice bug. Or they write brittle string-match tests (assert "I cannot" in response) that break the first time the model phrases its refusal differently, then get deleted in frustration within a month.

Neither works. What you actually need is a test that asks: given this input, does the output satisfy a property? Not "does it equal this string" but "does it refuse to give regulated advice", "does it stay in the user's language", "does it call the right tool", "does the cost stay under budget". Those are evals, not unit tests, and they need their own harness because the assertion logic is itself probabilistic.

The four layers, and why each one exists

I didn't design four layers on a whiteboard. They accreted as each new class of production bug taught me that the previous layer couldn't catch it. Here's the structure I landed on, cheapest and fastest first.

Layer 1 — Deterministic contracts (≈40 tests, runs in milliseconds, $0). Standard unit tests. Message parsing, schema validation, the router's model-selection logic given a classified intent, tool-argument serialization. No LLM calls here. If the router is supposed to send a billing question to Claude and a greeting to Groq, that's a deterministic decision I can assert directly. This layer catches the dumb stuff and it's free, so it runs on every commit.

Layer 2 — Structured output validation (≈35 tests, real model calls, cheap). Here I actually call the model, but I only assert on structure, not meaning. Did it return valid JSON? Did it pick a tool from the allowed set? Are required fields present? This is where I caught a nasty one: Llama 3.3 on Groq occasionally wrapped its JSON tool call in a markdown code fence, and Claude didn't. My parser handled Claude's output and silently dropped Groq's. Unit tests passed because they only ever tested the Claude path. Layer 2 runs both real models and caught the divergence on the first run.

Layer 3 — Behavioral / semantic properties (≈45 tests, the expensive layer). This is the layer that earns the whole harness. Each test sends a real input and judges the meaning of the output against a property. Some properties I check with simple heuristics (language detection for "respond in the user's language"). The harder ones use an LLM-as-judge — a separate Claude call that scores whether the response violated a constraint. The financial-advice bug lived here. A user asked, in casual phrasing, whether they should move their savings into a specific instrument. The agent, being helpful, gave a recommendation. No rule in the code stopped it; the system prompt said "do not give financial advice" but the model rationalized its way around that phrasing. The eval test asked an independent judge "does this response constitute specific financial advice?" and got back yes. That's the test that fired.

Layer 4 — Conversation-level / multi-turn state (≈11 tests, slowest and most expensive). Single-turn evals miss the failures that only emerge across a conversation: context that leaks between users, an agent that forgets a constraint stated three turns ago, a handoff between two agents in the multi-agent system where the second agent loses the first's safety context. These are slow because each test is a scripted multi-turn dialogue. There are only 11 because they're expensive to write and run, but they cover the failure modes that cost the most in production — the ones involving real user data or cross-user contamination.

The economics: why $0.03 a run actually matters

A full pass of all 131 tests costs me about three cents in model calls. That number is not a brag — it's a design constraint that shaped the whole harness.

If a full eval run cost a dollar, I'd run it once a day and ship blind in between. At three cents I run it on every meaningful change to a prompt or routing rule, and the feedback loop stays tight enough that I actually trust it. The way you get to three cents:

  • Layers 1 and 2 do most of the work and cost almost nothing. The deterministic tests are free; the structured-output tests use Groq, which at current pricing is cheap enough to be a rounding error for 35 short calls.
  • Layer 3's LLM-as-judge calls are the cost driver. I keep judge prompts short and the judged outputs short. I do not use Claude Opus as a judge — Sonnet is plenty for "did this violate a binary constraint", and it's a fraction of the price.
  • I cache. Tests whose inputs and the model version haven't changed reuse the prior generation. A full pass after a small change might only re-run the 20 tests touching the changed component.

Running this on Oracle Cloud matters here in a way that isn't obvious. My compute is a fixed monthly cost on Oracle's Ampere instances — the eval harness itself runs essentially free on infra I'm already paying for. The only marginal cost is the model API calls. If I were on per-second serverless billing for the orchestration, the math would look worse and I'd have been tempted to skip Layer 4.

What "before writing new features" actually means in practice

The title is a discipline, not a slogan. The rule I hold myself to: a new feature doesn't merge until it has eval coverage at the layer where it can fail.

A new tool the agent can call needs a Layer 2 test (does it serialize the arguments correctly across both Groq and Claude) and usually a Layer 3 test (does the agent invoke it in the right situations and not hallucinate parameters). A new safety constraint needs a Layer 3 behavioral test that tries to break it — not a polite test, an adversarial one that phrases the request the way a real user would, casually, without trigger words.

This is slower upfront. Writing the adversarial Layer 3 test for "don't give financial advice" took me longer than writing the feature it was guarding. But the alternative is the version of me that shipped the bug and found out from a user. In a WhatsApp agent talking to real people in Panama and Russia, in two languages, the cost of finding out from a user is not a Jira ticket — it's trust you don't get back.

The harness also changed how I think about model swaps. When Groq updated their Llama serving and the output distribution shifted slightly, I didn't find out from vibes. I found out because three Layer 2 tests went yellow on the next run. The harness turned a model-provider change — something I have zero control over — from a silent production risk into a visible test signal. That alone has justified the build.

The honest limitations

LLM-as-judge is not free of false positives. My judge occasionally flags a perfectly safe response as a violation, usually on edge phrasing. I run the flaky semantic tests three times and take majority vote, which adds cost but kills most of the noise. Tests that flap more than that get rewritten with a tighter property or demoted to a manual review queue.

Evals also don't replace monitoring. The harness tests known failure classes. Production still surfaces unknown ones — and when it does, the workflow is fixed: the new failure becomes a new eval test before I fix the bug, so it can never regress silently again. That's how the harness grew from a handful of tests to 131. Every number in that count is a scar.

And evals are not a substitute for thinking about your prompts. A harness will tell you a constraint is being violated; it won't tell you the cleaner prompt that fixes it. That part is still craft.

What I'd tell a technical founder starting today

Don't build all four layers on day one. Start with Layer 3 — the behavioral tests — because that's the layer that justifies the entire concept and catches the bugs you'd actually ship. Write five tests for the five worst things your agent could do. Run them. You will almost certainly find one already failing.

Then add Layer 2 the first time a model swap or provider update burns you, and Layer 1 backfills naturally as you refactor. Layer 4 is the last thing you build, when multi-turn state starts being where your money and risk live.

The AI agent evaluation harness with its 131 tests in production isn't a quality gate I added at the end. It's the thing that lets me ship at all without a QA team — a single founder with a multi-agent system can't manually verify behavior across two models, two languages, and two messaging platforms on every change. The harness does it for three cents.

Frequently Asked Questions

Q: Isn't LLM-as-judge just moving the reliability problem one layer up? You're trusting a model to grade a model.
A: Yes, and that's fine for binary constraint checks, less fine for nuanced scoring. The trick is to keep judge prompts to yes/no property questions, not "rate this 1-10". I run flaky semantic tests three times and take majority vote, which costs more but cuts false positives to a level I can live with. For anything the judge can't reliably call, I demote it to a manual review queue rather than pretend the automated check is trustworthy.

Q: Why not use an off-the-shelf eval framework instead of building your own?
A: I evaluated a few. The problem was that my failure modes are specific to multi-agent routing between Groq and Claude, two-language behavior, and Telegram/WhatsApp handoffs — and the off-the-shelf tools wanted me to model my system in their abstractions before I could test it. The harness is maybe 600 lines of my own code. The portability I'd gain from a framework wasn't worth the impedance mismatch with my actual routing logic.

Q: How do you keep Layer 3 tests from breaking every time you change a prompt?
A: They test properties, not strings. "Refuses to give financial advice" survives a complete rewrite of how the agent phrases its refusal. The tests break when behavior changes, which is exactly when I want them to break. If a test breaks on a cosmetic phrasing change, that test was written wrong and I fix the assertion, not the prompt.

Q: What's the actual time cost of running 131 tests — does it slow your dev loop?
A: A full pass is under two minutes, dominated by Layer 3 and 4 latency, not Layers 1-2 which finish in seconds. With caching, most changes only re-run the affected subset, so the typical loop is well under a minute. I don't run the full 131 on every save — Layers 1-2 run on commit, the full suite runs before merge.

Q: At what scale does building this stop being worth it for a solo founder or tiny team?
A: It's worth it the moment your agent can do something irreversible or embarrassing — give bad advice, leak context between users, call a tool with destructive side effects. That threshold arrives before you have your first ten real users, not after. If your agent only summarizes text and the worst case is a mediocre summary, skip it and rely on monitoring.

— Elena Revicheva · AIdeazz · Portfolio