Skip to main content
The EvalPort adapter converts native eval suites and reports to and from the EvalPort open spec (version 1.0.0-rc.5) so your agents interoperate with any EvalPort-compatible tool. Run an Agent through a suite, then export both the suite and results as spec-conformant EvalPort documents:
An Agent produces an EvalReport; one line exports it as an EvalPort ResultSet:

Quick Start

1

Export a suite

Build an EvalPackage and export it as an EvalPort suite dict:
2

Import a suite from another tool

Load an EvalPort suite dict from any compatible tool, then run it. from_evalport prefers spec-shaped test_cases but also accepts legacy cases:
3

Export a run report

Run a suite to get an EvalReport, then persist it as an EvalPort ResultSet:
4

Pin run_id / started_at for CI

Pass explicit run_id and started_at so CI runs produce stable, diffable output:

How It Works

The adapter maps native dataclasses to plain EvalPort dicts and back, so PraisonAI and external harnesses trade suites over the shared spec.
The exporter (to_evalport, report_to_evalport) now emits the spec-conformant 1.0.0-rc.5 shape. Downstream code that parsed the old fields (kind, suite_name, case_id, latency_ms, top-level score, grader_scores, top-level thresholds/seed, timeout_seconds) must be updated to the new keys. The importer (from_evalport) stays backward-compatible — it still reads legacy suites (cases, evalport_version, top-level thresholds/seed/timeout_seconds) and spec-shaped external suites with inline grader objects.
Three module-level functions cover every direction — pick one by what you hold: A round trip is lossless — from_evalport(to_evalport(pkg)) reproduces the original package’s to_dict().

Spec Mapping

Native models map 1:1 onto EvalPort concepts. Each grader_result carries a clamped [0,1] score:
A suite dict from to_evalport looks like this:
A result set from report_to_evalport looks like this:

Configuration Options

The adapter is dependency-free and exposes three functions — no config classes.
Full Python API for the eval package, including to_evalport, from_evalport, and report_to_evalport

Common Patterns

Round-trip a suite locally to prove fidelity:
Import a third-party EvalPort suite and run it through HarnessEvaluator:
Prove structural conformance for both documents with the external openeval package:

Best Practices

to_evalport writes a positive timeout_seconds as timeout_ms (integer milliseconds, max(1, round(sec*1000))) because the spec requires timeout_ms >= 1. A nonpositive timeout_seconds cannot be represented, so it is preserved under test_case.metadata.praisonai.timeout_seconds — the importer restores the original value, keeping round trips lossless.
The exported graders list on each test case always starts with "praisonai_verdict" (the spec requires at least one grader per case) followed by any criterion names, deduplicated in order. On import the adapter strips "praisonai_verdict" before returning criteria, so a round trip reproduces the original criteria exactly.
report_to_evalport accepts keyword-only run_id and started_at. Left unset, run_id defaults to a random UUID and started_at to the current UTC time — pass explicit values in CI so output stays stable and diffable.
Any raw score outside [0, 1] is clamped; the pre-clamp value survives under grader_result.metadata["openeval.raw_score"]. When clamping changes the summary average, the raw value is kept under metadata.praisonai.average_score. A non-numeric or NaN score becomes null and forces passed: false (“not verified”).
The adapter never imports evalport-sdk or openeval. Install validation packages only where you run validate_suite() / validate_result_set(), so the core SDK stays lightweight everywhere else.

Evaluation Suite

Run every evaluator as one CI gate

Harness Evaluator

Score Interactive Test Harness traces

Judge

LLM-as-judge for evaluating outputs

Evaluation

Evaluators, suites, and reports