What Youโll Build
A progression of custom judges: a lambda check, a reusable deterministic judge, a composed AI judge, an LLM judge with full control, and a RAG-specific judge. Youโll wire them into a jury alongside built-in judges. This tutorial builds on Build an Evaluation Pipeline. You should be comfortable withJudgmentContext, Judgment, and SimpleJury before starting.
Step 1: Lambda Judge
The simplest custom judge is a lambda โ three lines:Judge is a @FunctionalInterface with a single method: judge(JudgmentContext) -> Judgment.
Any lambda or method reference that matches this signature is a judge.
Lambda judges work well for one-off checks.
For production judges, extend a base class to get metadata and structured checks.
Step 2: Extend DeterministicJudge
For a judge youโll reuse, extendDeterministicJudge.
It implements JudgeWithMetadata so infrastructure code (logging, metrics, verdict reporting) can discover the judgeโs name and type.
- Constructor calls
super(name, description)โ this becomesmetadata()for logging and verdicts - Checks provide granular sub-assertions โ on failure, you can distinguish โfile not foundโ from โfile found but annotation missingโ
Judgment.error()handles unexpected failures without crashing the jury
Step 3: Add Metadata to Lambda Judges
If you prefer lambdas but still want metadata, useJudges.named():
Step 4: Build an AI Judge with ModelBackedJudge
For semantic criteria that canโt be checked from files or commands, you need an AI-backed judge.ModelBackedJudge composes three parts โ a prompt template, a model backend, and a response classifier โ into a judge without subclassing.
Available template variables:
{{goal}}, {{output}}, {{workspace}}, {{status}}, {{metadata.*}}.
ModelBackedJudge lives in the agent-judge-ai-core module, which has zero external dependencies.
The actual AI backend arrives through a JudgeModel implementation from a bridge module (agent-judge-llm or agent-judge-agent-client).
Use
ModelBackedJudge as the default. Reach for LLMJudge when you need full control over prompt construction or response parsing.
Step 5: Write a Custom LLM Judge
For full control over prompt construction and response parsing, extendLLMJudge.
It uses the template method pattern โ you implement two methods:
buildPrompt()โ construct the evaluation prompt from the contextparseResponse()โ parse the LLMโs response into aJudgment
LLM judges require the
agent-judge-llm module and Spring AI.
Always handle parse failures gracefully โ Judgment.error() prevents one broken response from crashing the jury.Prefer deterministic judges when the criterion can be checked from files, commands, or structured metadata. Use LLM judges when the criterion is semantic and cannot be expressed reliably as code.
Step 6: Wire Custom Judges into a Jury
Combine your custom judges with built-in ones:WeightedAverageStrategy normalizes all scores to [0, 1] and computes a weighted average.
Build success (weight 2.0) matters more than file existence (weight 1.0), and quality (weight 1.5) falls in between.
Step 7: Write a Custom RAG Judge
RAG judges follow the sameLLMJudge pattern but use the RagContext helper to extract the (question, context, answer) triple from metadata.
Hereโs a custom judge that evaluates answer completeness โ did the answer address all parts of the question?
- Use
RagContext.question(),RagContext.context(),RagContext.answer()to extract the triple - Return
ABSTAINwhen required inputs are missing โ this prevents misleading verdicts - Use the
(?mi)^\s*Answer:\s*(YES|NO)regex pattern for reliable LLM response parsing
RagContext.question() falls back to context.goal() and RagContext.answer() falls back to context.agentOutput(), but the explicit metadata keys are the recommended convention. LangChain4jโs sources are also available as a fallback for RagContext.context().
What You Built
The progression: lambda (quick checks) -> DeterministicJudge (production checks with metadata and sub-assertions) -> ModelBackedJudge (composed AI judge, no subclassing) -> LLMJudge (full control over prompt and parsing) -> RAG judge (LLMJudge with the
RagContext metadata convention).
Whatโs Next
Built-in Judges
Catalog of built-in judges โ see whatโs already available before writing custom judges
Jury System
CascadedJury for tiered evaluation, voting strategy configuration