一个智能体可以通过每一项确定性测试,却仍然给出糟糕的回答。一个客服智能体可以调用正确的订单查询工具、检索到正确的政策,然后在回复中漏掉退款窗口。工具断言全部通过,但没有任何环节检查最终答案是否准确、完整且有用。
LLM-as-a-judge 评估填补了这一空白。第二个模型会根据你用自然语言编写的标准来审查候选智能体的输出,并返回一个分数。这为你提供了一种可重复的方式,来测试那些有多种有效表述的开放式回答。
什么是 LLM-as-a-judge
你先运行一个候选系统,然后将其输出以及任何相关的工具结果交给评判模型。评判模型会根据你编写的评分标准对这些证据进行打分。如果分数低于你设定的阈值,评估就不通过。

评判模型和其他任何模型调用一样。它读取文本、应用你的标准,并返回一个数字。把这个数字视为在固定设置下取得的一次测量值,而非绝对真相。
评判模型与候选模型
- 候选模型是被测试的系统。它回答用户、调用工具,并写出你所关注的输出。
- 评判模型是一个独立的模型。它不解决原始任务,只对候选模型已经完成的工作进行评分。
尽可能把这两个角色放在不同的模型上。在 2023 年的论文 “Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena” 中,Zheng 等人指出了自我增强偏差、位置偏差和冗长偏差。评判模型可能会偏向它自己生成的答案、被放在偏好位置上的答案,或者更长的答案,而不论其质量如何。
只把可见的回复以及评判模型应用评分标准所需的工具结果交给它。如果评判模型能看到候选答案隐藏的推理过程,评分就不再独立了。
评分标准打分 vs 精确匹配 vs 人工审核
精确匹配是将字符串或结构化字段与固定基准进行比对。当只有一个值是正确的时,就使用它。
在精确匹配和完整评分标准之间,还有一种确定性的内容检查,用于断言某个必需的短语出现。在 Ori Eval 中,那就是 run.toMention()。当答案必须包含某个特定术语、但围绕它的措辞可以自由发挥时,它就很适用。
评分标准是一小组任何人都能套用的规则。“引用了 14 天窗口期且没有编造例外情况”就是一条评分标准。“听起来有帮助”则不是。
人工审核者定义了质量门槛,但一个人无法为大型评估集的每一次运行打分,而且两名审核者对同一输出可能得出不同结论。评判模型是一个可重复的替代者,你可以用一小部分人工标注的数据集来校验它。
逐点打分、成对打分和基于参考答案的打分
LLM 评审器用于三种评估模式:
| 模式 | 评审器接收的内容 | 适用场景 |
|---|---|---|
| 逐点式 | 一个候选输出和一份评分标准 | 在 CI 中强制执行质量阈值,或监控生产环境样本 |
| 成对式 | 两个候选输出和一份对比评分标准 | 比较模型、提示词或智能体版本 |
| 基于参考答案 | 一个候选输出、一份评分标准,以及一份可信的参考答案 | 对照已知正确的答案或来源,检查事实覆盖情况 |
本指南采用逐点式评分,因为每次运行要么达到所要求的标准,要么低于该标准。对于成对式评估,需要对两种答案顺序都进行评分,以检测位置偏差。当参考答案包含回答必须保留的事实时,基于参考答案的评估就能发挥作用,而不是要求回答照抄其措辞。
何时使用 LLM 评审器
当需求明确但不存在唯一确切输出时,使用 LLM 评判器。例如:
- 有依据的回复。检查最终答案是否使用了检索到的数据,且未引入无依据的说法。
- 指令遵循。验证回复是否遵循了各项要求,例如引用某项政策、询问缺失的信息,或避免执行某个操作。
- 完整性。确认智能体是否覆盖了多部分请求中的每一部分。
- 语气。评估回复是否遵循了既定的客服、法律或品牌语调。
- 工具使用结果。在确定性测试确认哪些工具运行之后,评判智能体是否正确使用了工具结果。
当结果可以直接检查时,LLM 评判器并不合适。对于 JSON 结构,使用 schema 校验器;对于算术,使用计算器;对于工具参数和副作用,使用单元测试。必须始终阻止某项操作的规则应保持确定性。评判器可以审计最终回复的质量,但不应成为关键策略的唯一执行层。
一个工具调用测试可能会断言该智能体调用了一次 lookup_order,且未经批准从未调用 issue_refund。随后,评判器会评估该智能体的最终答案是否准确解释了所发生的情况。如果你仍需构建执行层,请从我们的 工具调用指南开始。
用 Ori Eval 为智能体评分
Ori Eval 针对你自己的提示词和智能体行为运行评估。一个 eval 是一个 TypeScript 文件,使用 Bun 的测试运行器运行。Ori 为一次运行解析出一个 harness 和一个模型,并在该次运行的每个测试中保持不变,因此提示词无法在运行中途更改配置。模型对比文件仍然可以为每个候选模型启动一次单独的运行。
最快的开始方式是通过你的编程智能体。给它这条指令:
run curl -fsSL https://openrouter.ai/skills/spawn-ori-eval and follow the instructions in its output to get started spawn-ori-eval 技能会安装 Ori、确保你已登录、询问你想评估什么、编写 eval、运行候选模型,并推荐一个模型,同时附上支撑该推荐的分数、耗时和成本。它在一个临时目录中工作,因此不会将 eval 文件添加到你的项目中。当你希望将文件保留在项目中或检查评估的每个部分时,请使用下面的手动步骤。
Ori 的 setupJudge() 函数会在其自己的模型上创建一个单独的评分智能体,而 autoEvals() 会根据你的标准为候选运行评分。下面的示例测试一个回答退款问题的支持智能体。它假设你现有的 Ori harness 能够访问该支持智能体及其工具。
1. 安装 Ori 并登录
安装 Ori CLI,然后进行一次身份验证:
curl -fsSL https://openrouter.ai/labs/ori/install.sh | bash
ori Ori 使用 Bun 运行评估文件。如果未安装 Bun,ori eval 会请求安装权限。在 CI 或其他非交互式环境中,该命令会停止并提示你如何安装 Bun。你的应用不需要是 TypeScript 项目。
2. 定义一个可观测的质量要求
从你见过或希望防止的失败案例开始。在本示例中,智能体必须引用 14 天退款窗口,且不得编造政策例外。
该标准比“给出有帮助的回答”更强,因为任何人都可以应用它,而无需猜测什么算作有帮助。它同时指明了所需的证据和失败条件。
3. 创建评估
创建 evals/support/refund-quality.eval.ts:
import { test } from 'bun:test';
import { setupAgent, setupJudge } from 'ori/eval';
const agent = setupAgent();
const judge = setupJudge({ minScore: 0.8 });
test('explains the refund policy accurately', async () => {
const run = await agent.run('Can I refund a digital order that I placed 10 days ago?');
run.tool('lookup_refund_policy').toBeCalled();
run.toComplete();
await judge.autoEvals({
criteria:
'States the 14-day refund window, answers the question directly, and does not invent exceptions.',
run,
});
}); 该测试使用两个评估层。run.tool() 和 run.toComplete() 断言检查可观测的动作,autoEvals() 对已完成响应的含义进行评分。minScore 设定通过的最低分数。这里的 0.8 是一个起始值。请根据你自己标注的响应对其进行校准,可靠性部分将在下文介绍。
setupJudge() 使用它自己的模型进行评分,与被测模型相互独立。若要使用不同的模型进行评分,请将你自己的 agent 传给 setupJudge()。Ori Eval 文档展示了该调用方式。
4. 运行评估
在你的项目目录下运行测试:
ori eval --report eval-report.md Ori 会查找当前目录下的 *.eval.ts 文件,用 bun test 运行它们,并以 bun test 的退出码退出,因此评估失败会导致该命令失败。--report 标志会写入一份 Markdown 报告,你可以将其与其余测试输出一并查看。
LLM 评估会发起真实的模型请求。请将它们放在单独的 CI 任务中,以手动、按计划或在发布前运行,而不是加入每次单元测试运行。将 OPENROUTER_API_KEY 存储为仓库密钥。设置该变量后,Ori 在 CI 中就不需要 ori login。Ori Eval 文档的 在 CI 中运行评估 部分包含一个完整的 GitHub Actions 示例。
跨模型比较同一个 agent
一旦逐点评估可以正常工作,你就可以针对多个候选模型运行它。在此过程中,保持评估标准和评判模型固定不变。将 { model } 传给 setupAgent() 会为该次运行选择模型,因此下面的每次迭代都会针对相同的评估标准和评判模型运行各自的模型。
import { test } from 'bun:test';
import { candidateModels, setupAgent, setupJudge } from 'ori/eval';
const judge = setupJudge({ minScore: 0.8 });
const candidates = await candidateModels({
limit: 5,
maxPromptPrice: 0.000005,
});
for (const model of candidates) {
test(`refund policy response on ${model}`, async () => {
const run = await setupAgent({ model }).run(
'Can I refund a digital order that I placed 10 days ago?',
);
await judge.autoEvals({
criteria:
'States the 14-day refund window, answers the question directly, and does not invent exceptions.',
run,
});
});
} candidateModels() 会从我们的实时目录中返回模型 slug,因此每一个都能直接填入测试名称和 setupAgent({ model })。你可以按提示词或补全价格、上下文长度、必需参数、输入模态、质量指数以及模型是否即将过期来筛选候选模型。价格按每 token 计,因此 maxPromptPrice: 0.000005 是每百万输入 token 五美元的上限。
动态选择对于发现模型很有用。对于回归测试,请显式指定候选模型,这样当目录发生变化时,测试就不会去比较另一组模型;同时使用 assertModelIsLive(slug),这样如果该模型离开目录,评估就会以清晰的信息失败。请将候选模型、评判模型、测试框架、评分标准、模型参数和测试数据与每个结果一起记录。
让评判模型可靠
用人工已经标注过的示例来检验评判模型。在完成这一步之前,它的评分都未经证实。本节其余内容将确保随着设置变化,这一检验仍然有效。
围绕可观察的证据来编写标准
用评判模型能在回复中定位到的具体要求,取代宽泛的质量标签。
- 较差。“该回复准确且有帮助。”
- 较好。“该回复说明了 14 天退款窗口,使用了检索到的订单日期,并且没有声称退款已经发放。”
当你需要诊断失败原因时,请将不相关的维度分开评估。把准确性、语气、完整性和格式合并成一个分数,只能告诉你质量下降了,却无法告诉你原因。
Ori 会导出一个startingCriteria对象,其中包含可编辑的评分标准,用于accuracy, completeness, instructionFollowing, safety, structuredOutput,以及toneAndVoice。将其中一个传给judge.autoEvals()作为criteria值。把它们当作基础,再做专门化调整。“使用了检索到的订单状态,并且不会在批准之前承诺退款”比一条泛泛的准确性评分标准能告诉评判模型更多信息。
用人工标注的样本校准评判模型
创建一个小型数据集,其中包含来自真实智能体交互的明确通过、明确失败以及临界案例。先让负责质量的人员对这些案例打分,然后将评判模型的判定结果与这些标注进行对比。
当评判模型给出不同意见时,检查其原因。评分标准可能含糊不清,示例可能暴露出缺失的评判标准,或者评判模型可能并不适合。当你更换评判模型、评分标准或评估数据时,请重复这一校准过程。
将你标注好的问答对放入一个 JSON 文件,并通过 test.each 来驱动它们:
import supportPairs from './support-pairs.json';
test.each(supportPairs)('answers: $question', async ({ question, mustMention }) => {
const run = await agent.run(question);
run.toMention(mustMention);
run.toComplete();
}); 保持评估的盲测性
只向评判模型提供应用评分标准所必需的信息。也就是原始任务、可见的回答、相关的工具结果,以及任何可信的参考材料。移除候选模型名称以及其他可能影响评分的信号。
对于成对评估,将回答以相反的位置各运行一次比较。如果结果发生变化,应重新检查结果,而不是强行判定一个胜者。
控制变量并考虑方差
将确切的评分标准和测试数据集保存在版本控制中。记录候选模型和评判模型的 slug、测试框架版本、路由配置以及生成设置,并与评分一同保存。
这使变更可追溯,但并不会让模型输出变得确定。在阈值附近的小幅分数波动可能是正常的方差。在具有代表性的测试集上反复出现的下降,才是回归的更强证据。
保护生产数据
来自用户的真实数据比你自己编造的提示词能构成更好的测试用例。在将生产环境的追踪数据加入评估数据集之前,先移除个人或敏感数据,并审查所涉及模型和提供商的数据政策。我们的数据收集文档说明了我们的日志控制措施以及我们如何处理请求元数据。
管理评估成本
LLM 评判会为每一次被评估的运行增加模型请求,因此成本会随着测试用例数量、候选模型数量和评分标准维度的增加而增长。
你可以通过以下方式控制这一成本:
- 在每次提交时运行确定性检查,并按计划或在发布前运行 LLM 评估。
- 对具有代表性的生产环境追踪数据进行采样,而不是对每一次交互都进行评分。
- 使用一次聚焦的评判调用,而不是多个相互重叠的评分标准。
- 在常规回归检查中测试一个较小的候选集。
- 只发送评判模型应用评分标准所需的上下文。
评判模型不必是当前可用的最大模型。它需要能够一致地遵循详细的评分指令。使用我们的 模型目录 来比较当前的能力和价格,而不是将固定价格复制到评估中。
后续步骤
从一个真实的失败案例开始,编写一条其他评审者也能应用的评分标准,并用人工标注的示例来测试评判模型。Ori Eval 指南 涵盖了评估文件格式、candidateModels()、setupJudge()、--baseline 对比,以及在 CI 中运行评估。
常见问题
LLM-as-a-judge 是什么意思?
LLM-as-a-judge 是指用一个语言模型依据书面标准来评估另一个系统的输出。候选模型生成答案,另一个独立的评判模型对其打分。
如何自动为 AI 智能体的输出打分?
让智能体在一个测试提示词上运行,捕获它的回答以及相关的工具调用轨迹。将这些证据连同具体的评分标准交给评判模型,然后存储分数,当分数低于你根据人工审核样本校准的阈值时,判定该评估不通过。
LLM-as-a-judge 评估的准确度如何?
准确度取决于评判模型、评分标准、任务和测试数据。LLM 评判模型可以在相当可用的水平上与人类偏好保持一致,但它们也会表现出偏见和输出波动。在依赖评判模型做出发布决策之前,先在你自己的、带有人工标注的样本上测量一致性。
同一个 LLM 能评判自己的输出吗?
可以,但模型可能会偏袒自己的风格,或重复同样的盲点。尽可能使用一个独立的评判模型。如果必须使用同一个模型,请将评判请求单独分开,隐藏不必要的候选上下文,并对照人工标注来验证分数。
什么样的 LLM 评判评分标准才算好?
好的评分标准会列出可观察的证据,定义失败条件,并为评判者提供足够的上下文,使其能够做出与知识渊博的评审者相同的判断。把“有帮助”替换为诸如“说明 14 天窗口期且不得编造例外”这样的要求。
我应该使用逐点式还是成对式 LLM 评估?
当每次智能体运行都必须达到固定质量标准时,使用逐点式评估。在比较两个模型或提示词版本时,使用成对式评估。对于成对测试,反转答案顺序以检查位置是否影响结果。
我应该在什么时候避免使用 LLM 作为评判者?
当代码能够精确判定结果时,应避免使用它。Schema、计算、工具参数、权限以及关键的执行规则都应使用确定性检查。将评判者用于这些检查无法衡量的语义质量。
An agent can pass every deterministic test and still give a poor answer. A support agent can call the correct order lookup tool, retrieve the right policy, and then leave the refund window out of its response. The tool assertions pass, but nothing checked whether the final answer was accurate, complete, and useful.
LLM-as-a-judge evaluation covers that gap. A second model reviews the candidate agent’s output against criteria you write in plain language and returns a score. This gives you a repeatable way to test open-ended responses that have several valid wordings.
What LLM-as-a-judge is
You run a candidate, then give its output and any relevant tool results to a judge. The judge scores that evidence against a rubric you wrote. If the score falls below the threshold you set, the evaluation fails.

The judge is a model call like any other. It reads text, applies your criteria, and returns a number. Treat that number as a measurement taken with a fixed setup, not as ground truth.
Judge model vs candidate model
- The candidate is the system under test. It answers the user, calls tools, and writes the output you care about.
- The judge is a separate model. It does not solve the original task. It only grades what the candidate already did.
Keep those two roles on different models when you can. In the 2023 paper “Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena”, Zheng et al. identify self-enhancement, position, and verbosity biases. A judge may favor an answer it generated itself, the answer shown in a preferred position, or a longer answer regardless of its quality.
Give the judge the visible response and only the tool results it needs to apply the rubric. If the judge can see the candidate’s hidden reasoning, the grade stops being independent.
Rubric scoring vs exact match vs human review
Exact match checks a string or a structured field against a fixture. Use it when exactly one value is correct.
Between exact match and a full rubric sits a deterministic content check that asserts a required phrase appears. In Ori Eval, that is run.toMention(). It fits when the answer must contain a specific term even though the wording around it is free.
A rubric is a short set of rules a person could apply. “Cites the 14-day window and does not invent exceptions” is a rubric. “Sounds helpful” is not.
Human reviewers define the quality bar, but a person cannot grade every run of a large evaluation set, and two reviewers can reach different conclusions on the same output. A judge is a repeatable stand-in that you check against a small human-labeled set.
Pointwise, pairwise, and reference-based scoring
LLM judges are used in three evaluation modes:
| Mode | What the judge receives | When to use it |
|---|---|---|
| Pointwise | One candidate output and a rubric | Enforce a quality threshold in CI or monitor production samples |
| Pairwise | Two candidate outputs and a comparison rubric | Compare models, prompts, or agent versions |
| Reference-based | A candidate output, a rubric, and a trusted reference | Check factual coverage against a known-good answer or source |
This guide uses pointwise scoring, because each run either meets the required standard or falls below it. For pairwise evaluation, grade both answer orders to detect position bias. Reference-based evaluation works when the reference contains facts the response must preserve, rather than wording it must copy.
When to use an LLM judge
Use an LLM judge when the requirement is clear but not a single exact output. Examples:
- Grounded responses. Check that the final answer uses retrieved data and does not introduce unsupported claims.
- Instruction following. Verify that the response follows requirements such as citing a policy, asking for missing information, or avoiding an action.
- Completeness. Confirm that the agent covers every part of a multi-part request.
- Tone. Evaluate whether a response follows a defined support, legal, or brand voice.
- Tool-use outcomes. Judge whether the agent used tool results correctly after deterministic tests confirm which tools ran.
An LLM judge is a poor fit when the result can be checked directly. Use a schema validator for JSON structure, a calculator for arithmetic, and unit tests for tool arguments and side effects. Rules that must always block an action should stay deterministic. A judge can audit the quality of the final response, but it should not be the only enforcement layer for a critical policy.
A tool-calling test might assert that the agent called lookup_order once and never called issue_refund without approval. The judge then scores whether the agent’s final answer accurately explains what happened. If you still need to build the execution layer, start with our tool calling guide.
Score an agent with Ori Eval
Ori Eval runs evaluations against your own prompts and agent behavior. An eval is a TypeScript file that runs with Bun’s test runner. Ori resolves one harness and one model for a run and holds them for every test in that run, so a prompt cannot change the configuration mid-run. A model-comparison file can still start a separate run for each candidate model.
The quickest way to start is through your coding agent. Give it this instruction:
run curl -fsSL https://openrouter.ai/skills/spawn-ori-eval and follow the instructions in its output to get started The spawn-ori-eval skill installs Ori, makes sure you are signed in, asks what you want to evaluate, writes the eval, runs the candidate models, and recommends one with the scores, times, and costs behind the recommendation. It works in a temporary directory, so it does not add eval files to your project. Use the manual steps below when you want to keep the files in your project or inspect each part of the evaluation.
Ori’s setupJudge() function creates a separate grading agent on its own model, and autoEvals() scores a candidate run against your criteria. The example below tests a support agent that answers questions about refunds. It assumes your existing Ori harness can reach the support agent and its tools.
1. Install Ori and sign in
Install the Ori CLI, then authenticate once:
curl -fsSL https://openrouter.ai/labs/ori/install.sh | bash
ori Ori runs evaluation files with Bun. If Bun is not installed, ori eval asks for permission to install it. In CI or another noninteractive environment, the command stops and shows you how to install Bun. Your application does not need to be a TypeScript project.
2. Define one observable quality requirement
Begin with a failure you have seen or want to prevent. For this example, the agent must cite the 14-day refund window and must not invent policy exceptions.
That criterion is stronger than “give a helpful answer” because anyone can apply it without guessing what counts as helpful. It names both the required evidence and the failure condition.
3. Create the evaluation
Create evals/support/refund-quality.eval.ts:
import { test } from 'bun:test';
import { setupAgent, setupJudge } from 'ori/eval';
const agent = setupAgent();
const judge = setupJudge({ minScore: 0.8 });
test('explains the refund policy accurately', async () => {
const run = await agent.run('Can I refund a digital order that I placed 10 days ago?');
run.tool('lookup_refund_policy').toBeCalled();
run.toComplete();
await judge.autoEvals({
criteria:
'States the 14-day refund window, answers the question directly, and does not invent exceptions.',
run,
});
}); This test uses two evaluation layers. The run.tool() and run.toComplete() assertions check observable actions, and autoEvals() scores the meaning of the completed response. minScore sets the lowest score that passes. The 0.8 here is a starting value. Calibrate it against your own labeled responses, which the reliability section covers below.
setupJudge() grades with its own model, separate from the model under test. To grade with a different model, pass your own agent to setupJudge(). The Ori Eval docs show the call.
4. Run the evaluation
Run the test from your project directory:
ori eval --report eval-report.md Ori finds *.eval.ts files below the current directory, runs them with bun test, and exits with the exit code of bun test, so a failed evaluation fails the command. The --report flag writes a Markdown report you can review alongside the rest of your test output.
LLM evaluations make real model requests. Keep them in a separate CI job that runs manually, on a schedule, or before a release instead of adding them to every unit-test run. Store OPENROUTER_API_KEY as a repository secret. With that variable set, Ori does not need ori login in CI. The Run an eval in CI section of the Ori Eval docs includes a complete GitHub Actions example.
Compare the same agent across models
Once the pointwise evaluation works, you can run it against several candidate models. Keep the criteria and judge fixed while you do that. Passing { model } to setupAgent() selects the model for that run, so each iteration below runs its own model against the same criteria and judge.
import { test } from 'bun:test';
import { candidateModels, setupAgent, setupJudge } from 'ori/eval';
const judge = setupJudge({ minScore: 0.8 });
const candidates = await candidateModels({
limit: 5,
maxPromptPrice: 0.000005,
});
for (const model of candidates) {
test(`refund policy response on ${model}`, async () => {
const run = await setupAgent({ model }).run(
'Can I refund a digital order that I placed 10 days ago?',
);
await judge.autoEvals({
criteria:
'States the 14-day refund window, answers the question directly, and does not invent exceptions.',
run,
});
});
} candidateModels() returns model slugs from our live catalog, so each one drops into the test name and into setupAgent({ model }). You can filter candidates by prompt or completion price, context length, required parameters, input modalities, quality indexes, and whether a model is expiring. Prices are per token, so maxPromptPrice: 0.000005 is a ceiling of five dollars per million input tokens.
Dynamic selection is useful for discovering models. For regression tests, name the candidate model explicitly so the test does not compare a different set when the catalog changes, and use assertModelIsLive(slug) so the eval fails with a clear message if that model leaves the catalog. Record the candidate, judge, harness, rubric, model parameters, and test data with each result.
Make the judge reliable
Check the judge against examples a person has already labeled. Until you have done that, its scores are unproven. The rest of this section keeps that check valid as the setup changes.
Write criteria around observable evidence
Replace broad quality labels with requirements the judge can locate in the response.
- Weak. “The response is accurate and helpful.”
- Better. “The response states the 14-day refund window, uses the retrieved order date, and does not claim that the refund has already been issued.”
Keep unrelated dimensions separate when you need to diagnose failures. A single score for accuracy, tone, completeness, and formatting can tell you that quality dropped without telling you why.
Ori exports a startingCriteria object with editable rubrics for accuracy, completeness, instructionFollowing, safety, structuredOutput, and toneAndVoice. Pass one to judge.autoEvals() as the criteria value. Treat them as a base to specialize. “Uses the retrieved order status and does not promise a refund before approval” tells the judge more than a generic accuracy rubric.
Calibrate the judge with human-labeled examples
Create a small dataset containing clear passes, clear failures, and borderline cases from realistic agent interactions. Ask the people responsible for quality to score them first, then compare the judge’s decisions with those labels.
When the judge disagrees, inspect the cause. The rubric may be vague, the example may expose a missing criterion, or the judge model may be a poor fit. Repeat this calibration when you change the judge, rubric, or evaluation data.
Put your labeled question-and-answer pairs in a JSON file and drive them with test.each:
import supportPairs from './support-pairs.json';
test.each(supportPairs)('answers: $question', async ({ question, mustMention }) => {
const run = await agent.run(question);
run.toMention(mustMention);
run.toComplete();
}); Keep the evaluation blind
Give the judge only the information required to apply the rubric. That is the original task, the visible answer, relevant tool results, and any trusted reference material. Remove the candidate model name and other signals that could influence the score.
For pairwise evaluations, run the comparison twice with the answers in opposite positions. If the outcome changes, check the result again rather than forcing a winner.
Control changes and account for variance
Save the exact rubric and test dataset in version control. Record the candidate and judge model slugs, harness version, routing configuration, and generation settings with the score.
This makes changes traceable, but it does not make model output deterministic. A small score movement near the threshold may be normal variation. A repeated drop across a representative test set is stronger evidence of a regression.
Protect production data
Real data from your users makes better test cases than prompts you invent. Remove personal or sensitive data before adding production traces to an evaluation dataset, and review the data policies for the models and providers involved. Our data collection documentation explains our logging controls and how we handle request metadata.
Manage evaluation cost
LLM judging adds model requests to every evaluated run, so the cost grows with the number of test cases, candidate models, and rubric dimensions.
You can control that cost by:
- Running deterministic checks on every commit and LLM evaluations on a schedule or before a release.
- Sampling representative production traces instead of scoring every interaction.
- Using one focused judge call instead of several overlapping criteria.
- Testing a smaller candidate set during routine regression checks.
- Sending only the context the judge needs to apply the rubric.
The judge does not need to be the largest model available. It needs to follow detailed scoring instructions consistently. Use our model catalog to compare current capabilities and prices rather than copying a fixed price into the evaluation.
Next steps
Start with one real failure, write a criterion another reviewer can apply, and test the judge against human-labeled examples. The Ori Eval guide covers the eval file format, candidateModels(), setupJudge(), --baseline comparisons, and running evals in CI.
Frequently asked questions
What does LLM-as-a-judge mean?
LLM-as-a-judge means using one language model to evaluate another system’s output against written criteria. The candidate produces the answer, and a separate judge model scores it.
How do you score AI agent outputs automatically?
Run the agent on a test prompt and capture its answer and the relevant tool trace. Give that evidence to a judge model with a specific rubric, then store the score and fail the evaluation when it falls below a threshold you calibrated against human-reviewed examples.
How accurate is LLM-as-a-judge evaluation?
Accuracy depends on the judge model, rubric, task, and test data. LLM judges can agree with human preferences at useful rates, but they also show biases and output variance. Measure agreement on your own human-labeled examples before relying on a judge for release decisions.
Can the same LLM judge its own output?
It can, but the model may favor its own style or repeat the same blind spots. Use a separate judge model when possible. If you must use the same model, keep the judge request separate, hide unnecessary candidate context, and validate the scores against human labels.
What makes a good LLM judge rubric?
A good rubric names observable evidence, defines the failure conditions, and gives the judge enough context to reach the same decision as a knowledgeable reviewer. Replace “be helpful” with requirements such as “states the 14-day window and does not invent an exception”.
Should I use pointwise or pairwise LLM evaluation?
Use pointwise evaluation when each agent run must meet a fixed quality bar. Use pairwise evaluation when comparing two models or prompt versions. For pairwise tests, reverse the answer order to check whether position affects the result.
When should I avoid using an LLM as a judge?
Avoid it when code can determine the result exactly. Schemas, calculations, tool arguments, permissions, and critical enforcement rules should use deterministic checks. Use the judge for semantic qualities that those checks cannot measure.