Skip to main content

LLM-as-Judge Verifier

Use an LLM to evaluate agent outputs against a rubric instead of deterministic tests.

When to use LLM-as-judge

Use LLM-as-judge when the task output is subjective, open-ended, or hard to verify with unit tests — legal analysis, code review quality, document drafting, research summaries. For tasks with a clear right answer (e.g. “write fizzbuzz”), stick with deterministic test.sh verifiers. BenchFlow’s LLM judge supports:
  • First-class verifier strategytype: llm-judge in verifier/verifier.md, no test.sh needed
  • Multi-criterion rubrics with binary, likert, and numeric scoring
  • Per-criterion weights for non-uniform importance
  • Dense reward events emitted per criterion during evaluation
  • Multi-provider routing across Anthropic, OpenAI, and Google models
  • Configurable aggregation (weighted mean, all-pass, any-pass, threshold)
The judge is a first-class verification method alongside the deterministic test.sh verifier. A task selects it with one line of config — the framework handles deliverable collection, prompting, provider routing, retries, and reward aggregation.

Quick start

0. Install the judge provider SDKs

The judge calls the Anthropic, OpenAI, and Google SDKs — these are not installed by default. Install the judge extra (you only need at least one provider’s SDK for the model you use, but the extra ships all three):
If no provider SDK is installed, the judge cannot run: the verifier raises a verifier error (the rollout is marked errored) rather than silently recording a reward of 0.0 — a missing dependency is an environment failure, not a score.

1. Select the judge verifier in verifier/verifier.md

That’s the entire native verifier. There is no verifier/test.sh to write — the Verifier downloads the agent’s deliverables from input_dir, scores them against the rubric, and writes reward.json itself. Judge credentials are resolved from the host environment or .env and are scoped to the verifier runtime.

2. Write verifier/rubrics/verifier.toml

Place it where the strategy’s rubric field points:
A Harvey LAB style rubric.json works too — set rubric: rubrics/verifier.json:
That’s it. Run the task as usual — the reward is the proportion of criteria passed (or the configured aggregation), a partial float in [0, 1].

[verifier] reference

Native llm-judge strategy fields

Legacy split-layout packages still project these fields through [verifier] and [verifier.judge] in task.toml; native task.md packages should use verifier/verifier.md.

Library use — LLMJudgeRewardFunc

The judge is also a composable RewardFunc, usable directly or from a custom test.sh verifier:
Auto-discovery — if rubric.toml/rubric.json is in the rollout directory or its parent, it’s found automatically:

rubric.toml reference

[judge] section

[[criterion]] entries

[scoring] section

Score normalization

Each criterion type normalizes its raw score to [0, 1]:

Aggregation strategies


Criterion types

Binary (pass/fail)

The judge decides whether the criterion is satisfied. The LLM returns {"verdict": "pass", "reasoning": "..."}.

Likert (scaled)

The judge rates on a 1-to-N scale. The LLM returns {"score": 4, "reasoning": "..."}.
A score of 3 on a 5-point scale normalizes to (3-1)/(5-1) = 0.5.

Numeric (range)

The judge assigns a value within a continuous range. The LLM returns {"score": 75.0, "reasoning": "..."}.

Inline criteria (no TOML file)

For programmatic use or Harvey LAB-style criteria, pass criteria directly:
Harvey LAB match_criteria keys are also supported:

Dense reward events

Each criterion emits a RewardEvent during evaluation, enabling per-criterion observability and training signal:
Output:
Events have type "dense", a reward in [0, 1], a source of "criterion:{name}", and a step index. Events are cleared between score() calls.

Multi-provider routing

The judge model string determines which provider SDK is used: If the primary provider fails, the judge falls back through the other providers with retries and exponential backoff. The provider SDKs ship in the judge extra (uv sync --extra judge). If none are installed, the judge raises a verifier error instead of recording a reward — see step 0.

Evaluation output

After scoring, an evaluation_details.json is written to the rollout directory:
The score field is the actual aggregated score from the configured strategy, not n_passed / n_total.

File discovery

The judge automatically discovers deliverable files in the rollout directory. Supported formats: Files larger than 50 MB are skipped. Hidden files (starting with .) and internal metadata files (rubric.json) are excluded. File content is truncated at 15,000 characters per file when sent to the judge. To scope a criterion to specific files:

Python API

All rubric config types are importable from the top level:

A legal document analysis task scored entirely by config — no test.sh:
The framework downloads the agent’s deliverables from /app, grades each criterion, aggregates, and writes reward.json — no scripting required.

Where to go next