agentic-evals 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,56 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ uses: astral-sh/setup-uv@v3
19
+ with:
20
+ enable-cache: true
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ run: uv python install ${{ matrix.python-version }}
24
+
25
+ - name: Install dependencies
26
+ run: uv sync --extra dev --python ${{ matrix.python-version }}
27
+
28
+ - name: Lint (ruff check)
29
+ run: uv run ruff check .
30
+
31
+ - name: Format check (ruff format)
32
+ run: uv run ruff format --check .
33
+
34
+ - name: Type check (mypy)
35
+ run: uv run mypy
36
+
37
+ - name: Test (pytest)
38
+ run: uv run pytest
39
+
40
+ package:
41
+ runs-on: ubuntu-latest
42
+ needs: test
43
+ steps:
44
+ - uses: actions/checkout@v4
45
+ - name: Install uv
46
+ uses: astral-sh/setup-uv@v3
47
+ with:
48
+ enable-cache: true
49
+ - name: Set up Python
50
+ run: uv python install 3.12
51
+ - name: Install dependencies
52
+ run: uv sync --extra dev --python 3.12
53
+ - name: Build distributions
54
+ run: |
55
+ uv run python -m build
56
+ uv run python -m twine check dist/*
@@ -0,0 +1,91 @@
1
+ name: publish-pypi
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v7
17
+ with:
18
+ python-version: "3.12"
19
+ - name: Build distributions
20
+ run: |
21
+ python -m pip install --upgrade pip
22
+ python -m pip install build twine
23
+ python -m build
24
+ python -m twine check dist/*
25
+ - name: Upload distributions
26
+ uses: actions/upload-artifact@v4
27
+ with:
28
+ name: python-package-distributions
29
+ path: dist/
30
+
31
+ publish-pypi:
32
+ runs-on: ubuntu-latest
33
+ needs: build
34
+ environment: pypi
35
+ permissions:
36
+ id-token: write
37
+ steps:
38
+ - name: Download distributions
39
+ uses: actions/download-artifact@v4
40
+ with:
41
+ name: python-package-distributions
42
+ path: dist/
43
+ - name: Publish to PyPI
44
+ uses: pypa/gh-action-pypi-publish@release/v1
45
+
46
+ create-github-release:
47
+ runs-on: ubuntu-latest
48
+ needs: publish-pypi
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+ - name: Extract changelog section
52
+ env:
53
+ RELEASE_TAG: ${{ github.ref_name }}
54
+ run: |
55
+ python - <<'PY'
56
+ from pathlib import Path
57
+ import os
58
+
59
+ tag = os.environ["RELEASE_TAG"]
60
+ version = tag.removeprefix("v")
61
+ changelog = Path("CHANGELOG.md").read_text(encoding="utf-8").splitlines()
62
+
63
+ start = None
64
+ end = None
65
+ heading = f"## {version} - "
66
+ for index, line in enumerate(changelog):
67
+ if line.startswith(heading):
68
+ start = index
69
+ continue
70
+ if start is not None and line.startswith("## "):
71
+ end = index
72
+ break
73
+
74
+ if start is None:
75
+ raise SystemExit(
76
+ f"Could not find CHANGELOG.md section for version {version}."
77
+ )
78
+
79
+ if end is None:
80
+ end = len(changelog)
81
+
82
+ section = "\n".join(changelog[start:end]).strip() + "\n"
83
+ Path("release-notes.md").write_text(section, encoding="utf-8")
84
+ PY
85
+ - name: Create GitHub release
86
+ uses: softprops/action-gh-release@v3
87
+ with:
88
+ tag_name: ${{ github.ref_name }}
89
+ name: ${{ github.ref_name }}
90
+ body_path: release-notes.md
91
+ generate_release_notes: false
@@ -0,0 +1,46 @@
1
+ name: publish-testpypi
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+ id-token: write
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v7
16
+ with:
17
+ python-version: "3.12"
18
+ - name: Build distributions
19
+ run: |
20
+ python -m pip install --upgrade pip
21
+ python -m pip install build twine
22
+ python -m build
23
+ python -m twine check dist/*
24
+ - name: Upload distributions
25
+ uses: actions/upload-artifact@v4
26
+ with:
27
+ name: python-package-distributions
28
+ path: dist/
29
+
30
+ publish-testpypi:
31
+ runs-on: ubuntu-latest
32
+ needs: build
33
+ environment: testpypi
34
+ permissions:
35
+ id-token: write
36
+ steps:
37
+ - name: Download distributions
38
+ uses: actions/download-artifact@v4
39
+ with:
40
+ name: python-package-distributions
41
+ path: dist/
42
+ - name: Publish to TestPyPI
43
+ uses: pypa/gh-action-pypi-publish@release/v1
44
+ with:
45
+ repository-url: https://test.pypi.org/legacy/
46
+ skip-existing: true
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ .venv/
6
+ .mypy_cache/
7
+ .ruff_cache/
8
+ .pytest_cache/
9
+ htmlcov/
10
+ .coverage
11
+ dist/
12
+ build/
13
+ .env
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented here.
4
+
5
+ This project follows [Semantic Versioning](https://semver.org/).
6
+
7
+ ## 0.1.0 - 2026-09-13
8
+
9
+ ### Added
10
+
11
+ - Initial extraction of AgenticLens's evaluation engine into a standalone,
12
+ framework-agnostic package: `EvalTrace`/`EvalSpan` (a minimal, tool-agnostic
13
+ trace shape), `Score`, `Evaluator`/`EvaluatorRegistry`/`CallableEvaluator`/
14
+ `LLMJudgeEvaluator`/`BusinessRuleEvaluator`, `TestCase`/`TestSuite`,
15
+ `evaluate_suite` (deterministic JSON Schema/field/tool/latency/cost/
16
+ turn-count checks plus custom evaluators), `run_live_suite` (Python/HTTP
17
+ live targets), and `GateConfig`/`evaluate_gate`.
18
+ - Zero dependency on AgenticLens or any other DeepAgentLabs project —
19
+ depends only on `pydantic`, `pyyaml`, `jsonschema`, and `referencing`.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepAgentLabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,237 @@
1
+ Metadata-Version: 2.5
2
+ Name: agentic-evals
3
+ Version: 0.1.0
4
+ Summary: A standalone, framework-agnostic evaluation and scoring engine for LLM/agent outputs — extracted from AgenticLens's evaluation module.
5
+ Project-URL: Homepage, https://github.com/DeepAgentLabs/agentic-evals
6
+ Project-URL: Repository, https://github.com/DeepAgentLabs/agentic-evals
7
+ Project-URL: Issues, https://github.com/DeepAgentLabs/agentic-evals/issues
8
+ Project-URL: Changelog, https://github.com/DeepAgentLabs/agentic-evals/blob/main/CHANGELOG.md
9
+ Author: agentic-evals Contributors
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 DeepAgentLabs
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: agents,evaluation,llm,llm-as-judge,scoring,testing
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Programming Language :: Python :: 3.10
37
+ Classifier: Programming Language :: Python :: 3.11
38
+ Classifier: Programming Language :: Python :: 3.12
39
+ Classifier: Programming Language :: Python :: 3.13
40
+ Classifier: Programming Language :: Python :: 3.14
41
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
42
+ Requires-Python: >=3.10
43
+ Requires-Dist: jsonschema>=4.23
44
+ Requires-Dist: pydantic<3,>=2.0
45
+ Requires-Dist: pyyaml<7,>=6.0
46
+ Requires-Dist: referencing>=0.35
47
+ Provides-Extra: dev
48
+ Requires-Dist: build>=1.2; extra == 'dev'
49
+ Requires-Dist: mypy>=1.10; extra == 'dev'
50
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
51
+ Requires-Dist: pytest>=8.0; extra == 'dev'
52
+ Requires-Dist: ruff>=0.6; extra == 'dev'
53
+ Requires-Dist: twine>=5.1; extra == 'dev'
54
+ Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
55
+ Description-Content-Type: text/markdown
56
+
57
+ # agentic-evals
58
+
59
+ **A standalone, framework-agnostic evaluation and scoring engine for LLM and
60
+ agent outputs.**
61
+
62
+ Extracted from [AgenticLens](https://github.com/DeepAgentLabs/agenticlens)'s
63
+ proven evaluation module — the same engine, usable on its own. It scores
64
+ whatever trace-shaped data you give it (see `EvalTrace`/`EvalSpan` below);
65
+ it has no dependency on any specific tracing/observability tool, and no
66
+ dependency on AgenticLens itself.
67
+
68
+ ## Status
69
+
70
+ **Alpha.** The engine (deterministic checks, LLM-as-judge and custom
71
+ evaluators, a release gate, live Python/HTTP targets) is real, tested code
72
+ lifted directly from AgenticLens's evaluation module. No PyPI release yet.
73
+
74
+ ## Why a separate package
75
+
76
+ AgenticLens's evaluation module was never actually AgenticLens-specific —
77
+ scoring an LLM/agent output against expectations doesn't need AgenticLens's
78
+ full trace schema, CLI, or dashboards. Pulling it out means:
79
+
80
+ - `agentic-sidecar`, `agentic-chaos`, or any other project can score outputs
81
+ without depending on all of AgenticLens.
82
+ - Anyone with *any* trace-shaped data — not just AgenticLens users — can use
83
+ it, the same way Braintrust's `autoevals` doesn't care what produced the
84
+ string it's scoring.
85
+
86
+ ## Install
87
+
88
+ ```bash
89
+ pip install agentic-evals
90
+ ```
91
+
92
+ ## Core concepts
93
+
94
+ - **`EvalTrace`/`EvalSpan`** — the minimal trace shape the engine inspects:
95
+ a trace id, spans (each optionally naming a `tool_name` and carrying
96
+ arbitrary `attributes`), total latency, estimated cost, and metadata.
97
+ Deliberately not tied to any specific instrumentation format — build one
98
+ from whatever you already have.
99
+ - **`Score`** — a single named judgment (0-1 value, pass/fail, explanation).
100
+ - **`Evaluator`** — anything with a `.name` and an `.evaluate(context) ->
101
+ list[Score]`. `CallableEvaluator` adapts a plain Python function;
102
+ `LLMJudgeEvaluator` and `BusinessRuleEvaluator` are named convenience
103
+ subclasses for readability/reporting.
104
+ - **`TestCase`/`TestSuite`** — declarative expectations (exact match,
105
+ substring, JSON Schema, required fields, required/forbidden tool calls,
106
+ required tool arguments, latency/cost/turn-count thresholds, or a named
107
+ custom evaluator) plus the cases that make up a suite.
108
+ - **`evaluate_suite`** — runs a suite against supplied `EvaluationSample`s
109
+ and returns an `EvaluationReport` (per-case scores plus a pass-rate/cost/
110
+ latency summary).
111
+ - **`GateConfig`/`evaluate_gate`** — turn an `EvaluationReport` into a
112
+ pass/fail release decision on configurable thresholds.
113
+
114
+ ## Quickstart
115
+
116
+ ```python
117
+ from agentic_evals import (
118
+ EvalSpan,
119
+ EvalTrace,
120
+ EvaluationSample,
121
+ TestCase,
122
+ TestSuite,
123
+ evaluate_suite,
124
+ )
125
+
126
+ suite = TestSuite(
127
+ name="support-answers",
128
+ version="1",
129
+ cases=[
130
+ TestCase(
131
+ id="case-1",
132
+ name="Answer contains the right total",
133
+ expected_contains=["42"],
134
+ required_tools=["calculator"],
135
+ max_latency_ms=2000,
136
+ )
137
+ ],
138
+ )
139
+
140
+ sample = EvaluationSample(
141
+ case_id="case-1",
142
+ output="The combined total is 42.",
143
+ trace=EvalTrace(
144
+ trace_id="trace-1",
145
+ total_latency_ms=350,
146
+ spans=[EvalSpan(tool_name="calculator")],
147
+ ),
148
+ )
149
+
150
+ report = evaluate_suite(suite, [sample])
151
+ print(report.summary.pass_rate) # 1.0
152
+ ```
153
+
154
+ ## LLM-as-judge
155
+
156
+ ```python
157
+ from agentic_evals import (
158
+ EvaluationContext,
159
+ EvaluatorConfig,
160
+ EvaluatorRegistry,
161
+ LLMJudgeEvaluator,
162
+ Score,
163
+ TestCase,
164
+ )
165
+
166
+
167
+ def judge(context: EvaluationContext) -> Score:
168
+ # Call whatever model/provider you like here.
169
+ correct = "42" in context.sample.output
170
+ return Score(
171
+ name="answer_quality",
172
+ value=0.95 if correct else 0.1,
173
+ passed=correct,
174
+ explanation="Judged against the rubric in context.config.config.",
175
+ )
176
+
177
+
178
+ registry = EvaluatorRegistry()
179
+ registry.register(LLMJudgeEvaluator("answer_quality_judge", judge))
180
+
181
+ case = TestCase(
182
+ id="case-1",
183
+ name="Answer quality",
184
+ evaluators=[EvaluatorConfig(name="answer_quality_judge", threshold=0.8)],
185
+ )
186
+ ```
187
+
188
+ ## Release gates
189
+
190
+ ```python
191
+ from agentic_evals import GateConfig, evaluate_gate
192
+
193
+ decision = evaluate_gate(
194
+ report,
195
+ GateConfig(min_pass_rate=0.95, max_average_latency_ms=1500, max_total_cost_usd=0.25),
196
+ )
197
+ if not decision.passed:
198
+ raise SystemExit(f"Release gate failed: {decision.reasons}")
199
+ ```
200
+
201
+ Never fabricates a value it can't back up: `total_cost_usd` on a summary or
202
+ gate decision stays `None` unless every case in scope has a known cost —
203
+ an incomplete cost picture is reported as unavailable, not `$0.00`.
204
+
205
+ ## Live targets
206
+
207
+ Point a suite at a real running system (a trusted Python callable, or an
208
+ HTTP endpoint) instead of pre-recorded samples:
209
+
210
+ ```python
211
+ from agentic_evals import PythonTarget, run_live_suite
212
+
213
+ report = run_live_suite(suite, PythonTarget(callable_path="my_module:run_case"))
214
+ ```
215
+
216
+ Live targets are intentionally powerful developer-facing integrations —
217
+ Python targets execute local code and HTTP targets can reach arbitrary
218
+ URLs. Only point them at trusted suite files and trusted target
219
+ definitions.
220
+
221
+ ## Using it with AgenticLens's own traces
222
+
223
+ If you already have an AgenticLens `Run` (from its instrumentation API or
224
+ OTLP ingestion), AgenticLens itself provides the adapter —
225
+ `agenticlens.evaluation.to_eval_trace(run)` — so you don't have to hand-build
226
+ an `EvalTrace`. This package has no dependency in the other direction.
227
+
228
+ ## What's deliberately not here
229
+
230
+ Dataset versioning/splitting, judge calibration, and HTML report rendering
231
+ stay in AgenticLens for now — those are product features built *on top of*
232
+ this engine (the same way Braintrust's dataset/experiment platform is
233
+ separate from the `autoevals` library itself), not the engine.
234
+
235
+ ## License
236
+
237
+ MIT
@@ -0,0 +1,181 @@
1
+ # agentic-evals
2
+
3
+ **A standalone, framework-agnostic evaluation and scoring engine for LLM and
4
+ agent outputs.**
5
+
6
+ Extracted from [AgenticLens](https://github.com/DeepAgentLabs/agenticlens)'s
7
+ proven evaluation module — the same engine, usable on its own. It scores
8
+ whatever trace-shaped data you give it (see `EvalTrace`/`EvalSpan` below);
9
+ it has no dependency on any specific tracing/observability tool, and no
10
+ dependency on AgenticLens itself.
11
+
12
+ ## Status
13
+
14
+ **Alpha.** The engine (deterministic checks, LLM-as-judge and custom
15
+ evaluators, a release gate, live Python/HTTP targets) is real, tested code
16
+ lifted directly from AgenticLens's evaluation module. No PyPI release yet.
17
+
18
+ ## Why a separate package
19
+
20
+ AgenticLens's evaluation module was never actually AgenticLens-specific —
21
+ scoring an LLM/agent output against expectations doesn't need AgenticLens's
22
+ full trace schema, CLI, or dashboards. Pulling it out means:
23
+
24
+ - `agentic-sidecar`, `agentic-chaos`, or any other project can score outputs
25
+ without depending on all of AgenticLens.
26
+ - Anyone with *any* trace-shaped data — not just AgenticLens users — can use
27
+ it, the same way Braintrust's `autoevals` doesn't care what produced the
28
+ string it's scoring.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install agentic-evals
34
+ ```
35
+
36
+ ## Core concepts
37
+
38
+ - **`EvalTrace`/`EvalSpan`** — the minimal trace shape the engine inspects:
39
+ a trace id, spans (each optionally naming a `tool_name` and carrying
40
+ arbitrary `attributes`), total latency, estimated cost, and metadata.
41
+ Deliberately not tied to any specific instrumentation format — build one
42
+ from whatever you already have.
43
+ - **`Score`** — a single named judgment (0-1 value, pass/fail, explanation).
44
+ - **`Evaluator`** — anything with a `.name` and an `.evaluate(context) ->
45
+ list[Score]`. `CallableEvaluator` adapts a plain Python function;
46
+ `LLMJudgeEvaluator` and `BusinessRuleEvaluator` are named convenience
47
+ subclasses for readability/reporting.
48
+ - **`TestCase`/`TestSuite`** — declarative expectations (exact match,
49
+ substring, JSON Schema, required fields, required/forbidden tool calls,
50
+ required tool arguments, latency/cost/turn-count thresholds, or a named
51
+ custom evaluator) plus the cases that make up a suite.
52
+ - **`evaluate_suite`** — runs a suite against supplied `EvaluationSample`s
53
+ and returns an `EvaluationReport` (per-case scores plus a pass-rate/cost/
54
+ latency summary).
55
+ - **`GateConfig`/`evaluate_gate`** — turn an `EvaluationReport` into a
56
+ pass/fail release decision on configurable thresholds.
57
+
58
+ ## Quickstart
59
+
60
+ ```python
61
+ from agentic_evals import (
62
+ EvalSpan,
63
+ EvalTrace,
64
+ EvaluationSample,
65
+ TestCase,
66
+ TestSuite,
67
+ evaluate_suite,
68
+ )
69
+
70
+ suite = TestSuite(
71
+ name="support-answers",
72
+ version="1",
73
+ cases=[
74
+ TestCase(
75
+ id="case-1",
76
+ name="Answer contains the right total",
77
+ expected_contains=["42"],
78
+ required_tools=["calculator"],
79
+ max_latency_ms=2000,
80
+ )
81
+ ],
82
+ )
83
+
84
+ sample = EvaluationSample(
85
+ case_id="case-1",
86
+ output="The combined total is 42.",
87
+ trace=EvalTrace(
88
+ trace_id="trace-1",
89
+ total_latency_ms=350,
90
+ spans=[EvalSpan(tool_name="calculator")],
91
+ ),
92
+ )
93
+
94
+ report = evaluate_suite(suite, [sample])
95
+ print(report.summary.pass_rate) # 1.0
96
+ ```
97
+
98
+ ## LLM-as-judge
99
+
100
+ ```python
101
+ from agentic_evals import (
102
+ EvaluationContext,
103
+ EvaluatorConfig,
104
+ EvaluatorRegistry,
105
+ LLMJudgeEvaluator,
106
+ Score,
107
+ TestCase,
108
+ )
109
+
110
+
111
+ def judge(context: EvaluationContext) -> Score:
112
+ # Call whatever model/provider you like here.
113
+ correct = "42" in context.sample.output
114
+ return Score(
115
+ name="answer_quality",
116
+ value=0.95 if correct else 0.1,
117
+ passed=correct,
118
+ explanation="Judged against the rubric in context.config.config.",
119
+ )
120
+
121
+
122
+ registry = EvaluatorRegistry()
123
+ registry.register(LLMJudgeEvaluator("answer_quality_judge", judge))
124
+
125
+ case = TestCase(
126
+ id="case-1",
127
+ name="Answer quality",
128
+ evaluators=[EvaluatorConfig(name="answer_quality_judge", threshold=0.8)],
129
+ )
130
+ ```
131
+
132
+ ## Release gates
133
+
134
+ ```python
135
+ from agentic_evals import GateConfig, evaluate_gate
136
+
137
+ decision = evaluate_gate(
138
+ report,
139
+ GateConfig(min_pass_rate=0.95, max_average_latency_ms=1500, max_total_cost_usd=0.25),
140
+ )
141
+ if not decision.passed:
142
+ raise SystemExit(f"Release gate failed: {decision.reasons}")
143
+ ```
144
+
145
+ Never fabricates a value it can't back up: `total_cost_usd` on a summary or
146
+ gate decision stays `None` unless every case in scope has a known cost —
147
+ an incomplete cost picture is reported as unavailable, not `$0.00`.
148
+
149
+ ## Live targets
150
+
151
+ Point a suite at a real running system (a trusted Python callable, or an
152
+ HTTP endpoint) instead of pre-recorded samples:
153
+
154
+ ```python
155
+ from agentic_evals import PythonTarget, run_live_suite
156
+
157
+ report = run_live_suite(suite, PythonTarget(callable_path="my_module:run_case"))
158
+ ```
159
+
160
+ Live targets are intentionally powerful developer-facing integrations —
161
+ Python targets execute local code and HTTP targets can reach arbitrary
162
+ URLs. Only point them at trusted suite files and trusted target
163
+ definitions.
164
+
165
+ ## Using it with AgenticLens's own traces
166
+
167
+ If you already have an AgenticLens `Run` (from its instrumentation API or
168
+ OTLP ingestion), AgenticLens itself provides the adapter —
169
+ `agenticlens.evaluation.to_eval_trace(run)` — so you don't have to hand-build
170
+ an `EvalTrace`. This package has no dependency in the other direction.
171
+
172
+ ## What's deliberately not here
173
+
174
+ Dataset versioning/splitting, judge calibration, and HTML report rendering
175
+ stay in AgenticLens for now — those are product features built *on top of*
176
+ this engine (the same way Braintrust's dataset/experiment platform is
177
+ separate from the `autoevals` library itself), not the engine.
178
+
179
+ ## License
180
+
181
+ MIT