The vitest-evals library uses an explicit-run pattern for AI evaluations. This pattern binds a suite-level harness to a set of tests, allowing for structured LLM-based grading (judges).
Core Components
describeEval: Binds a suite-level harness (which manages the agent/app execution) and judges (which grade the results). It also accepts a judgeThreshold.run(input): Inside a test, you call run to execute the harness with the provided input. This returns the result of the agent/app execution.- Judges: Every judge is a named object with an
assess(ctx) method. They receive a JudgeContext containing the input, output, normalized run/session, and tool calls. toSatisfyJudge: A Vitest matcher used to assert that a result meets a specific judge's criteria.
Example Usage
import { describeEval, FactualityJudge, toolCalls } from "vitest-evals";
import { piAiHarness, piAiJudgeHarness } from "@vitest-evals/harness-pi-ai";
// 1. Setup a dedicated judge harness (the model used for grading)
const judgeHarness = piAiJudgeHarness({
model: getModel("anthropic", "claude-sonnet-4-5"),
temperature: 0,
});
// 2. Create a judge instance
const factualityJudge = FactualityJudge({ judgeHarness });
// 3. Define the eval suite
describeEval(
"my eval suite",
{
harness: piAiHarness({ agent: () => myAgent }),
judges: [factualityJudge],
judgeThreshold: 0.6,
},
(it) => {
it("passes a test", async ({ input }, { run }) => {
const result = await run(input);
// Assertions on structure/tools
expect(toolCalls(result)).toBeDefined();
// Assertions via the judge
await expect(result).toSatisfyJudge(factualityJudge, {
expected: "The agent should be polite",
threshold: 0.6,
});
});
},
);
import { getModel } from "@mariozechner/pi-ai";
import { expect } from "vitest";
import { piAiHarness, piAiJudgeHarness } from "@vitest-evals/harness-pi-ai";
import {
describeEval,
FactualityJudge,
toolCalls,
} from "vitest-evals";
import { createRefundAgent } from "../src/refundAgent";
const judgeHarness = piAiJudgeHarness({
model: getModel("anthropic", "claude-sonnet-4-5"),
temperature: 0,
});
const factualityJudge = FactualityJudge({ judgeHarness });
describeEval(
"demo pi refund agent",
{
harness: piAiHarness({
agent: () => createRefundAgent(),
}),
judges: [factualityJudge],
judgeThreshold: 0.6,
},
(it) => {
it.for([
{
name: "approves refundable invoice",
input: "Refund invoice inv_123",
expected: "The refund request is approved.",
expectedStatus: "approved",
expectedTools: ["lookupInvoice", "createRefund"],
},
])("$name", async ({ input, ...expected }, { run }) => {
const result = await run(input);
expect(result.output).toMatchObject({
status: expected.expectedStatus,
});
expect(toolCalls(result).map((call) => call.name)).toEqual(
expected.expectedTools,
);
await expect(result).toSatisfyJudge(factualityJudge, {
expected: expected.expected,
threshold: 0.6,
});
});
},
);