Resource library

QA How-To

How to Choose an LLM Evaluation Framework (2026)

Learn how to choose llm evaluation framework options by comparing metrics, CI support, datasets, observability, cost, security, portability, and extensibility.

22 min read | 2,954 words

TL;DR

Choose the framework that best matches your dominant evaluation unit and delivery workflow. Promptfoo is a strong default for cross-model prompt regression in CI, DeepEval fits Python test suites and custom metrics, Ragas specializes in RAG quality, and an observability platform is useful when production traces and feedback are the main requirement.

Key Takeaways

  • Start with the decision your evaluation must protect, then select metrics and tooling.
  • Use Promptfoo for configuration-driven model and prompt matrices with straightforward CI gates.
  • Use DeepEval for Python-native unit-style tests and custom LLM-as-a-judge metrics.
  • Use Ragas when retrieval and answer quality are the central risks in a RAG system.
  • Require dataset versioning, raw result export, deterministic checks, and repeat trials before adopting a framework.
  • Run a small proof of concept with your own failures instead of choosing from feature lists.
  • Keep product telemetry and offline regression evaluation connected, but do not confuse monitoring with testing.

If you are deciding how to choose LLM evaluation framework tooling, begin with the failures you need to catch and the release decision you need to make. Do not begin with a vendor checklist. A support chatbot, a retrieval system, and a tool-using agent have different evaluation units, evidence, and acceptable error rates.

The practical choice is usually not one permanent winner. Select one primary regression runner, keep datasets and results portable, and add production observability only when it answers a separate question. This guide gives you a repeatable selection process and a runnable proof of concept. For the broader discipline, read the RAG application evaluation guide.

TL;DR

If your dominant need is Start with Why Main caution
Prompt and model comparison in CI Promptfoo Declarative matrices, assertions, red-team support, readable reports Complex custom logic can become awkward in YAML
Python-native LLM tests DeepEval Pytest-like workflow, built-in metrics, custom GEval criteria Judge-backed metrics require calibration and incur model cost
Retrieval-augmented generation quality Ragas Metrics and dataset concepts are designed around query, context, and response It is narrower than a general release-testing system
Production traces and human feedback LangSmith, Phoenix, or another observability platform Connects traces, datasets, experiments, and feedback Hosted workflow and retention rules can create lock-in
Fully controlled scoring A thin custom harness Exact schemas, local rules, and no framework coupling You own reports, concurrency, retries, and integrations

For most QA teams, shortlist Promptfoo and DeepEval, then include Ragas only if retrieval is a first-class component. Run the same 20 to 50 representative cases through each finalist. Compare authoring effort, reproducibility, failure diagnostics, CI output, execution time, and exportability.

What You Will Build

You will create a small, framework-neutral evaluation dataset and use it to make an evidence-based choice. By the end, you will have:

  • A weighted requirements scorecard tied to release risks.
  • A versioned JSONL dataset containing deterministic and semantic expectations.
  • A runnable local baseline evaluator with machine-readable output.
  • A Promptfoo proof of concept that evaluates the same behavioral contract.
  • A DeepEval proof of concept for Python-native semantic scoring.
  • A decision record that documents the winner, rejected alternatives, and an exit plan.

The examples evaluate a customer-support answer. The target must include an order identifier, avoid inventing a refund, and answer the user's request. This mix matters because exact assertions and semantic judgment should coexist.

Prerequisites

Use Node.js 20 or newer and Python 3.11 or newer. Confirm both runtimes before installing anything:

node --version
python3 --version

Create a disposable directory and Python environment:

mkdir llm-eval-selection
cd llm-eval-selection
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip

You need an API key only for judge-backed or live-model runs. Keep it in the shell or CI secret store, never in datasets, configuration committed to Git, or captured result artifacts. The local baseline below needs no network access. When you evaluate a real application, expose a stable adapter such as an HTTP endpoint or a function that accepts one test input and returns a structured response.

Verify the workspace before continuing:

test -d .venv && node -e "console.log('workspace ready')"

Expected output is workspace ready.

Step 1: Define How to Choose LLM Evaluation Framework Criteria

Translate product risk into capabilities. A framework should not receive points merely because it has many metrics. Give it points when it can provide evidence for a release decision. For a RAG assistant, retrieval recall and citation support may dominate. For a structured extractor, JSON schema validity and field accuracy matter more than answer relevance. For an agent, tool selection, arguments, side effects, and termination require trace-aware assertions.

Create scorecard.json:

{
  "criteria": [
    {"name": "deterministic_assertions", "weight": 20},
    {"name": "semantic_metrics", "weight": 15},
    {"name": "ci_integration", "weight": 15},
    {"name": "failure_diagnostics", "weight": 15},
    {"name": "dataset_portability", "weight": 10},
    {"name": "rag_support", "weight": 10},
    {"name": "production_traces", "weight": 5},
    {"name": "cost_controls", "weight": 5},
    {"name": "self_host_option", "weight": 5}
  ]
}

Weights must total 100. Score each candidate from 0 to 5 and calculate sum(weight * score / 5). Use zero when a required capability is absent, not when you have not researched it. Mark unknowns separately and test them during the proof of concept.

Verify the scorecard:

node -e "const s=require('./scorecard.json'); const n=s.criteria.reduce((a,c)=>a+c.weight,0); if(n!==100) process.exit(1); console.log(n)"

Expected output is 100. This simple check prevents a visually persuasive but mathematically distorted comparison.

Step 2: Build a Representative Evaluation Dataset

A tool comparison based on toy arithmetic prompts tells you little about your system. Sample real failure categories: unsupported claims, wrong retrieval, missed constraints, malformed structure, unsafe tool calls, excessive latency, and refusal mistakes. Include ordinary successes too, because a framework that only sees adversarial cases can optimize your process around rare behavior. The golden dataset guide explains how to curate and maintain these cases.

Create cases.jsonl with one JSON object per line:

{"id":"refund-pending","input":"Where is refund R-104?","output":"Refund R-104 is still processing. I cannot confirm a completion date.","mustContain":["R-104"],"mustNotContain":["completed","guaranteed"],"maxChars":180}
{"id":"refund-unknown","input":"Did refund R-999 complete?","output":"I cannot find refund R-999. Verify the reference or contact support.","mustContain":["R-999"],"mustNotContain":["completed","paid"],"maxChars":180}

Each record has a stable ID, input, captured candidate output, and deterministic requirements. In a real suite, replace output with a call to the system under test, but retain captured outputs for fast smoke checks. Keep expected facts distinct from a reference answer so models are not penalized for harmless wording changes. Store retrieved contexts, expected tool calls, or schema expectations when the application needs them.

Verify that every line is valid and IDs are unique:

node -e "const fs=require('fs');const rows=fs.readFileSync('cases.jsonl','utf8').trim().split('\n').map(JSON.parse);if(new Set(rows.map(x=>x.id)).size!==rows.length)process.exit(1);console.log(rows.length+' valid cases')"

Expected output is 2 valid cases. Your production proof should use enough cases to cover every high-risk behavior, usually dozens rather than two.

Step 3: Establish a Portable Deterministic Baseline

Before comparing semantic frameworks, prove that the dataset can drive an evaluator without one. This baseline exposes which requirements do not need an LLM judge. Exact substrings, JSON Schema, regular expressions, tool names, citation identifiers, latency budgets, and HTTP status codes are cheaper and more reproducible than subjective scoring.

Create evaluate.mjs:

import { readFile, writeFile } from 'node:fs/promises';

const text = await readFile('cases.jsonl', 'utf8');
const cases = text.trim().split('\n').map(JSON.parse);
const results = cases.map((test) => {
  const failures = [];
  for (const value of test.mustContain) {
    if (!test.output.includes(value)) failures.push(`missing:${value}`);
  }
  for (const value of test.mustNotContain) {
    if (test.output.toLowerCase().includes(value.toLowerCase())) {
      failures.push(`forbidden:${value}`);
    }
  }
  if (test.output.length > test.maxChars) failures.push('too_long');
  return { id: test.id, pass: failures.length === 0, failures };
});
await writeFile('results.json', JSON.stringify(results, null, 2));
const failed = results.filter((result) => !result.pass);
console.log(`${results.length - failed.length}/${results.length} passed`);
process.exitCode = failed.length ? 1 : 0;

Run it:

node evaluate.mjs
node -e "const r=require('./results.json'); if(!r.every(x=>x.pass)) process.exit(1); console.log('result schema readable')"

Expected output includes 2/2 passed and result schema readable. The exported JSON is also an exit test: any shortlisted framework must preserve case IDs, assertion details, and scores in a format you can archive or transform.

Step 4: Compare the Framework Families

The best LLM evaluation tools solve different layers of the problem. Separate runner, metric library, experiment tracker, and production observability in your scorecard even when one product bundles them. This avoids selecting an excellent trace viewer as if it were a complete release gate.

Dimension Promptfoo DeepEval Ragas Observability platform Custom harness
Primary interface YAML or JavaScript configuration and CLI Python tests and CLI Python datasets and metrics SDK plus hosted or self-hosted UI Your language and schema
Strongest fit Prompt, provider, and red-team matrices Unit-style LLM tests and custom judges RAG retrieval and generation evaluation Traces, experiments, annotation, feedback Narrow deterministic contracts
CI ergonomics Strong CLI exit behavior Familiar to Python and pytest teams Requires you to design the surrounding gate Depends on platform and SDK Entirely your responsibility
Deterministic assertions Built in Can combine with ordinary test assertions Not its central advantage Usually supported through evaluators Excellent
Semantic evaluation Model-graded and similarity assertions Built-in metrics and GEval RAG-focused metrics Platform evaluators Must implement or call a judge
Portability risk Config and output conversion Python metric coupling Dataset and metric coupling Trace and experiment model coupling Low framework lock-in, high maintenance

Promptfoo is compelling when a QA engineer needs to compare several prompts and providers without building a test runner. Its configuration is reviewable, and a CLI fits pull-request checks. Read the Promptfoo CI tutorial when that workflow matches your release process.

DeepEval fits teams already expressing quality checks as Python tests. It offers metrics for common LLM behaviors and supports GEval criteria for product-specific judgment. Its key selection question is whether its test-case abstractions match your outputs. The DeepEval versus Ragas comparison explores that narrower decision.

Ragas deserves extra weight when retrieved contexts are explicit evaluation inputs. It helps organize metrics such as faithfulness and context-oriented quality, but it does not remove the need for dataset governance, deterministic assertions, or CI policy. Observability platforms become stronger when you need trace sampling, annotation queues, user feedback, and online experiments. A custom harness remains sensible for small, regulated, or highly structured systems, provided you budget for reporting and maintenance.

Verify this step by recording a 0 to 5 score for every criterion and adding a note with evidence. A score without a proof command, screenshot, exported artifact, or documentation reference is provisional.

Step 5: Run a Promptfoo Proof of Concept

Install Promptfoo locally so the version is captured by the lockfile:

npm init -y
npm install --save-dev promptfoo
npx promptfoo --version

Create promptfooconfig.yaml. The echo provider makes this example runnable without an API key and isolates assertion behavior from provider variability:

description: Framework selection proof of concept
providers:
  - echo
prompts:
  - '{{output}}'
tests:
  - vars:
      output: 'Refund R-104 is still processing. I cannot confirm a completion date.'
    assert:
      - type: contains
        value: R-104
      - type: not-contains
        value: completed
      - type: javascript
        value: output.length <= 180
  - vars:
      output: 'I cannot find refund R-999. Verify the reference or contact support.'
    assert:
      - type: contains
        value: R-999
      - type: not-contains
        value: completed

Run and export the evaluation:

npx promptfoo eval -c promptfooconfig.yaml --output promptfoo-results.json
npx promptfoo eval -c promptfooconfig.yaml --no-cache

The command should report passing assertions and exit successfully. Inspect whether the JSON preserves useful identifiers, assertion reasons, provider metadata, and timing. Then replace echo with your actual provider or application adapter and add one semantic assertion. Repeat with caching disabled to see true model variance and cost. Never let cached responses conceal a nondeterministic regression.

Evaluate authoring friction too. Ask a teammate unfamiliar with the config to add a third case. If a basic change requires a framework specialist, that cost belongs in your scorecard.

Step 6: Run a DeepEval Proof of Concept

Install DeepEval in the active virtual environment:

python -m pip install deepeval
python -c "import deepeval; print('deepeval import ok')"

Create test_refunds.py. Begin with normal Python assertions, which run without a judge model:

import json
from pathlib import Path

CASES = [json.loads(line) for line in Path('cases.jsonl').read_text().splitlines()]

def test_refund_contracts():
    for case in CASES:
        for required in case['mustContain']:
            assert required in case['output'], case['id']
        for forbidden in case['mustNotContain']:
            assert forbidden.lower() not in case['output'].lower(), case['id']
        assert len(case['output']) <= case['maxChars'], case['id']

Verify the deterministic layer:

python -m pip install pytest
python -m pytest -q test_refunds.py

Expected output shows one passing test. Next, create test_relevancy.py for an actual DeepEval metric:

from deepeval import assert_test
from deepeval.metrics import AnswerRelevancyMetric
from deepeval.test_case import LLMTestCase

def test_answer_relevancy():
    case = LLMTestCase(
        input='Where is refund R-104?',
        actual_output='Refund R-104 is still processing. I cannot confirm a completion date.'
    )
    metric = AnswerRelevancyMetric(threshold=0.7)
    assert_test(case, [metric])

Set the model credential required by your configured judge, then run:

python -m pytest -q test_relevancy.py

Judge scores can vary, so 0.7 is an illustrative starting threshold, not a universal quality boundary. Calibrate it against blinded human labels, record the judge model and prompt, and repeat borderline cases. The LLM nondeterminism testing guide shows why a single pass is weak evidence.

Step 7: Measure Reliability, Cost, and Diagnostics

A framework can produce plausible scores and still be unsuitable for release control. Run each finalist on the same frozen dataset at least three times with caches disabled. Capture wall time, judge calls, token usage when available, failed case IDs, raw reasons, and process exit status. For a serious selection, include one intentionally broken output per failure category and verify that the framework detects it. This is mutation testing for the evaluator.

Do not compare only aggregate averages. A 0.85 mean can hide a safety-critical case scoring 0.20. Require per-case results, slices by risk category, and a maximum allowed count of critical failures. Use confidence intervals or repeated-trial pass rates for noisy metrics. For deterministic assertions, demand identical results on every run.

Diagnostics should tell an engineer what changed. faithfulness: 0.62 is less actionable than a reason identifying the unsupported sentence and the context that failed to support it. Confirm that judge rationales are stored safely because prompts and traces may contain personal or confidential data. Check redaction, retention, access control, regional storage, and deletion behavior before sending production traces to a hosted service.

Create a simple evidence table in your decision record:

Evidence Candidate A Candidate B Acceptance rule
Deterministic detection 10/10 mutations 10/10 mutations All detected
Repeated semantic stability Record observed result Record observed result Team-defined bound
Median local runtime Measure it Measure it Fits PR budget
Actionable failure reasons Reviewer score Reviewer score At least 4/5
Raw export usable Yes or no Yes or no Required

Verify by rerunning both proof-of-concept commands from a clean checkout. If undocumented local state is required, the candidate is not CI-ready.

Step 8: Decide, Pilot, and Define an Exit Plan

Calculate weighted totals, but do not let a high score override a failed mandatory requirement. Select the smallest stack that covers the dominant risk. A common outcome is Promptfoo for configuration-driven regression plus a production tracing tool. A Python-heavy RAG team may choose DeepEval or Ragas, ordinary pytest assertions, and its existing observability system.

Pilot the winner for two release cycles. Define ownership for datasets, metric changes, flaky eval triage, cost review, and framework upgrades. Pin dependencies, record judge versions, and treat evaluator prompt changes like test-code changes. A release threshold should be derived from baseline performance and business risk, not copied from a tutorial. Use the regression threshold guide to formalize the gate.

Your architecture decision record should include the application boundary, alternatives, weighted scores, proof-of-concept commit, measured costs, security findings, decision, review date, and exit plan. The exit plan is concrete: datasets remain JSONL or another open representation, case IDs survive exports, custom metrics have documented formulas, and raw results can be transformed without the vendor UI.

Verify the final choice with one command that returns nonzero when a critical regression is introduced. Run it in a pull request and archive its machine-readable result. A dashboard that someone must remember to inspect is not a release gate.

Which Should You Choose When Learning How to Choose LLM Evaluation Framework Tools

Choose Promptfoo when your test matrix is naturally prompts x providers x cases, configuration review matters, and CI is the primary execution environment. Choose DeepEval when developers own Python tests, want metric objects next to test cases, and expect to write custom judge criteria. Choose Ragas when your core evidence consists of questions, retrieved contexts, responses, and reference facts, and retrieval diagnosis outweighs broad provider comparison.

Choose an observability platform when production traces, annotation, feedback, experiment tracking, and team workflows are more important than a local test runner. Confirm that it still provides a reliable CI API or pair it with a runner. Choose a custom harness when outputs are highly structured, deterministic checks dominate, data cannot leave your environment, or framework abstractions create more work than they save.

If two candidates remain close, prefer the one that makes failures easiest to reproduce and datasets easiest to export. Metric count is a weak tie-breaker. Your team will spend more time understanding regressions, reviewing case changes, and operating the suite than browsing a catalog of evaluators.

Interview Questions and Answers

A strong interview explanation starts with risk and evaluation units, then distinguishes deterministic assertions, model-based metrics, human review, and online monitoring. It should also explain how a framework participates in a release decision. The structured interview questions below cover the most useful discussion points without duplicating the selection tutorial.

Common Mistakes

Choosing by popularity -> Map the tool to application failures and prove it on your dataset. Community activity matters for maintenance, but it cannot establish fitness.

Using an LLM judge for exact rules -> Validate schema, required fields, tool names, citations, and forbidden content deterministically. Save judge calls for qualities that require interpretation.

Treating one score as ground truth -> Keep metric components and per-case evidence. Aggregate scores hide severe failures and category imbalance.

Copying thresholds from examples -> Calibrate thresholds with human-labeled examples and known regressions. Different judges, prompts, domains, and risk tolerances change score meaning.

Evaluating only happy paths -> Include ambiguous inputs, missing context, injection attempts, provider errors, long conversations, and tool failures. Weight cases according to impact without erasing rare critical risks.

Ignoring nondeterminism -> Repeat trials, pin controllable settings, report pass rates, and quarantine unstable judge metrics until calibrated. Do not solve noise by lowering every threshold.

Confusing offline evaluation with monitoring -> Offline suites support repeatable comparisons before release. Online monitoring reveals distribution shifts and real user failures. Connect them by promoting production failures into reviewed regression cases.

Locking evidence inside a UI -> Export datasets, raw responses, scores, reasons, metadata, and trace links. Test the export before procurement, not after migration becomes urgent.

Sending sensitive traces without review -> Apply redaction and least-privilege access. Verify retention and deletion instead of assuming an evaluation product inherits your application's controls.

Troubleshooting

The same case passes and fails across runs -> Separate deterministic assertions from judge metrics, disable caches during reliability tests, pin the judge, and run repeated trials. Review borderline cases rather than immediately weakening the threshold.

CI passes locally but fails in the runner -> Pin Node and Python versions, lock dependencies, declare credentials as secrets, and remove reliance on shell profiles or local caches. Reproduce from a clean container.

Judge costs grow unexpectedly -> Run cheap deterministic checks first, evaluate only changed or risk-selected cases on pull requests, cache stable development experiments, and reserve full uncached suites for scheduled or release runs.

RAG scores do not explain retrieval failures -> Store retrieved contexts and document IDs with every case. Add direct recall-at-k or expected-document assertions instead of asking an answer-level judge to infer retrieval behavior.

Reports cannot identify the failing dataset row -> Require stable case IDs in input and output. Reject adapters that collapse results into an aggregate without an exportable mapping.

A framework upgrade changes scores -> Pin the package and judge configuration, rerun a calibration set before upgrading, compare distributions, and record intentional threshold changes in review.

Where To Go Next

Turn the proof of concept into a maintained regression suite. Expand the dataset with reviewed production failures, define risk slices, and assign owners for cases and metrics. For retrieval-heavy systems, use the RAG evaluation guide. For CI implementation, follow building evals with Promptfoo. For framework-specific trade-offs, examine DeepEval versus Ragas.

Keep the first rollout narrow. Gate one meaningful behavior, prove that engineers can diagnose failures, and measure operational cost. Add metrics only when each metric protects a named product requirement.

Conclusion

The reliable answer to how to choose LLM evaluation framework tooling is to compare candidates against your own risk model, dataset, and release workflow. Promptfoo, DeepEval, Ragas, observability platforms, and custom harnesses each optimize a different evaluation layer. There is no benefit in forcing one tool to own every layer.

Build a portable dataset, retain deterministic checks, run a small proof of concept, measure repeated behavior, and require an actionable CI failure. That process produces a defensible choice and leaves your team free to change tools as the application evolves.

Interview Questions and Answers

How would you select an LLM evaluation framework for a new product?

I would identify high-impact failure modes and the release decisions the evaluation must support. Then I would weight requirements such as deterministic assertions, semantic metrics, dataset support, CI behavior, diagnostics, security, cost, and exportability. I would run finalists against the same representative dataset, including intentionally broken outputs, and choose based on measured evidence rather than feature count.

What is the difference between an evaluation runner and an observability platform?

An evaluation runner executes controlled cases and assertions, commonly before release. An observability platform captures production traces, feedback, metadata, and experiments across real traffic. Products may combine both, but I evaluate the capabilities separately because a rich trace UI does not automatically provide a deterministic CI gate.

When would you prefer deterministic metrics over an LLM judge?

I use deterministic metrics whenever correctness can be expressed directly, including schema validity, required identifiers, numeric calculations, citation IDs, tool arguments, and forbidden claims. They are cheaper, faster, and reproducible. I reserve an LLM judge for qualities such as relevance or tone that genuinely require semantic interpretation.

How do you validate an LLM-as-a-judge metric?

I build a blinded, human-labeled calibration set containing clear and borderline examples. I compare judge decisions with reviewers, analyze disagreements by category, repeat runs to measure stability, and inspect reasons for position or verbosity bias. I then version the judge model, rubric, prompt, and threshold together.

Why is a single aggregate evaluation score risky?

An average can hide a critical failure in a small safety or compliance slice. It also loses the diagnostic difference between retrieval, generation, structure, and latency problems. I retain per-case and per-category results, then apply hard gates to critical cases alongside aggregate trend thresholds.

How would you test an evaluation framework before adoption?

I would use a frozen dataset with stable IDs, ordinary successes, edge cases, and seeded faults. I would run repeated uncached trials, verify nonzero CI exit behavior, review failure explanations, measure runtime and judge usage, and test raw export. I would also ask another engineer to add a case to expose authoring and maintenance friction.

How do you manage nondeterminism in an LLM regression suite?

I separate exact assertions from probabilistic metrics, pin controllable model settings, record model and evaluator versions, and run repeated trials for noisy cases. I report pass rates or score distributions instead of treating one run as truth. Persistent borderline cases go through calibration or human review rather than silently receiving a lower threshold.

Frequently Asked Questions

What is the best LLM evaluation framework for CI?

Promptfoo is a strong starting point for configuration-driven prompt and provider comparisons because its CLI and assertions fit CI workflows. DeepEval is often better for Python teams that want evaluation cases beside unit tests. The best choice is the one that reliably exits on your critical failures and exports useful per-case evidence.

Should I use DeepEval or Ragas?

Use DeepEval for broad Python-native LLM testing, custom judge criteria, and unit-style integration. Use Ragas when retrieval contexts and RAG-specific quality are central to the evaluation model. Test both with the same representative cases if retrieval is important but not the application's only behavior.

Can I evaluate an LLM without another LLM as a judge?

Yes. Use exact matches, JSON Schema, regular expressions, required facts, forbidden content, tool-call assertions, retrieval recall, latency, and executable task checks. Human review and model judges are useful for subjective qualities, but they should not replace deterministic evidence.

How many examples do I need to compare evaluation frameworks?

Begin a proof of concept with 20 to 50 cases spanning every important failure category, then expand based on coverage and observed production failures. The category mix matters more than an arbitrary total. Include known bad outputs so you can measure whether each framework detects them.

How should I set LLM evaluation thresholds?

Calibrate thresholds against human-labeled examples and known regressions using the exact judge configuration you will run. Inspect per-category behavior and repeat borderline cases. Do not copy a universal value because score distributions vary by metric, judge, prompt, and domain.

Do I need both offline evaluation and production observability?

Usually, once the application reaches production. Offline evaluation provides repeatable pre-release comparisons, while observability captures real traffic, traces, feedback, and distribution changes. Feed reviewed production failures back into the offline dataset.

How do I avoid LLM evaluation vendor lock-in?

Keep source datasets in a portable format, assign stable case IDs, export raw outputs and metric details, and document custom scoring logic. Test data export during selection. Treat hosted experiments as a view over evidence you can retain, not the sole copy of that evidence.

Related Guides