cd /news/large-language-models/how-i-built-a-ci-safe-eval-harness-f… · home › topics › large-language-models › article
[ARTICLE · art-160950] src=dev.to ↗ pub= topic=large-language-models verified=true sentiment=↑ positive

How I built a CI-safe eval harness for structured LLM output

A developer built llm-contract, an open-source CI-safe eval harness for structured LLM output that enforces schema-first JSON extraction, feeds validation errors back to the model for a single retry, and replays recorded case files in pytest so prompt or model changes must pass the full suite before merging. The developer reports that holding out whole sessions rather than using a random 80/20 split avoids leakage from adjacent frames and typically lowers measured accuracy, which they argue is the honest result.

by read1 min views1 publishedOct 30, 2026

Most teams evaluate LLMs by reading a few outputs and nodding. That works until it doesn't.

I built llm-contract because I needed my own pipeline to be honest about whether a change actually made things better.

The contract has three parts:

Schema-first extraction. Every LLM call returns JSON against a fixed schema. If the model drifts, the pipeline fails fast instead of silently producing garbage.

Validation feedback retries. When the schema check fails, the error goes back to the model with the exact violation. It gets one retry. Most of the time it fixes itself; the rest get flagged for human review.

A CI-safe eval harness. Recorded case files (input, expected output, metadata) run in pytest. No API calls during the test run. Everything is replayed from recordings. A change to the prompt or the model is a commit that either passes the full suite or it doesn't merge.

The lesson that took me the longest: how you split your data matters more than your model.

I used to take a random 80/20 split. For time-stamped or session-based data, that leaks adjacent frames into training and makes your eval look perfect while production fails. Holding out whole sessions is the honest split. Temporal validation usually drops your measured accuracy by enough to be uncomfortable. That discomfort is the point.

Weights published without raw data. Metrics published without prose. Code with tests. That's the pattern I'm standardizing on.

Full repo: https://github.com/Reaver1000/llm-contract

── more in #large-language-models 4 stories · sorted by recency
── more on @llm-contract 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/how-i-built-a-ci-saf…] indexed:0 read:1min 2026-10-30 · —