> ## Documentation Index
> Fetch the complete documentation index at: https://laminar.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Signals

When your agent goes into production, the questions you care about are things like: *did it get stuck, did the user give up, did this run fail for a different reason than last week's*. You can answer them by opening a trace and reading it. You can't answer them across ten thousand traces.

**Signals are how Laminar answers them.** A Signal is an instruction, written in plain language, that reads every trace and produces a structured record when it sees what you described. The result is a stream of events you can **[query](/platform/sql-editor), [cluster](/signals/clusters), and [alert](/signals/alerts) on**.

<Frame caption="A Signal's events tab: each row is one detected event linked back to a trace">
  <img src="https://mintcdn.com/laminarai/UWEXa7uqWnwytmE6/images/signals/signal-detail.png?fit=max&auto=format&n=UWEXa7uqWnwytmE6&q=85&s=ee98755075684a5dacf01228179a8463" alt="Signal detail view with events list and per-event payload" width="1512" height="982" data-path="images/signals/signal-detail.png" />
</Frame>

## What Signals can help you answer

If you can describe it to a colleague, you can write a Signal for it.

* **Business outcomes**: "agent completed checkout," "agent answered the question correctly."
* **Logical failures**: "agent loops on the same tool without progress," "agent gave up after one retry."
* **Behavioral categorization**: user intent, topic, any categorical field you want on the trace.
* **User friction**: "user asked for the same information multiple times", "user gave up after multiple retries".
* **Cost and waste**: "long context, short answer," "tool called with malformed arguments and retried."

Essentially, **anything you've ever had to ask a teammate to skim traces for**. If you've written a Slack message that starts with "can you look through today's runs and tell me how often...", that's a Signal.

## Anatomy of a Signal

A Signal has three parts:

* **Prompt**: plain-language instructions that describe what the Signal should detect or extract from an agent trace.
* **Structured output schema**: a JSON schema the extracted payload must conform to.
* **Triggers**: trace conditions that must be met for the Signal to run.

That's everything you configure. The rest of this page explains what Laminar does with those three parts when a trace arrives.

## How a Signal run works

When a trace matches a Signal's trigger conditions, Laminar doesn't just paste the raw trace into a single LLM call. A Signal run is a small investigation, and it moves through three stages: compress the trace, let an agent investigate it, then turn what the agent found into events.

<Frame>
  <img src="https://mintcdn.com/laminarai/281c7dMO5OKwGsEE/images/ChatGPT-Image-Jul-2,-2026,-05_33_30-PM.png?fit=max&auto=format&n=281c7dMO5OKwGsEE&q=85&s=ce193f0d7b76d17d66f04b087b654e86" alt="Chat GPT Image Jul 2, 2026, 05 33 30 PM" width="1825" height="862" data-path="images/ChatGPT-Image-Jul-2,-2026,-05_33_30-PM.png" />
</Frame>

### 1. The trace is compressed

Agent traces are long. A single run can contain hundreds of spans, megabytes of tool output, and the same system prompt repeated on every LLM call. Before anything reads the trace, Laminar compresses it into a compact transcript:

* **LLM turns and tool calls are kept.** These carry the story of what the agent did.
* **Repeated system prompts are deduplicated and summarized**, so the transcript states them once instead of on every turn.
* **The user's original request is extracted** and placed up front, so the Signal always knows what the agent was asked to do.
* **Plumbing spans are dropped** unless they carry errors or match the Signal's relevance rules.

<Note>
  Traces are compressed to around 10% of it's original token count on average
</Note>

Compression is lossy on purpose, but nothing is out of reach: every span in the transcript keeps a short reference id, and the agent can use it to pull the full, uncompressed content of any span on demand.

### 2. An agent investigates the trace

Your prompt doesn't run as a one-shot classification. Laminar runs it as an **agent with tools**, working over the compressed transcript across multiple steps:

* It can **search within span content** to find where something happened.
* It can **fetch the full input and output of any span** by its reference id when the compressed view isn't enough.
* When it has seen enough, it **submits its findings** and the run ends.

This is what makes Signals reliable on long traces. A checkout failure buried in step 40 of a 200-step run isn't lost to truncation: the agent can search for it, pull the exact tool output, and base its answer on the actual content.

A run ends in one of two ways:

* The agent submits **one or more findings**. Each finding contains a payload that conforms to your schema, a short summary of what was found, and a severity (`critical`, `warning`, or `info`).
* The agent submits **nothing**, meaning the behavior you described wasn't present in that trace. No event is created.

A single trace can legitimately produce multiple findings: an agent that retried a broken tool three times produces three retry events, not one.

### 3. Findings become signal events

Each finding becomes a **signal event** linked back to the trace that produced it. From there, every event independently flows into the rest of the platform:

* It's **indexed for search**, so you can find it from the Signals UI.
* It's checked against your **alert rules** (severity and custom payload filters), and matching events fire [Alerts](/signals/alerts).
* It's queued for **clustering**, where Laminar groups it with similar events from other traces so patterns surface as [Clusters](/signals/clusters).

<Note>
  Signal events are accessible via the `signal_events` table and can be easily queried using the [SQL Editor](/platform/sql-editor). All signal events are linked to the traces that produced them. You can use event payloads to query corresponding traces. In a sense, you can think of a signal event payload as an additional column of the traces table.
</Note>

## Run a Signal on new traces or historical traces

Each Signal can run in two modes, configured independently:

* **Triggers** run the Signal on new traces as they arrive. Use Triggers for anything you want to watch in real time (live error rates, live success counts, anything that feeds Alerts). Trigger filters are AND-combined and are evaluated against accumulated trace state, so Signals fire once per matching trace.
* **Backfill** runs the Signal across a historical slice of traces. Use a backfill to seed a new Signal, re-run a changed prompt over last week's traffic, or investigate a window of traces that match a filter.

Both paths produce the same kind of signal event; the only difference is when and which traces the Signal reads.

## Next steps

<CardGroup cols={2}>
  <Card title="Quickstart" icon="play" href="/signals/quickstart">
    Write your first Signal, trigger it on new traces arriving in real-time, and see events.
  </Card>

  <Card title="Clusters" icon="boxes" href="/signals/clusters">
    Learn how Laminar groups similar signal events so you can see patterns.
  </Card>

  <Card title="Alerts" icon="bell" href="/signals/alerts">
    Fire Slack or email notifications on new signal events or clusters.
  </Card>
</CardGroup>
