# Classifications

Dimensions you define yourself — a set of categories, and an LLM that sorts every session, trace, or issue into them.

A **classification** is a question you want asked of every conversation. You name the question, list the answers it may give, and Brizz runs a classifier over your traffic that assigns one — "which product area was this about?", "why did this run produce nothing?", "what kind of task was the user trying to do?"

Where [user intents](/docs/platform/analyze/user-intents.md) are *discovered* for you, a classification is *declared* by you. Both end up as a dimension you can filter and group by; the difference is who decides what the categories are.

## What it is

A classification has a **name**, a list of **categories** (each a value with an optional description), and optional **guidance** — free text telling the classifier how to decide. You choose whether it assigns **one category or several**, and which **scope** it runs over: sessions, traces, or issues.

Each one is bound to specific trace services, or to **all services** — present and future. Those two are exclusive: an empty service list on its own means bound to nothing, which is not the same as all.

Under the hood a classification is a [label](/docs/platform/labels.md) plus the classifier that populates it. That's the payoff — once it's running, its categories behave like any other label: filter [Sessions](/docs/platform/observe/sessions.md) by them, group charts by them, slice [Issues](/docs/platform/issues.md) with them.

Classifications carry an **origin**. Ones you create are `custom`. Brizz ships some of its own, marked with a sparkle in the list — those are read-only: you can read and filter by them, but not edit, pause, or delete them.

## Building one

The editor is a four-step wizard, and the order matters — each step narrows what the one before it exposed.

**1. Define.** Name it, pick the scope, and write the categories. A category is a value plus a description, and the description does real work: it's what the classifier reads when deciding whether a session belongs. Add guidance for the rules that apply across all categories — when to assign nothing, what to ignore, how to break a tie.

**2. Context scope.** Choose what the classifier is allowed to read: user turns, assistant turns, tool calls, system prompts, events, errors, reasoning. When tool calls are included you separately control whether tool **inputs**, **results**, and **errors** come with them, and whether the classifier can see which sub-agent produced what.

This is an exclusion at the data layer, not an instruction in a prompt. Anything you leave out never leaves the backend, so a classifier scoped to user turns alone cannot be talked into reading a system prompt or the raw body of a document your agent was processing. The default — user, assistant, and tool calls with their inputs, results, and errors — is deliberately not everything.

**3. Which sessions to classify.** Narrow the population with session filters, the same ones the [Sessions](/docs/platform/observe/sessions.md) page offers. You can also set a **sample percent**, keeping a fraction of matching sessions rather than all of them — the practical lever when the population is large and you only need the shape.

**4. When you save.** A classification only sees sessions that mature *after* it exists. This step is where you decide whether to also push history through it — see [Backfilling history](#backfilling-history).

### Previewing before you save

At any point you can run a **preview**: the classifier runs over a handful of recent sessions and returns, for each one, the category it assigned and its reasoning. The run is asynchronous — it reports progress as it goes and you can cancel it.

Read the reasoning, not just the verdict. A category assigned for the wrong reason will keep being assigned for the wrong reason at scale. Preview also reports sessions it **skipped**, meaning your context scope excluded everything that session had to offer — distinct from a session it read and matched to nothing, and usually a sign the scope is too tight.

Previewing is a loop, not a gate: adjust the categories, the guidance, or the context scope, and run it again.

### Backfilling history

A **backfill run** pushes existing sessions through a classification. Every run is windowed to a time range, and before you start one Brizz estimates its size: how many sessions matched, how many survive sampling, and how many LLM calls the run would make.

Read the LLM-call estimate rather than the session count. The classifier walks each session in rolling windows, so a session figure understates the real work several-fold. Large runs ask you to confirm; past a limit they're refused outright and you have to narrow the window.

A few things about a completed run:

- **Classified is lower than processed** whenever the runner declined a session — machine-generated ones are skipped outright rather than scored.
- **Failed chunks** mean a partial success: some batches errored and their sessions were left unclassified. Re-run that window.
- **Only previously matched** re-scores just the sessions this classification already labeled, which is what you want after editing categories rather than after creating them.

## How to read it in the dashboard

The **list** shows one row per classification with its scope, its bindings, and three numbers: **volume** (how many items carry it), **coverage** (what share of the eligible population it reached), and **issue rate** (how often its items also carry an issue). Toggle a custom classification off to pause it without losing its history.

Open a row for the **detail** view:

- **KPI cards** — volume, coverage, issue rate, the **worst category** by issue rate, and the category count. Worst category is the one to look at first; it's where a declared dimension turns into a finding.
- **Category distribution** — a bar per category, plus an **Unclassified** bucket for the items the classifier reached but matched to nothing. A dominant Unclassified bucket flattens everything else, so you can hide it while reading the real categories.
- **Click any bar** to open exactly the sessions behind it. Clicking Unclassified opens the complement — sessions this classification never labeled.

Coverage and the Unclassified bucket read as **unavailable** for some bindings — a tenant-wide classification has no cheap, correct denominator to compare against. The categories themselves are still exact.

## Renaming a category

Renaming a category is not a text edit — a category is identified by the value string the classifier wrote into every stored assignment. Rename it through the editor and Brizz moves the existing assignments to the new name. Change the string some other way and it reads as dropping one category and adding another: the new name starts empty, and the history goes with the old one.

## How to act on it

1. **Declare a dimension you already argue about.** The classifications that earn their keep are the ones answering a question your team asks weekly — which product area, which failure mode, which kind of request.
2. **Write descriptions, not just values.** `billing` is a label; "questions about invoices, payment methods, or refunds" is something a classifier can act on.
3. **Tighten the context scope deliberately.** A classifier that reads everything will classify the content your agent was processing rather than the conversation about it — the failure mode this step exists to prevent.
4. **Sample first, backfill later.** Run at a low sample percent to see whether the categories hold, then widen once they do.
5. **Read the worst category.** A dimension whose categories all carry the same issue rate isn't telling you anything; one with a clear outlier just localized a problem for you.

## Availability

Classifications are behind a tenant feature — if **Classifications** isn't in your navigation, [contact us](mailto:support@brizz.ai). **Viewing** is available to any member. **Creating, editing, and deleting** carry the same permissions as [labels](/docs/platform/labels.md), so they require admin or higher. Brizz-authored classifications are read-only regardless of role.

## See also

- [Labels](/docs/platform/labels.md) — what a classification becomes once it's running, and how to filter and group by it.
- [User intents](/docs/platform/analyze/user-intents.md) — the discovered counterpart to a declared dimension.
- [Sessions](/docs/platform/observe/sessions.md) — where a category's items open, and the filters step 3 is built from.
- [Issues](/docs/platform/issues.md) — the problems the issue-rate column is counting.
