Skip to main content

ExperimentConfig

AgentInvoker

Single-method interface — implement this to plug in any agent:
Contract:
  • Blocking: returns when agent completes, times out, or fails
  • Thread-safe: callable from multiple threads
  • NOT responsible for: timeout enforcement, workspace setup, result tracking

Template Invokers

The agent-experiment-template provides a hierarchy of ready-made invokers. Choose based on your orchestration needs:
ClassExtendsUse When
TemplateAgentInvokerAbstractTemplateAgentInvokerSingle-phase agent via AgentClient (rename to {Domain}AgentInvoker)
TwoPhaseTemplateAgentInvokerAbstractTemplateAgentInvokerTwo-phase explore + act via ClaudeSyncClient
WorkflowAgentInvokerAbstractTemplateAgentInvokerSingle-step workflow — simplest workflow entry point
WorkflowInvoker<S>AgentInvoker (direct)Multi-step typed workflow with cost tracking
AbstractTemplateAgentInvoker provides:
  • Pre/post invoke hooks (preInvoke, postInvoke)
  • Knowledge file injection into workspaces
  • Phase capture collection
WorkflowAgentInvoker wraps a single ClaudeStep in a Workflow with journal integration wired automatically — step events are recorded as WorkflowStepEvent entries via WorkflowJournal. The experiment name is pulled from context.metadata("experimentId"). WorkflowInvoker<S> is the base for multi-step workflows with typed state. Journal and cost tracking are built in. Subclasses implement three methods:

InvocationContext

What the runner passes to your agent:
FieldTypeDescription
workspacePathPathDirectory where agent operates
promptStringFully constructed prompt
systemPromptStringOptional additional system instructions
modelStringModel identifier
timeoutDurationTimeout hint
metadataMapPass-through (experimentId, itemId, etc.)
runDirPathOptional directory for trace artifacts

InvocationResult

What your agent returns:
FieldTypeDescription
successbooleanAgent completed without error
statusTerminalStatusCOMPLETED, ERROR, TIMEOUT
inputTokensintTotal input tokens consumed
outputTokensintTotal output tokens produced
totalCostUsddoubleEstimated cost
durationMslongWall-clock execution time

ExecutionDetail

Marker interface that decouples shared experiment infrastructure (ComparisonEngine, ResultStore, VerdictExtractor) from domain-specific per-item execution details.
ImplementationUsed ByContains
InvocationResultAgentExperimentAgent invocation output, tokens, cost, phases
JudgeExecutionDetailJudgeExperimentCandidate judgment, expected label, scorer result
ItemResult.executionDetail() returns @Nullable ExecutionDetail. Consumers use instanceof pattern matching to access domain-specific fields:

Dataset Format

dataset.json

item.json

Directory layout

ItemFilter

ResultStore

ImplementationUse case
FileSystemResultStore(path)Production — persists to disk
InMemoryResultStore()Testing — HashMap-backed
Both implement:

ExperimentResult

MethodTypeDescription
experimentId()StringUnique run ID
experimentName()StringExperiment name from config
items()List<ItemResult>Per-item results
passCount()intItems that passed all judges
failCount()intItems that failed
passRate()doublePass count / total (0.0–1.0)

Re-Evaluation

Re-evaluate stored experiment results with a different jury without re-invoking the system under test.

ReEvaluationContextFactory

Functional interface that reconstructs a JudgmentContext from a stored ItemResult:
Returns Optional.empty() when re-evaluation is not possible (failed item, missing execution detail, workspace not preserved).

AgentReEvaluationContextFactory

Default implementation for agent experiment results. Pattern-matches on InvocationResult to reconstruct the context:
Maps TerminalStatus to ExecutionStatus (COMPLETED → SUCCESS, TIMEOUT → TIMEOUT, ERROR → FAILED). Preserves original costUsd and totalTokens.

ReEvaluator

Orchestrates post-hoc re-scoring of stored experiment results:
MethodDescription
reEvaluate(ExperimentResult, Jury)Re-score a loaded result with a new jury
reEvaluate(String experimentId, Jury)Load by ID, then re-score
agentDefaults(ResultStore)Convenience factory with AgentReEvaluationContextFactory
Re-evaluated results carry metadata: reEvaluated=true, systemReinvoked=false, originalCostUsd, reEvaluationJury, originalTimestamp. Skipped items carry reEvaluationSkipped=true with a reason.

Judge Experiment

Run a judge as the system under test against a labeled dataset to measure agreement rate.

JudgeScorer

Functional interface that scores a candidate judge’s Judgment against the expected label:

JudgeScoringInput

JudgeScorerResult

JudgeScorers

Built-in scoring implementations:
Factory MethodScoring Rule
exactVerdictMatch()PASS/FAIL must exactly match expected "PASS"/"FAIL" label
exactCategoryMatch()CategoricalScore value must match expected label (case-insensitive)
numericalTolerance(double)NumericalScore within tolerance of expected numeric value

JudgeExecutionDetail

Domain evidence preserved for each item:

JudgeExperiment

Builder-based experiment runner where the system under test is a Judge:
Builder MethodRequiredDescription
name(String)YesExperiment name
candidate(Judge)YesJudge to evaluate
items(List<DatasetItem>)YesLabeled dataset items
input(Function<DatasetItem, JudgmentContext>)YesBuilds context from item
expected(Function<DatasetItem, String>)YesExtracts expected label from item
scorer(JudgeScorer)YesScoring strategy
resultStore(ResultStore)YesPersistence
datasetVersion(String)NoDefaults to "1.0.0"
Takes List<DatasetItem> directly — judge datasets do not require filesystem loading.

JudgeExperimentResult

MethodDescription
agreementRate()Fraction of items where judge agreed with expected label
disagreements()Items where judge disagreed
from(ExperimentResult)Create from an ExperimentResult containing JudgeExecutionDetail items
asExperimentResult()Unwrap for ComparisonEngine and ResultStore compatibility

JudgeDisagreement


Modules