Skip to main content
A score tells you that an item failed. The trace tells you why. When you run an experiment, the Fiddler Evals SDK captures the OpenTelemetry spans your task emits and links them to the experiment item that produced them. You get per-item traces in the UI for debugging, and your evaluators can score on the execution itself — tool call order, retry counts, token usage, latency — not just the final output string.

What You’ll Learn

  • How traces are captured during an experiment run, with no setup
  • How to score an evaluator on a captured trace
  • How to keep evaluation traces out of your production application
Time to complete: ~15 minutes

Prerequisites

  • A task instrumented with OpenTelemetry — either through a Fiddler integration or your own spans
  • A Fiddler API key from Settings > Credentials
  • Python 3.10 or later
  • Fiddler Evals SDK: pip install fiddler-evals
If you prefer a notebook, open the fully worked example in Google Colab or download it from GitHub.

There Is Nothing to Turn On

Trace capture is automatic. fiddler-otel is a base dependency of the Evals SDK, so evaluate() sets capture up on its own as long as it can resolve a Fiddler application for the dataset.
If your task emits spans, they are captured and linked. If it does not, nothing changes.
Evaluators bind to your task’s outputs by parameter name. The inputs bucket is passed through as a single dict, not spread into the namespace, so an evaluator cannot read a dataset input directly.AnswerRelevance.score() takes (user_query, rag_response), which is why the task above returns user_query as well as the answer. Omit it and the run fails with ScoreFunctionInvalidArgs: Missing required arguments ... ['user_query']. Alternatively, remap with score_fn_kwargs_mapping.
Capture is best-effort by design: evaluation must work for users who do no tracing at all. If setup fails, the SDK logs a warning and the experiment runs normally — the task still executes and the scores are still published. There is exactly one exception, covered in Keep evaluation traces out of production.

Score an Evaluator on the Trace

Declare a session parameter on your evaluator’s score function and the runner passes the captured spans to it. Parameter binding is by name, so evaluators that do not declare session are unaffected.
Always default session to None and handle the None case. Capture is best-effort, so an evaluator that assumes a session breaks the moment tracing is unavailable. EvalFn converts your return value for you: bool becomes 1.0 or 0.0, int and float pass through, and None produces a SKIPPED score. Return a Score directly when you want to control the reasoning text:
A Score you construct yourself requires both name and evaluator_name, and the explanation field is reasoning.

What a Session Contains

Your evaluator receives a Session with two attributes:
UUID
The experiment item’s ID. Equal to experiment_item.id.
list[dict]
The spans the task produced, in completion order.
Each span is a plain dict — no OpenTelemetry objects to import: Times are integer nanoseconds so duration is a plain subtraction with no precision loss:
Exceptions arrive as span events rather than attributes, which is where most instrumentations record them:
The span dict is deliberately a curated subset aimed at scoring. OpenTelemetry infrastructure fields — resource, links, and instrumentation scope — are omitted because they are constant or empty for eval runs. The full-fidelity span is still written to the trace store and visible in the UI, so nothing is lost.

Keep Evaluation Traces Out of Production

Evaluation traces are real traces, so send them to a dedicated pre-production application rather than the one serving live traffic. A process shares one global FiddlerClient. If one already exists and its application_id does not match the dataset’s application, evaluate() raises ValueError instead of degrading quietly — this is the one capture failure that is deliberately not best-effort, because silently mixing evaluation and production traffic is worse than a failed run. Point the dataset at its own application and the SDK handles the rest:
A golden dataset promoted from production spans necessarily belongs to the application that served those spans — span promotion resolves spans through the dataset’s application, and trace capture follows it. Replaying such a dataset writes its captured traces to that same application.

Next Steps