What Is a Golden Set?
A golden set (or "gold standard dataset") is a carefully curated collection of representative inputs, each paired with a verified expected output or acceptance criteria. Humans β usually domain experts β confirm every label.
It is the single source of truth for correctness. When you change a prompt, swap a model, or refactor agent logic, you re-run it against the golden set and compare. If the score drops, you have a regression.
Golden sets prize quality over quantity. Fifty carefully chosen, well-labeled examples that cover your critical paths beat ten thousand noisy, auto-generated ones.
"The answer key β the examples you trust enough to grade everything else against."
- An exam answer key
- A lab reference standard
- A calibration weight
Why This Layer Comes First
A Shared Target
Turns fuzzy "the answer looks good" into an objective, agreed-upon definition of correct.
Regression Detection
A stable baseline means any drop in score is an immediate, visible signal that something broke.
Everything Depends On It
Coverage, error analysis, replay, rubrics, and experiments all measure against this ground truth.
Aligns the Team
Writing expected outputs forces product, engineering, and domain experts to agree on requirements.
Fast Feedback
A small, trusted set runs in seconds, giving developers a tight edit-evaluate loop.
Onboards Newcomers
New engineers learn the product's expectations by reading real, labeled examples.
Anatomy of a Golden Example
A rich golden example records more than input and output. Metadata makes the set searchable, auditable, and useful for the coverage layer that follows.
{
"id": "refund-shipped-001",
"input": "Can I get a refund for order #12345?",
"expected": {
"intent": "refund_request",
"decision": "eligible",
"must_mention": ["refund", "30 days"]
},
"category": "refunds",
"difficulty": "easy",
"rationale": "Shipped < 30 days ago, so policy allows a refund.",
"verified_by": "support-lead",
"created_at": "2026-07-01",
"source": "real_ticket"
}
Stable ID
A permanent id lets you track a single example across dataset versions and link failures back to it.
Structured Expectation
Prefer criteria (must_mention, decision) over a single exact string, so grading tolerates valid phrasing differences.
Category & Difficulty
These tags feed Layer 2 (Behavioral Coverage) and Layer 3 (Error Analysis) directly.
Provenance
verified_by, source, and rationale make the label auditable and trustworthy.
How Golden Sets Are Built & Used
(logs, tickets, experts)"] --> B["π§Ή Deduplicate & sample"] B --> C["βοΈ Draft expected outputs"] C --> D["π₯ Expert review"] D --> E{"Agreed?"} E -- "No" --> C E -- "Yes" --> F["π·οΈ Tag & version"] F --> G["π¦ Golden Set v1.0"]
Pull real, representative inputs from production logs and support tickets.
Domain experts write and cross-check the expected outputs.
Freeze the set, commit it, and tag a semantic version.
Add every new production failure as a permanent regression case.
Step-by-Step Implementation
Model a golden example
Represent examples as typed records with structured expectations and metadata.
from __future__ import annotations
from dataclasses import dataclass, field
import json
@dataclass(frozen=True)
class GoldenExample:
"""A single verified input paired with its expected outcome.
Args:
id: Stable identifier that survives dataset versioning.
input: The exact input handed to the agent under test.
expected: Structured acceptance criteria (not just a string).
category: Behavioral bucket used by the coverage layer.
difficulty: Relative hardness, useful for slicing results.
"""
id: str
input: str
expected: dict
category: str = "general"
difficulty: str = "medium"
def load_golden_set(path: str) -> list[GoldenExample]:
"""Load a JSONL golden set from disk.
Args:
path: Path to a newline-delimited JSON file.
Returns:
A list of :class:`GoldenExample` records.
"""
examples: list[GoldenExample] = []
with open(path, encoding="utf-8") as fh:
for line in fh:
line = line.strip()
if line:
examples.append(GoldenExample(**json.loads(line)))
return examples
Write forgiving matchers
Exact-string matching is too brittle for LLMs. Combine criteria-based and semantic matchers so valid rephrasings still pass.
from typing import Protocol
class Matcher(Protocol):
"""Scores how well an actual output satisfies an expectation."""
def __call__(self, actual: str, expected: dict) -> float: ...
def criteria_match(actual: str, expected: dict) -> float:
"""Fraction of required phrases present in ``actual`` (0.0β1.0)."""
required = [p.lower() for p in expected.get("must_mention", [])]
if not required:
return 1.0
hits = sum(1 for phrase in required if phrase in actual.lower())
return hits / len(required)
def decision_match(actual_decision: str, expected: dict) -> float:
"""Return 1.0 when a categorical decision matches exactly."""
return float(actual_decision == expected.get("decision"))
Run the set & report
A small runner executes the agent over every example and aggregates a pass rate plus per-item detail.
from dataclasses import dataclass
from typing import Callable
from .models import GoldenExample
@dataclass
class ItemResult:
"""Outcome of grading one golden example."""
id: str
score: float
passed: bool
def evaluate_golden_set(
examples: list[GoldenExample],
agent: Callable[[str], str],
matcher: Callable[[str, dict], float],
threshold: float = 1.0,
) -> dict:
"""Run ``agent`` over every example and grade with ``matcher``.
Args:
examples: The golden set to evaluate against.
agent: Callable mapping an input string to the agent's output.
matcher: Scoring function ``(actual, expected) -> float``.
threshold: Minimum per-item score to count as a pass.
Returns:
A summary dict with overall ``pass_rate`` and per-item ``results``.
"""
results = []
for ex in examples:
score = matcher(agent(ex.input), ex.expected)
results.append(ItemResult(ex.id, score, score >= threshold))
passed = sum(1 for r in results if r.passed)
return {"pass_rate": passed / max(len(results), 1), "results": results}
Gate CI on the baseline
Fail the build if the pass rate drops below your agreed baseline.
from golden.models import load_golden_set
from golden.matchers import criteria_match
from golden.runner import evaluate_golden_set
def test_agent_meets_golden_baseline():
"""The agent must satisfy at least 95% of the golden set."""
examples = load_golden_set("golden/support.jsonl")
report = evaluate_golden_set(examples, build_agent(), criteria_match)
failing = [r.id for r in report["results"] if not r.passed]
assert report["pass_rate"] >= 0.95, f"Regressions: {failing}"
Use Cases
Policy Correctness
50 labeled refund/exchange scenarios ensure the agent always applies the right policy decision.
Query Ground Truth
Natural-language questions paired with verified SQL and expected result rows.
Structured Fields
Documents paired with the exact JSON fields that must be extracted from them.
Refusal Cases
Known unsafe prompts paired with the expected refusal, guaranteeing guardrails hold.
Best Practices & Pitfalls
Do
- Use real inputs. Source examples from production logs, not from imagination.
- Verify with experts. Every label should be confirmed by someone who knows the domain.
- Version the set. Treat it like code β semantic versions and a changelog.
- Grow from failures. Every production bug becomes a permanent new example.
Avoid
- Exact-string grading. LLM phrasing varies; grade on criteria and meaning.
- Unverified auto-labels. A golden set labeled by another LLM is not "golden".
- Bloat. Ten thousand noisy rows hide regressions; keep it sharp and trusted.
- Silent edits. Never quietly change an expected output to make a test pass.
FAQ
How big should a golden set be?
Start with 30β100 excellent examples covering your critical paths. Precision and coverage matter far more than raw size.
Can an LLM help create the golden set?
Yes β for drafting candidates and expected outputs. But a human must verify each one before it becomes "golden". Unverified LLM labels are just predictions.
Golden set vs. a regular test dataset?
A golden set is a small, high-trust, human-verified subset. A test/eval dataset can be much larger and noisier. The golden set is your immovable baseline.
What if two answers are both correct?
Encode acceptance criteria rather than one exact string β required facts, a decision label, or a semantic-similarity threshold β so any valid answer passes.