Skip to main content

Statistical regression testing for LLM agents. Get a p-value on whether behavior actually shifted between versions, not just whether one run looked different. Apache 2.0, self-hostable, no SaaS dependency -- a Promptfoo alternative for the statistical testing gap threshold-based eval tools don't cover.

Project description

Agent Evaluation

Statistical regression testing for LLM agents. Run your agent 50 times on a fixed test suite at version A, 50 times at version B, and get a p-value on whether behavior actually changed, not just whether the score looks different.

agent-eval running the basic-comparison example and reporting a REGRESSED verdict with p-value, Cohen's d, and a 95% confidence interval

PyPI npm License: Apache 2.0 CI

OpenSSF Scorecard


Install

pip install agent-regress-cli
# or
uv add agent-regress-cli

Prefer Node/npx? A thin CLI wrapper is also published as agent-regress-npm-cli on npm (it shells out to this same Python package, so Python still needs to be installed):

npx agent-regress-npm-cli --help

The problem this solves

You changed a prompt. Or switched from GPT-4o to GPT-4o-mini to cut costs. Or a dependency updated silently. Your evals still pass, because they test individual responses against fixed thresholds. They don't detect whether behavior shifted across the whole distribution.

A 3-point drop in accuracy might be noise from LLM variance. Or it might be a real regression. Without statistical testing you cannot tell which. Teams either ignore small drops and miss real problems, or escalate everything and drown in false alarms.

Agent Evaluation answers the distributional question with a p-value and effect size:

============================================================
agent-regress Report -- tool_accuracy
============================================================
Verdict:    REGRESSED
p-value:    0.0031
Cohen's d:  -0.610
95% CI:     [-0.221, -0.067]

Version A:  0.8400 +/- 0.0601  (n=50)
Version B:  0.7000 +/- 0.0903  (n=50)
Delta:      -0.1400
============================================================

When CI fails, the assertion error gives the deploy-blocking message:

AssertionError: REGRESSED: tool_accuracy dropped 16.7%
(p=0.003, Cohen's d=-0.61, 95% CI [-0.22, -0.07])
Version A: 0.840 +/- 0.060  (n=50)
Version B: 0.700 +/- 0.090  (n=50)

When nothing changed:

Verdict:    STABLE
p-value:    0.4100
Cohen's d:  0.021

DeepEval, Promptfoo, and Braintrust test whether individual responses meet thresholds. None of them answer whether a version's behavior distribution shifted significantly from the last. Agent Evaluation addresses that specific statistical question, which threshold testing cannot answer.


Quickstart

from agent_regress import compare

# Any callable that takes a test case dict and returns a score 0.0-1.0
def agent_v1(test_case: dict) -> float:
    ...  # your existing agent

def agent_v2(test_case: dict) -> float:
    ...  # your updated agent

test_suite = [
    {"query": "find SKU for order 8823", "expected": "SKU-4492"},
    # ... more test cases
]

report = compare(
    version_a=agent_v1,
    version_b=agent_v2,
    test_suite=test_suite,
    n_runs=50,
    metric="tool_accuracy",  # use any name except "accuracy" when agents return floats
)

print(report)           # structured output with p-value, CI, effect size
report.assert_stable()  # raises AssertionError if behavior regressed

Agent returns text? Pass a scorer or use the built-ins:

from agent_regress import compare, exact_match_scorer, f1_scorer

# exact_match_scorer: 1.0 if str(output).strip() == str(expected).strip()
# f1_scorer: token-level F1 (multiset — handles repeated tokens correctly)
report = compare(
    version_a=agent_v1,
    version_b=agent_v2,
    test_suite=test_suite,
    n_runs=50,
    scorer=exact_match_scorer,  # test_case must have an "expected" key
)

Or write your own:

def my_scorer(output: str, test_case: dict) -> float:
    return 1.0 if output.strip() == test_case["expected"] else 0.0

report = compare(..., scorer=my_scorer)

Add to CI: fail the build on regression

Two patterns. Pick one.

report.assert_stable() — inline, after you've already called compare():

# test_regression.py -- add to your existing test suite
from agent_regress import compare

def test_no_regression():
    report = compare(
        version_a=production_agent,
        version_b=staging_agent,
        test_suite=load_test_suite(),
        n_runs=50,
    )
    report.assert_stable(
        p_threshold=0.05,  # act on changes at p < 0.05
        min_effect=0.2,    # Cohen's d threshold -- ignore noise below 0.2
    )

RegressionGate — reusable gate object, useful when you run multiple comparisons with the same thresholds:

from agent_regress import compare, RegressionGate

gate = RegressionGate(p_threshold=0.05, min_effect=0.2)

def test_tool_accuracy():
    report = compare(version_a=prod, version_b=staging, test_suite=suite, n_runs=50)
    gate.check(report)  # raises AssertionError on regression; warns if n < 30

def test_routing_accuracy():
    report = compare(version_a=prod, version_b=staging, test_suite=routing_suite, n_runs=50)
    gate.check(report)

Both patterns: warn (not fail) when n < 30 per version; treat n < 10 as insufficient data and skip the gate.

uv run pytest test_regression.py

How it differs from the alternatives

Capability Agent Evaluation DeepEval Braintrust Promptfoo
Statistical version comparison (p-values) Yes No No No
Effect size reporting (Cohen's d) Yes No No No
Bootstrap 95% confidence intervals Yes No No No
Distributional shift detection Yes No No No
Tau-bench pass^k harness (k=1,4,8) Yes No No No
GAIA Level 1-3 split harness Yes No No No
SWE-bench scaffold score harness Yes No No No
Self-hostable, zero SaaS required Yes Partial No Yes
Sample size warnings (n < 30) Yes No No No
Core license Apache 2.0 MIT Proprietary MIT†
Requires cloud account No Optional Yes No
Test type Distributional Threshold Threshold Threshold

†Promptfoo acquired by OpenAI, March 2026.

DeepEval tests whether an individual agent response clears a quality bar. Agent Evaluation tests whether behavior changed significantly between two agent versions, a different statistical question that threshold testing cannot answer. The scipy Mann-Whitney U call at the core is one line, so any SaaS eval platform can add it. What accumulates over time through production use is version-specific regression history and a community-maintained benchmark leaderboard with independent result verification.


Statistical methods

Agent Evaluation uses three statistical tests, applied in combination:

Mann-Whitney U compares two score distributions without assuming normality. LLM scores are not Gaussian. The U test is distribution-free and robust to the long tails and bimodal distributions that appear in real agent outputs.

Bootstrap confidence intervals (1,000 resamples, seed=42) give a 95% CI on the mean score delta. The CI tells you how large the shift was: a CI of [-0.22, -0.07] means you can be 95% confident the true per-run accuracy drop is between 7 and 22 percentage points.

Cohen's d (pooled standard deviation) separates statistical significance from operational significance. A shift at p=0.001 with d=0.04 is real but meaningless. A shift at p=0.06 with d=0.5 is operationally large but requires more data to confirm. The default CI gate acts only when both p < 0.05 and d >= 0.2.

See docs/statistical-methods.md for the full methodology.


Benchmarks

Statistical test overhead is the time to run the comparison itself, not the agent calls. Agent calls are the bottleneck; the statistics are not.

Measured on Apple M3 Pro, Python 3.14, scipy 1.15, numpy 2.2:

Operation n=50 per version n=1,000 per version
Mann-Whitney U 0.34ms 0.47ms
Bootstrap CI (1,000 resamples) 26ms 31ms
Full compare() statistical overhead ~27ms ~32ms

See docs/benchmarks.md to reproduce.


Integration matrix

Framework Status Install
LangGraph Shipped (v0.1) pip install agent-regress-cli[langgraph]
OpenAI Agents SDK Shipped (v0.1) pip install agent-regress-cli[openai-agents]
CrewAI Shipped (v0.1) pip install agent-regress-cli[crewai]
LangChain LCEL Shipped (v0.1) pip install agent-regress-cli[langchain]
AutoGen Planned (v0.3)
Vercel AI SDK (TypeScript) Planned (v0.4)

Comparing two installed versions of the same framework (rather than two in-process configurations)? See docs/cross-version-comparison.md for the subprocess_runner() pattern.


Standard benchmarks

Agent Evaluation ships harnesses for the three standard agent benchmarks:

Tau-bench pass^k measures reliability across k independent attempts. Single-run benchmarks miss degradation: an agent that succeeds 60% of the time at k=1 reaches 99.93% at k=8. The k=1 vs k=8 curve is the signal.

from agent_regress.benchmarks.tau_bench import TauBenchHarness

harness = TauBenchHarness(agent=my_agent, dataset=tau_bench_dataset)
results = harness.evaluate(k_values=[1, 4, 8])

GAIA Level 1-3 split stratifies by task difficulty. Overall accuracy hides per-difficulty regressions: a prompt change that helps Level 1 often hurts Level 3.

from agent_regress.benchmarks.gaia import GAIAHarness

harness = GAIAHarness(agent=my_agent, dataset=gaia_dataset)
results = harness.evaluate()  # returns list[GAIALevelResult], one per level
for r in results:
    print(f"Level {r.level}: {r.accuracy:.3f}  ({r.n_correct}/{r.n_questions})")

SWE-bench scaffold score isolates framework contribution from model contribution.

from agent_regress.benchmarks.swebench import SWEBenchHarness

harness = SWEBenchHarness(agent=my_agent, dataset=swe_dataset)
result = harness.evaluate()
print(f"scaffold pass rate: {result.scaffold_pass_rate:.3f}  ({result.n_resolved}/{result.n_instances})")

See leaderboard/README.md to submit results.


Try it in Docker

git clone https://github.com/RudrenduPaul/agent-eval
cd agent-eval
docker compose up

Starts two services:

  • web (http://localhost:8080) — leaderboard UI served by web/serve.py, reading leaderboard/results/*.json
  • example — runs examples/01-basic-comparison/example.py and prints the comparison report to stdout

Good for verifying the install works and seeing the leaderboard UI before wiring agent-regress into your own agent.


Security

  • Supply chain: SLSA Level 2 via GitHub Actions provenance. All releases signed with Sigstore. SBOM attached to every GitHub Release.
  • Vulnerability scanning: Trivy scans on every CI run (HIGH/CRITICAL only, exit on unfixed). CodeQL static analysis on every push.
  • Dependency pinning: Dependabot keeps all GitHub Actions and Python dependencies current.
  • Disclosure: SECURITY.md — report vulnerabilities privately via GitHub Security Advisories.

Leaderboard

The leaderboard/ directory version-controls Tau-bench pass^k, GAIA, and SWE-bench results across models and frameworks. Submit by opening a PR with a JSON file matching leaderboard/schema.json. Results are independently reproduced before merging.

See leaderboard/README.md.


FAQ

What is agent-eval, and what makes it different from a normal LLM eval framework?

Agent Evaluation is a statistics library for detecting whether an agent's behavior actually changed between two versions. Run the same test suite 50 times on version A and 50 times on version B, and it reports a p-value (Mann-Whitney U), an effect size (Cohen's d), and a bootstrap 95% confidence interval on the score delta. Most eval frameworks check whether a single response clears a fixed quality threshold. Agent Evaluation instead answers a distributional question: did the score distribution shift significantly, or is a change just LLM-run-to-run noise.

How do I install it, and which platforms does it support?

pip install agent-regress-cli or uv add agent-regress-cli. It requires Python 3.10 through 3.13 (per the classifiers in pyproject.toml) and has no OS-specific code, so it runs anywhere those Python versions run. Node users can call npx agent-regress-npm-cli --help, a thin wrapper that shells out to this same Python package, so Python still needs to be installed alongside Node.

How does it compare to DeepEval, Promptfoo, or Braintrust?

The full breakdown is in the comparison table above. In short: DeepEval, Promptfoo, and Braintrust all test whether an individual response clears a fixed quality bar. None of the three report a p-value, an effect size, or a bootstrap confidence interval on whether behavior shifted between two versions, which is the specific statistical question agent-eval is built to answer.

I ran a comparison and got a warning about insufficient statistical power, or a verdict of INSUFFICIENT_DATA. What does that mean?

The library warns (but does not fail) when either version has fewer than 50 runs, since that is the sample size needed for reliable detection of a moderate effect (Cohen's d of 0.2) at 80% power. Below 10 runs per version, it returns INSUFFICIENT_DATA instead of a REGRESSED/STABLE/IMPROVED verdict, since the sample is too small to trust any statistical conclusion. Re-run with n_runs=50 or higher for a verdict you can act on.

Does agent-eval call my LLM or manage API keys for me?

No. compare() takes two callables you provide, version_a and version_b, and runs your existing agent code against your test suite. Agent Evaluation never makes a model call itself, and the stats module (src/agent_regress/stats/) is required to stay pure Python and scipy with no LLM calls, so the statistical core has no network dependency and nothing to configure credentials for.

Which agent frameworks does it integrate with today?

LangGraph, the OpenAI Agents SDK, CrewAI, and LangChain LCEL are shipped as of v0.1 (see the integration matrix above), each installable as an extra, e.g. pip install agent-regress-cli[langgraph]. AutoGen and a Vercel AI SDK (TypeScript) integration are planned but not yet shipped.

Can I use agent-eval commercially, and what license is it under?

Yes. It is licensed under Apache License 2.0, which permits commercial use, modification, and distribution, and includes an explicit patent grant. You need to preserve the copyright and license notices and state any changes you make; there is no warranty. See LICENSE for the full text.


Contributing

  • Read CONTRIBUTING.md before opening a PR
  • Good first issues are labeled in GitHub
  • Stats module (src/agent_regress/stats/) must stay pure Python + scipy — no LLM calls, ever
  • All PRs require 95% coverage on stats/, 80% overall

GitHub Discussions for design questions.

Apache 2.0. Contributions welcome.


Cite this work

If you use Agent Evaluation in research, please cite:

@software{paul2026agenteval,
  author = {Paul, Rudrendu and Nandy, Sourav},
  title = {Agent Evaluation: Statistical Regression Testing for LLM Agents},
  year = {2026},
  url = {https://github.com/RudrenduPaul/agent-eval},
  license = {Apache-2.0}
}

Built by Rudrendu Paul and Sourav Nandy

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agent_regress_cli-0.1.4.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agent_regress_cli-0.1.4-py3-none-any.whl (56.8 kB view details)

Uploaded Python 3

File details

Details for the file agent_regress_cli-0.1.4.tar.gz.

File metadata

  • Download URL: agent_regress_cli-0.1.4.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for agent_regress_cli-0.1.4.tar.gz
Algorithm Hash digest
SHA256 3b6f583d60bfcbdfd1e87e06e47f172529592ad4cbd07b619b6419542cd95b7d
MD5 7fd16b828428e0879cc8e26917ff1e27
BLAKE2b-256 8d5d5af71cd72576bc61472ed4ac44d3d045f9e0fe6808a16964d657de7edee4

See more details on using hashes here.

File details

Details for the file agent_regress_cli-0.1.4-py3-none-any.whl.

File metadata

  • Download URL: agent_regress_cli-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 56.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for agent_regress_cli-0.1.4-py3-none-any.whl
Algorithm Hash digest
SHA256 f93ec21ff11a542db5a1822c421ab54218ae12cbda3a2d2c3a10274700f82366
MD5 eec6f92482a2fc10d47794f698df851b
BLAKE2b-256 0ca948dd3e52ea4d3bb0ab8e0c1d43dbcf4b07003e4bf7416fb541de4111e02a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page