typed-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.
Files changed (67) hide show
  1. typed_evals-0.1.0/LICENSE +21 -0
  2. typed_evals-0.1.0/MANIFEST.in +5 -0
  3. typed_evals-0.1.0/PKG-INFO +372 -0
  4. typed_evals-0.1.0/README.md +340 -0
  5. typed_evals-0.1.0/docs/ADAPTERS.md +137 -0
  6. typed_evals-0.1.0/docs/ARCHITECTURE.md +123 -0
  7. typed_evals-0.1.0/docs/CALIBRATION.md +177 -0
  8. typed_evals-0.1.0/docs/EVALUATION.md +291 -0
  9. typed_evals-0.1.0/docs/PUBLISHING.md +56 -0
  10. typed_evals-0.1.0/docs/RUNTIME.md +544 -0
  11. typed_evals-0.1.0/pyproject.toml +63 -0
  12. typed_evals-0.1.0/setup.cfg +4 -0
  13. typed_evals-0.1.0/tests/conftest.py +106 -0
  14. typed_evals-0.1.0/tests/test_agent_framework_adapter.py +179 -0
  15. typed_evals-0.1.0/tests/test_agents.py +384 -0
  16. typed_evals-0.1.0/tests/test_calibration.py +242 -0
  17. typed_evals-0.1.0/tests/test_calibration_multimetric.py +111 -0
  18. typed_evals-0.1.0/tests/test_convenience.py +132 -0
  19. typed_evals-0.1.0/tests/test_crewai_adapter.py +152 -0
  20. typed_evals-0.1.0/tests/test_evaluator.py +204 -0
  21. typed_evals-0.1.0/tests/test_io_integrations.py +262 -0
  22. typed_evals-0.1.0/tests/test_langchain_adapter.py +80 -0
  23. typed_evals-0.1.0/tests/test_live.py +20 -0
  24. typed_evals-0.1.0/tests/test_metric_reload.py +131 -0
  25. typed_evals-0.1.0/tests/test_metrics.py +143 -0
  26. typed_evals-0.1.0/tests/test_package.py +77 -0
  27. typed_evals-0.1.0/tests/test_runtime.py +536 -0
  28. typed_evals-0.1.0/tests/test_sdk_contract.py +224 -0
  29. typed_evals-0.1.0/tests/test_tool_guard.py +280 -0
  30. typed_evals-0.1.0/tests/test_utils.py +46 -0
  31. typed_evals-0.1.0/typed_evals/__init__.py +86 -0
  32. typed_evals-0.1.0/typed_evals/__main__.py +3 -0
  33. typed_evals-0.1.0/typed_evals/_utils.py +50 -0
  34. typed_evals-0.1.0/typed_evals/adapters/__init__.py +1 -0
  35. typed_evals-0.1.0/typed_evals/adapters/agent_framework.py +56 -0
  36. typed_evals-0.1.0/typed_evals/adapters/crewai.py +104 -0
  37. typed_evals-0.1.0/typed_evals/adapters/langchain.py +79 -0
  38. typed_evals-0.1.0/typed_evals/backends/__init__.py +17 -0
  39. typed_evals-0.1.0/typed_evals/backends/jev.py +82 -0
  40. typed_evals-0.1.0/typed_evals/calibration/__init__.py +23 -0
  41. typed_evals-0.1.0/typed_evals/calibration/core.py +246 -0
  42. typed_evals-0.1.0/typed_evals/cli.py +97 -0
  43. typed_evals-0.1.0/typed_evals/data/__init__.py +29 -0
  44. typed_evals-0.1.0/typed_evals/data/datasets.py +56 -0
  45. typed_evals-0.1.0/typed_evals/data/models.py +162 -0
  46. typed_evals-0.1.0/typed_evals/errors.py +25 -0
  47. typed_evals-0.1.0/typed_evals/evaluation/__init__.py +25 -0
  48. typed_evals-0.1.0/typed_evals/evaluation/decorators.py +78 -0
  49. typed_evals-0.1.0/typed_evals/evaluation/evaluator.py +396 -0
  50. typed_evals-0.1.0/typed_evals/evaluation/pipeline.py +327 -0
  51. typed_evals-0.1.0/typed_evals/metrics/__init__.py +41 -0
  52. typed_evals-0.1.0/typed_evals/metrics/agents.py +94 -0
  53. typed_evals-0.1.0/typed_evals/metrics/base.py +196 -0
  54. typed_evals-0.1.0/typed_evals/metrics/presets.py +25 -0
  55. typed_evals-0.1.0/typed_evals/metrics/rag.py +61 -0
  56. typed_evals-0.1.0/typed_evals/metrics/registry.py +29 -0
  57. typed_evals-0.1.0/typed_evals/py.typed +0 -0
  58. typed_evals-0.1.0/typed_evals/runtime/__init__.py +31 -0
  59. typed_evals-0.1.0/typed_evals/runtime/agents.py +191 -0
  60. typed_evals-0.1.0/typed_evals/runtime/guards.py +518 -0
  61. typed_evals-0.1.0/typed_evals/runtime/tools.py +152 -0
  62. typed_evals-0.1.0/typed_evals.egg-info/PKG-INFO +372 -0
  63. typed_evals-0.1.0/typed_evals.egg-info/SOURCES.txt +65 -0
  64. typed_evals-0.1.0/typed_evals.egg-info/dependency_links.txt +1 -0
  65. typed_evals-0.1.0/typed_evals.egg-info/entry_points.txt +2 -0
  66. typed_evals-0.1.0/typed_evals.egg-info/requires.txt +21 -0
  67. typed_evals-0.1.0/typed_evals.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Aaryan Verma and typed_evals contributors
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,5 @@
1
+ include LICENSE README.md
2
+ recursive-include docs *.md
3
+ recursive-include tests *.py
4
+ prune examples
5
+ prune notebooks
@@ -0,0 +1,372 @@
1
+ Metadata-Version: 2.4
2
+ Name: typed_evals
3
+ Version: 0.1.0
4
+ Summary: Evaluation for LLM and Agents using System One Models, with opt-in isotonic calibration.
5
+ Author: Aaryan Verma
6
+ License-Expression: MIT
7
+ Project-URL: Author, https://github.com/Aaryanverma
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
11
+ Classifier: Typing :: Typed
12
+ Requires-Python: >=3.11
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Requires-Dist: typesafe-sdk<0.8,>=0.7.0
16
+ Requires-Dist: pydantic<3,>=2.12
17
+ Provides-Extra: calibration
18
+ Requires-Dist: scikit-learn<2,>=1.4; extra == "calibration"
19
+ Provides-Extra: langchain
20
+ Requires-Dist: langchain<2,>=1; extra == "langchain"
21
+ Provides-Extra: crewai
22
+ Requires-Dist: crewai<2,>=1.15.22; extra == "crewai"
23
+ Provides-Extra: agent-framework
24
+ Requires-Dist: agent-framework-core<2,>=1.19; extra == "agent-framework"
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest<10,>=8; extra == "dev"
27
+ Requires-Dist: pytest-asyncio<2,>=0.24; extra == "dev"
28
+ Requires-Dist: pytest-cov<8,>=5; extra == "dev"
29
+ Requires-Dist: ruff>=0.9; extra == "dev"
30
+ Requires-Dist: build>=1.2; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # Typed Evals
34
+
35
+ Evaluate LLM responses, RAG datasets, and recorded agent executions using System One Models like **[Jev](https://typesafe.ai/)** as the judge. Guard tools before they execute.
36
+ Optionally calibrate individual metrics against human pass/fail labels.
37
+
38
+ **Made with ❤︎ by [Aaryan Verma](https://github.com/Aaryanverma).**
39
+
40
+ The project, command-line tool, and Python package are all named `typed_evals`.
41
+ The Python package lives directly in the repository root.
42
+
43
+ `Requires python >= 3.11`
44
+
45
+ ## Install
46
+
47
+ ```python
48
+ pip install typed_evals
49
+ export TYPESAFE_API_KEY='your-key'
50
+ ```
51
+
52
+ OR
53
+
54
+ ```bash
55
+ python -m pip install .
56
+ export TYPESAFE_API_KEY='your-key'
57
+ ```
58
+
59
+ The default judge is `jev-1.13.0`, through the official `typesafe-sdk` 0.7.x.
60
+ For an offline demonstration without credentials, run `python examples/offline_demo.py`
61
+ after installing the fitting dependency with `pip install '.[calibration]'`.
62
+
63
+ ## Evaluate a RAG response
64
+
65
+ ```python
66
+ from typed_evals import evaluate
67
+
68
+ result = evaluate(
69
+ input="What is the refund period?", # your query
70
+ response="You can request a refund within 30 days.", # Response from your LLM
71
+ contexts=["Refunds are allowed within 30 days of purchase."], # context used for query
72
+ preset="rag",
73
+ )
74
+
75
+ print(result.passed)
76
+ for name, metric in result.metrics.items():
77
+ print(name, metric.score, metric.passed)
78
+ ```
79
+
80
+ Supply your evidence and choose a preset. Credentials come from the environment;
81
+ backend configuration and metric objects are optional. Without a preset or custom
82
+ metrics, evaluation checks **answer relevancy only**, even when contexts are supplied.
83
+
84
+ | Preset | Checks | Required evidence |
85
+ |---|---|---|
86
+ | `"response"` (default) | Answer relevancy | `input`, `response` |
87
+ | `"rag"` | Faithfulness, answer relevancy, context relevance | `input`, `response`, `contexts` |
88
+ | `"agent"` | Task completion, tool grounding | `input`, `response`, `trace`, `expected_outcome` |
89
+
90
+ Presets are fixed panels using the metrics' existing defaults (threshold `0.5`
91
+ for these three panels). They never infer or drop checks based on available data.
92
+ Missing evidence and judge errors raise by default. See the
93
+ [metric definitions and score semantics](docs/EVALUATION.md#built-in-metrics)
94
+ when selecting checks and acceptance thresholds for your application.
95
+
96
+ ## Evaluate a dataset
97
+
98
+ ```python
99
+ report = evaluate("examples/assets/rag_samples.jsonl", preset="rag")
100
+ print(report.summary)
101
+ report.save("evaluation-report.json")
102
+ ```
103
+
104
+ `evaluate` also accepts one dictionary, an `EvaluationSample`, or a list/tuple
105
+ of dictionaries and samples. Direct fields or one sample return `SampleResult`;
106
+ a sequence or file always returns `EvaluationReport`, including empty and
107
+ single-row datasets. JSON files contain arrays; JSONL files contain one row per line:
108
+
109
+ ```json
110
+ {"input":"Refund period?","response":"30 days.","contexts":["Refunds allowed within 30 days."]}
111
+ ```
112
+
113
+ All rows are validated before judging starts. Each sample's metrics share one
114
+ request; batches use up to eight concurrent workers by default and preserve input order.
115
+
116
+ In notebooks or async applications, use `aevaluate` to keep the event loop responsive:
117
+
118
+ ```python
119
+ from typed_evals import aevaluate
120
+
121
+ report = await aevaluate("examples/assets/rag_samples.jsonl", preset="rag")
122
+ ```
123
+
124
+ The synchronous API also works in notebooks, but blocks until evaluation finishes.
125
+
126
+ ## Guard a LangChain tool
127
+
128
+ Install `pip install '.[langchain]'`, then decorate the tool before registering it:
129
+
130
+ ```python
131
+ from langchain.tools import ToolRuntime, tool
132
+ from typed_evals.adapters.langchain import guard_tool
133
+
134
+
135
+ @tool
136
+ @guard_tool(
137
+ policy="Only read tickets owned by the authenticated customer.",
138
+ contexts=lambda runtime: runtime.context["authorization_evidence"],
139
+ )
140
+ def read_ticket(ticket_id: str, runtime: ToolRuntime) -> str:
141
+ """Read the complete text of a support ticket."""
142
+ return ticket_store.read_authorized(runtime.context["customer_id"], ticket_id)
143
+ ```
144
+
145
+ Here `ticket_store` is your application's ticket service. Supply current,
146
+ application-owned authorization evidence in the agent's runtime context.
147
+ The adapter captures the latest human text, tool name, arguments, and call ID.
148
+ It uses `ToolSafety` with threshold `0.9` and raises `GuardrailViolation` on a
149
+ failed or unavailable judgment before the function executes. Native outputs
150
+ are preserved. The tool still enforces deterministic authorization when it runs.
151
+
152
+ See the complete [LangChain example](examples/langchain_guarded_tools.py), including
153
+ agent construction and handling blocked calls. For plain Python tools, import
154
+ `guard_tool` from `typed_evals` and supply `input` and `contexts` as values or callbacks
155
+ of bound arguments. The [runtime guide](docs/RUNTIME.md) covers both helpers,
156
+ custom metrics, calibrated guards, and additional checkpoints.
157
+
158
+ ## CrewAI and Microsoft Agent Framework
159
+
160
+ Framework integrations are optional:
161
+
162
+ | Framework | Install from this repository | Adapter |
163
+ |---|---|---|
164
+ | LangChain | `pip install '.[langchain]'` | `typed_evals.adapters.langchain.guard_tool` |
165
+ | CrewAI | `pip install '.[crewai]'` | `typed_evals.adapters.crewai.guard_tool` |
166
+ | Microsoft Agent Framework | `pip install '.[agent-framework]'` | `typed_evals.adapters.agent_framework.guard_tool` |
167
+
168
+ The CrewAI decorator creates a native tool ready for `Agent(tools=[...])`.
169
+ The Microsoft adapter wraps a function under `@agent_framework.tool` and reads
170
+ explicitly selected evidence from its injected `FunctionInvocationContext`.
171
+ Both use the same runtime guard and default tool-safety threshold of `0.9`.
172
+ See the [adapter guide](docs/ADAPTERS.md) for registration, runtime evidence, and
173
+ framework error-handling details. Try the offline native-tool examples:
174
+
175
+ ```bash
176
+ python examples/crewai_guarded_tools.py
177
+ python examples/agent_framework_guarded_tools.py
178
+ ```
179
+
180
+ ## Available metrics
181
+
182
+ List all built-in metric names without API credentials:
183
+
184
+ ```python
185
+ from typed_evals import list_metrics
186
+
187
+ print(list_metrics())
188
+ # ['answer_correctness', 'answer_relevancy', 'context_relevance',
189
+ # 'faithfulness', 'policy_compliance', 'task_completion',
190
+ # 'tool_accuracy', 'tool_grounding', 'tool_safety']
191
+ ```
192
+
193
+ The function returns a new, alphabetically sorted list. It includes
194
+ `PolicyCompliance` and `ToolSafety`, which require `policy=...` when constructed.
195
+ Custom `Metric` instances are not registered in this list. See the
196
+ [metric definitions](docs/EVALUATION.md#built-in-metrics) for constructors and required evidence.
197
+
198
+ ## Customize when needed
199
+
200
+ Choose custom metrics **instead of** a preset to control the panel and thresholds:
201
+
202
+ ```python
203
+ from typed_evals import Faithfulness, AnswerRelevancy
204
+
205
+ result = evaluate(
206
+ input="Refund period?",
207
+ response="30 days.",
208
+ contexts=["Refunds are allowed within 30 days."],
209
+ metrics=[Faithfulness(threshold=0.8), AnswerRelevancy(threshold=0.8)],
210
+ )
211
+ ```
212
+
213
+ Create a custom metric and use it for evaluation:
214
+
215
+ ```python
216
+ from typed_evals import Faithfulness, AnswerRelevancy, Metric
217
+
218
+ # create a new metric
219
+ WeirdMetric = Metric(
220
+ name="weirdness",
221
+ kind="score", # noul, choice, score (from Jev)
222
+ instructions="Assess how weird the response is.",
223
+ criteria=[
224
+ "The response is completely normal and expected.",
225
+ "The response is somewhat unusual but still understandable.",
226
+ "The response is very weird and unexpected.",
227
+ ],
228
+ pass_definition="The response is not weird.",
229
+ required_fields=("input", "response"),
230
+ threshold=0.8,
231
+ )
232
+
233
+ # add it to metrics
234
+ result = evaluate(
235
+ input="Refund period?",
236
+ response="30 days.",
237
+ contexts=["Refunds are allowed within 30 days."],
238
+ metrics=[
239
+ Faithfulness(threshold=0.8),
240
+ AnswerRelevancy(threshold=0.8),
241
+ WeirdMetric,
242
+ ],
243
+ )
244
+ ```
245
+
246
+
247
+ For reusable configuration, use `Evaluator(preset="rag")` or `Evaluator(metrics=[...])`.
248
+ Existing `EvaluationSample`, `Evaluator`, `EvaluationPipeline`, and runtime APIs
249
+ remain available. Pass `backend=JevBackend(model="...")` to select a different Jev model.
250
+
251
+ ## Use another judge backend
252
+
253
+ The Python API supports custom judge backends through the public `Backend` and
254
+ `JudgeSession` protocols. Jev is the only bundled provider today, but a future
255
+ provider can be integrated by implementing an adapter and passing it as `backend=`
256
+ to `evaluate`, `aevaluate`, `Evaluator`, or `EvaluationPipeline`. Runtime guards
257
+ can use the same adapter through their evaluator or `guard_tool(backend=...)`.
258
+
259
+ A backend supplies:
260
+
261
+ - `model: str`, identifying the configured judge model.
262
+ - `session()`, an async context manager yielding a judge session.
263
+ - `async judge(state, questions)` on that session, returning a `JudgeResponse`
264
+ with the actual model ID, answers keyed by metric name, and optional usage.
265
+
266
+ Once your adapter is implemented, use it directly:
267
+
268
+ ```python
269
+ from typed_evals import evaluate
270
+ from your_app.backends import YourBackend # Your provider adapter.
271
+
272
+ result = evaluate(
273
+ input="What is the refund period?",
274
+ response="You can request a refund within 30 days.",
275
+ backend=YourBackend(),
276
+ )
277
+ ```
278
+
279
+ The current question and answer contract uses the TypeSafe SDK's Noul, Choice,
280
+ and Score formats. Your adapter must translate the rubrics into provider requests
281
+ and return answers matching the selected metrics' formats and score semantics;
282
+ the `typesafe-sdk` dependency is still required. The CLI currently uses `JevBackend`.
283
+ See the [backend interface](docs/ARCHITECTURE.md#backend-interface) and the
284
+ [synthetic backend example](examples/offline_demo.py) for an existing implementation.
285
+
286
+ ## Calibration
287
+
288
+ A raw judge score of `0.8` does not necessarily mean humans would pass 80% of
289
+ similar examples. Calibration uses representative human labels to align each
290
+ metric's scores with observed pass rates, helping you set meaningful thresholds
291
+ for your use case.
292
+
293
+ Calibration is off by default. Use `EvaluationPipeline` to fit or load per-metric
294
+ curves against representative human labels; see the [calibration guide](docs/CALIBRATION.md).
295
+ `score` is the raw metric score unless calibration is applied. `passed` compares
296
+ the score with the metric threshold; it is `None` for unavailable evaluations.
297
+ Jev judgments can be wrong, and the checks do not establish a single probability
298
+ that an entire answer is true.
299
+
300
+ ## Documentation, notebooks, and examples
301
+
302
+ | Folder | Contents |
303
+ |---|---|
304
+ | [`typed_evals/`](typed_evals/) | Main Python package: evaluation, metrics, calibration, runtime guards, adapters, and CLI. |
305
+ | [`docs/`](docs/) | Evaluation, runtime, calibration, and architecture guides. |
306
+ | [`notebooks/`](notebooks/) | Interactive walkthroughs for response, RAG, and agent evaluation. |
307
+ | [`examples/`](examples/) | Python scripts and sample datasets for evaluation and tool guards. |
308
+ | [`tests/`](tests/) | Unit, integration, and optional live API tests. |
309
+
310
+ Start with the guide for your use case:
311
+
312
+ - [Evaluation guide](docs/EVALUATION.md): metrics, data formats, custom checks, wrappers, CLI.
313
+ - [Runtime guide](docs/RUNTIME.md): tool guards, agent decorators, policy and failure semantics.
314
+ - [Calibration guide](docs/CALIBRATION.md): fitting, held-out validation, saved artifacts.
315
+ - [Adapter guide](docs/ADAPTERS.md): LangChain, CrewAI, and Microsoft Agent Framework tools.
316
+ - [Architecture](docs/ARCHITECTURE.md): implementation boundaries.
317
+
318
+ The Python package uses lowercase subpackages grouped by responsibility:
319
+
320
+ ```text
321
+ typed_evals/
322
+ ├── adapters/ # Framework integrations
323
+ ├── backends/ # Judge SDK and backend protocols
324
+ ├── calibration/ # Fitting, diagnostics, and saved calibration
325
+ ├── data/ # Validated models and dataset loading
326
+ ├── evaluation/ # Evaluator, pipeline, and result decorators
327
+ ├── metrics/ # Base metric, RAG/agent rubrics, registry, and presets
328
+ └── runtime/ # Guards, agent wrappers, and tool decorators
329
+ ```
330
+
331
+ Public imports such as `from typed_evals import Evaluator, Faithfulness` stay the
332
+ same. For direct module imports, use the paths in the [architecture guide](docs/ARCHITECTURE.md#modules).
333
+
334
+ For interactive usage, open the [introductory notebook](notebooks/sample_notebook.ipynb)
335
+ or the [advanced notebook](notebooks/advanced_usage.ipynb), which covers custom
336
+ metrics, calibration, and agent integrations. Install this repository into the
337
+ notebook kernel's environment and use the repository root as the working directory
338
+ so the relative dataset paths resolve. The notebooks use `python-dotenv` and make
339
+ live requests with `TYPESAFE_API_KEY`; calibration also needs `.[calibration]`.
340
+ The advanced agent sections additionally use `agent-framework`, `langchain`,
341
+ `langchain-google-genai`, and Gemini credentials.
342
+
343
+ Examples you can run without API credentials after installing `.[calibration]`:
344
+
345
+ ```bash
346
+ python examples/offline_demo.py
347
+ python examples/runtime_guardrails.py
348
+ python examples/decorated_agent.py
349
+ ```
350
+
351
+ For live evaluation, see [RAG evaluation](examples/rag_evaluation.py),
352
+ [recorded agent evaluation](examples/agent_evaluation.py), and the
353
+ [calibrated pipeline](examples/calibrated_pipeline.py). The
354
+ [custom metrics](examples/custom_metrics.py) example defines reusable rubrics, and
355
+ the [LangChain tool guard](examples/langchain_guarded_tools.py) example demonstrates
356
+ guarding an agent's tool calls.
357
+
358
+ ## Development
359
+
360
+ ```bash
361
+ python -m pip install -e '.[calibration,dev,langchain,crewai,agent-framework]'
362
+ pytest --cov=typed_evals --cov-report=term-missing
363
+ ruff check .
364
+ ruff format --check .
365
+ python -m build
366
+ ```
367
+
368
+ Tests cover SDK serialization, retries, evaluation, calibration, runtime enforcement,
369
+ and native LangChain, CrewAI, and Microsoft Agent Framework tool dispatch with fake judges.
370
+ CI installs all framework extras so integration tests run. Without an extra, that
371
+ framework's integration tests are skipped. The optional live smoke test
372
+ makes a billable API call only with both `TYPED_EVALS_LIVE=1` and `TYPESAFE_API_KEY` set.