For the complete documentation index, see llms.txt. This page is also available as Markdown.

App Versioning & Experiments

Tag traces with application version and experiment variants

Distributional is now Talaria Scientific. The DBNL product described in these docs has been sunset; this documentation is preserved for reference. Read the announcement.

DBNL recognizes span attributes that tag every span with an application version and/or experiment_variants, and rolls those up onto the spans, traces, and sessions rows, populating the version and experiment_variants columns of the DBNL Semantic Convention. experiment_variants is filterable via the Experiment Filters in the Filter Builder wherever it appears (Logs, Explorer, and Segment creation), so you can compare model / prompt / retriever variants across those views. The version column is ingested for every trace but is not yet a first-class filter target in the UI.

The Python SDK exposes first-class context managers (dbnl.using_experiments, dbnl.using_version) that propagate these attributes onto every span in a block. Node.js applications set the same attributes directly via the OpenTelemetry API.

Application Version

The preferred way to tag traces with an application version is to pass version= to dbnl.init_tracing() once at startup. It sets service.version on the provider's OTel Resource, which DBNL picks up as the trace / session version column.

import dbnl

dbnl.login()
dbnl.init_tracing(
    project_id="{PROJECT_ID}",
    service_name="my-agent",
    version="2026.04.21",
)

For the rare case where a single process emits traces under multiple versions (blue/green, canary, replay), override per-trace with dbnl.using_version(...):

with dbnl.using_version("2026.04.21-canary"):
    agent.invoke({"input": user_query})

Set service.version on the Resource attached to your NodeSDK (or TracerProvider). DBNL picks it up as the trace / session version column.

import { NodeSDK } from "@opentelemetry/sdk-node";
import { Resource } from "@opentelemetry/resources";

const sdk = new NodeSDK({
  resource: new Resource({
    "service.name": "my-agent",
    "service.version": "2026.04.21",
  }),
  // ...spanProcessors as in the OTEL Trace Ingestion guide
});

To override the version for a specific trace (blue/green, canary, replay), set the dbnl.version attribute on the root span of that trace. DBNL prefers dbnl.version over service.version when populating the trace / session version column.

rootSpan.setAttribute("dbnl.version", "2026.04.21-canary");

Experiment Variants

Each entry in an experiment mapping is an independent experimental dimension you are A/B-ing (model, prompt, retriever, planner, etc.) mapped to the specific variant this invocation used.

Wrap an agent / chain invocation in dbnl.using_experiments({name: variant, ...}) to stamp experiment variants onto every span emitted inside the block, including every auto-instrumented LLM, tool, retriever, and agent-step span.

For a single experimental dimension, dbnl.using_experiment("llm_model", "gpt-5.4-nano") is a shorthand for the one-key case. Both are also usable as decorators and as async with context managers.

There are no first-class helpers in JS yet. Set the variants directly as span attributes on the root span of the trace. DBNL rolls trace-level attributes up from the root span, so this is enough for trace- and session-level filtering.

Each variant is encoded as a pair of indexed attributes:

To also stamp child spans (so spans.experiment_variants reflects them), either set the same attributes on each span you care about or install a custom SpanProcessor that reads the variants off the OTel Context at span start.

Rollup Semantics

DBNL reassembles stamped span attributes into the experiment_variants and version columns. The rollup differs by table:

  • spans: from each span's own attributes.

  • traces: from the trace's root span. In Python, the root span is emitted inside the with block, so variants propagate automatically; in Node.js, set the attributes on the root span explicitly.

  • sessions: from the session's first trace only. If you vary experiments across turns of a multi-turn session, only the first turn's variants land on the session row; to analyze the remaining turns, filter traces (or spans) by session_id.

Bring-Your-Own TracerProvider (Python)

dbnl.init_tracing() installs the dbnl context-stamp span processor automatically. If you manage your own TracerProvider without calling init_tracing(), add dbnl.get_dbnl_context_stamp_processor() to it yourself so that using_experiments / using_version have any effect: