Skip to main content
When a Signal has fired across thousands of traces, reading the event list by hand stops working. Clusters group similar events so you see patterns instead of scrolling.
Signal events page showing the cluster list with proportion bars next to a stacked frequency chart

What a cluster is

A cluster is a group of signal events whose summaries are semantically similar. Laminar generates a short summary of each event’s payload, embeds it, and groups events by meaning rather than by exact wording, so “timeout calling the payments API” and “payments request exceeded deadline” land in the same cluster. Clustering is scoped to a single Signal: events from different Signals never share a cluster. Read top-down when you want the shape of the problem (“most failures are tool loops”). Read bottom-up when you want the specific example (“this one loop is the config-validation tool calling itself twelve times”).
Clustering is fully automatic. There is nothing to enable per Signal and no thresholds to tune.

Where to find them

On any Signal detail page, open the Events tab. The clusters view sits below the events table, split into two resizable panels:
  • Left: the cluster list. Each row shows the cluster name, a proportion bar sized to its share of events, and the event count. Rows with sub-clusters expand in place; leaf clusters and the unclustered bucket have their own icons. Hover a row to see how many sub-clusters it has, its event count in the selected range, and when it was created and last updated.
  • Right: a stacked frequency chart. Each cluster is a stacked series over time, with a Signal runs overlay so you can read cluster volume against how often the Signal ran.
Both panels respect the page-level time range. Clicking a cluster filters the events table to that cluster’s members; clicking a sub-cluster narrows further. From any event you can jump to the trace that produced it.

How the hierarchy works

Clusters form a tree, up to a few levels deep:
  • Leaf clusters are the most specific named groups: events that describe near-identical behavior, like “config-validation tool retries in a loop”.
  • Parent clusters group similar leaf clusters into broader patterns, like “tool call loops”. A parent’s events are the union of its children’s events, so counts add up as you move up the tree.
  • The top level is a handful of broad categories that cover most of the Signal’s events. This is the view to start from during triage.
The hierarchy is not fixed upfront. It grows organically as events arrive: the first events of a new pattern form a leaf cluster, and when several related leaf clusters accumulate, a parent forms above them. Cluster names are generated by Laminar’s AI from representative sample events. Naming runs bottom-up: sub-clusters are named first, and each parent is then named with its children’s names in view, so a parent reads one abstraction level above its children instead of duplicating the name of its largest child. As new events shift what a cluster contains, its name is refreshed so it keeps describing the current members.
Below the named hierarchy there is an internal accumulation layer of small, unnamed groups. It is hidden from the UI and excluded from the clusters SQL table; it exists so that one-off events don’t produce noisy single-event clusters.

When events get clustered

Clustering runs asynchronously, after events are created:
  1. Every new signal event is queued for clustering together with its summary.
  2. Queued events for the same Signal are processed in batches. A batch runs once enough events accumulate, or shortly after the first event arrives, typically within a minute.
  3. Each event in the batch either joins the closest existing cluster or starts a new one. A new named cluster appears once a couple of similar events have arrived; until then, one-off events sit in the Unclustered bucket.
  4. If the batch created new clusters or meaningfully changed existing ones, names are generated or refreshed.
Two consequences worth knowing:
  • An event shows up in the events table immediately but can take a minute or two to land in a cluster. During a live incident, expect cluster counts to trail the event count slightly.
  • A genuinely new failure mode surfaces as a new cluster shortly after the second similar event arrives. Pair this with a New cluster alert to hear about emerging failure modes without watching the page.
Clusters are a view over the underlying events, not a copy. Deleting a Signal or purging events removes cluster membership automatically.

When clusters earn their keep

Clusters pay off when you have hundreds or thousands of events and an open-ended question:
  • Triage: “Of the 4,000 traces flagged by agent_failure this week, which handful of failure modes account for most of them?”
  • Regression detection: a cluster that was empty yesterday and full today is a new failure mode.
  • Prompt tuning: if a cluster contains events you don’t consider matches, your prompt is too broad. If expected events split across unrelated clusters, your payload schema isn’t capturing the discriminating fields.
If your Signal has a small, well-defined set of payload fields (say, a category enum with five values), grouping in the SQL Editor or a custom dashboard is usually enough. Reach for clusters when the events are free-form or when you don’t yet know what categories exist.

Querying clusters with SQL

Clusters are queryable in the SQL Editor:
  • The clusters table has one row per named cluster, including name, level, parent_id, and num_signal_events, so you can reconstruct the hierarchy or trend cluster sizes over time.
  • The signal_events table has a clusters column: the IDs of every cluster an event belongs to, from its most specific cluster up through its parents.

Next steps

Alerts

Fire Slack or email notifications on new signal events or clusters.

SQL Editor

Query the clusters and signal_events tables directly.