API reference
APIs
Eval() Quickstart
The fastest, most opinionated API. Perfect for simple cases.
def Eval(
name: str,
data: list[dict] | Callable[[], list[dict]],
task: Callable[[Any], str],
scores: list[Callable],
threshold: float = 1.0,
) -> EvalResult
Parameters:
| Parameter | Type | Description |
|---|---|---|
| name | str | Eval name (appears in output) |
| data | list[dict] or callable | Test data with "input"/"expected" keys, or callable that returns it |
| task | callable | Function under test; called with each row's input value, returns the output |
| scores | list[callable] | Scorer functions; each returns 0-1 or bool |
| threshold | float | Min score for a case to pass (default 1.0) |
Built-in scorers for Eval():
equals— Exact matchcontains— Case-sensitive substringicontains— Case-insensitive substringlevenshtein— Similarity (0-1)matches— Regex matchnumeric_close— 1% relative tolerance
TestSuite API
More structured, trace-aware evaluation with custom expectations.
def evaluate_suite(
suite: TestSuite,
samples: list[EvaluationSample],
registry: EvaluatorRegistry | None = None,
) -> EvaluationReport
Returns a full EvaluationReport with per-case scores, summary metrics, pass rates, cost/latency, and breakdowns by metric and tag.
Scorers Library
Pre-built evaluators organized by type:
Text Scorers (No LLM)
from agentic_evals import scorers
# Deterministic checks
scorer = scorers.text.exact_match
scorer = scorers.text.levenshtein_similarity
scorer = scorers.text.valid_json
scorer = scorers.text.json_diff
scorer = scorers.text.regex_match
Rubric Scorers (LLM-Graded)
from agentic_evals import LLMRubricEvaluator, FACTUALITY, default_registry
# Register an LLM rubric evaluator
registry = default_registry()
registry.register(
LLMRubricEvaluator(
"factuality_check",
FACTUALITY,
complete_fn=your_model_call, # Your function to call LLM
)
)
When no built-in template fits, describe the criterion in plain language. make_rubric() builds the prompt, the verdict letters and their scores:
from agentic_evals import LLMRubricEvaluator, make_rubric
concise = make_rubric("concise", "The answer is at most two sentences and has no preamble.")
tone = make_rubric(
"tone",
"The reply is courteous and does not blame the reader.",
levels=[ # best first; scores from 0 to 1
("Courteous throughout.", 1.0),
("Neutral: neither courteous nor rude.", 0.5),
("Rude, dismissive, or blames the reader.", 0.0),
],
)
registry.register(LLMRubricEvaluator("concise", concise, complete_fn=your_model_call))
registry.register(LLMRubricEvaluator("tone", tone, complete_fn=your_model_call))
The default scale is pass/fail. Pass with_reference=True to show the judge a reference next to the output.
Trajectory Scorers (Trace-Aware)
from agentic_evals import scorers
scorer = scorers.trajectory.tool_call_precision
scorer = scorers.trajectory.tool_call_recall
scorer = scorers.trajectory.no_redundant_tool_calls
scorer = scorers.trajectory.trajectory_efficiency
Release Gates
Turn an evaluation report into a pass/fail CI decision:
def evaluate_gate(
report: EvaluationReport,
config: GateConfig,
) -> GateDecision
from agentic_evals import evaluate_gate, GateConfig
decision = evaluate_gate(
report,
GateConfig(
min_pass_rate=0.95, # At least 95% of cases pass
max_average_latency_ms=1500, # Avg latency under 1.5s
max_total_cost_usd=0.25, # Total cost under $0.25
),
)
if not decision.passed:
print(f"Release blocked: {decision.reasons}")
exit(1)
A gate can hold one slice of the report to a stricter bar than the suite as a whole, keyed by case tag or by Score.metric:
GateConfig(
min_pass_rate=0.95,
min_tag_pass_rate={"safety": 1.0}, # Every safety-tagged case passes
min_metric_pass_rate={"forbidden_tool": 1.0}, # No forbidden tool call, anywhere
)
A tag or metric named in the config but missing from the report fails the gate, so a renamed tag cannot quietly switch a check off.
Since 0.9.0 the gate also reads judge and live-target outcomes. A judge that never delivered a verdict fails the default gate (max_judge_unavailable_scores=0):
GateConfig(
min_judge_agreement=0.8, # every case judged with samples=N
max_judge_cost_usd=2.50, # fails when any judge score has no cost
max_timed_out_cases=0, # live runs: timeouts, apart from wrong answers
)
Live Targets
Run a suite against a real system (trusted code or HTTP endpoint) instead of pre-recorded samples:
def run_live_suite(
suite: TestSuite,
target: LiveTarget,
*,
registry: EvaluatorRegistry | None = None,
trace_adapter: TraceAdapter | None = None,
max_workers: int = 1,
retry: RetryPolicy | None = None,
) -> EvaluationReport
Python Target (executes local code):
from agentic_evals import PythonTarget, run_live_suite
report = run_live_suite(
suite,
PythonTarget(callable_path="my_module:my_agent"),
# my_module.py must have a my_agent(input, case=None) function
)
HTTP Target (calls a remote endpoint):
from agentic_evals import HTTPTarget, run_live_suite
report = run_live_suite(
suite,
HTTPTarget(
url="http://localhost:8000/evaluate",
method="POST",
headers={"Authorization": "Bearer token"},
),
)
Retries, timeouts and async (0.9.0): a call that raises or times out is retried under retry; a case whose calls all fail is reported with target_status "timed_out" or "error" instead of aborting the run. arun_live_suite awaits async def targets and cancels them at an explicit timeout_seconds.
import asyncio
from agentic_evals import PythonTarget, RetryPolicy, arun_live_suite
report = asyncio.run(
arun_live_suite(
suite,
PythonTarget(callable_path="my_module:my_async_agent", timeout_seconds=20),
retry=RetryPolicy(max_attempts=3, backoff_seconds=1),
max_concurrency=4,
)
)
print(report.summary.live.timed_out_case_ids)