For the complete documentation index, see llms.txt. Markdown versions are available by appending .md to documentation URLs.

AI Traces Query API - Query LLM Cost and Tool Calls

SigNoz Cloud - This page applies to SigNoz Cloud editions.
Self-Host - This page applies to self-hosted SigNoz editions.

The builder_ai_query query type runs queries against your AI traces, which are traces with at least one LLM, tool, or agent span. It adds per-trace fields such as tool call count and estimated cost, so you can filter, aggregate, and order AI traces programmatically. Use it when you want the data behind the AI Observability Explorer without the UI.

API endpoint

builder_ai_query uses the same endpoint, authentication, and top-level payload as the rest of the Trace API:

POST https://<your-signoz-url>/api/v5/query_range

Replace <your-signoz-url> with the URL that you use to open SigNoz in a browser, for example <your-workspace>.<region>.signoz.cloud for SigNoz Cloud.

See the Trace API overview for the API key and header setup, and the payload model for the start, end, requestType, and compositeQuery fields.

To use this query type, set type to builder_ai_query inside a query envelope and keep signal as traces:

{
  "type": "builder_ai_query",
  "spec": {
    "name": "A",
    "signal": "traces"
  }
}

The spec accepts the same fields as a builder query (filter, selectFields, aggregations, groupBy, order, limit, stepInterval). The difference is that builder_ai_query also exposes the AI trace fields below.

Fields for AI queries

Two kinds of fields are available in AI queries.

Trace fields hold a total for the whole trace. Use them in filter, in aggregations, and in order. With requestType: trace, SigNoz uses only the spans inside start and end to select traces. filter tests those spans, and order uses them to select the traces for the page. The returned totals include every span of the trace, even spans outside start and end. SigNoz sorts the page by these full totals. So a returned trace can show totals that differ from the values that filter tested. With raw, scalar, and time_series, totals include only spans inside the query range.

FieldTypeHolds
trace.tool_call_countintNumber of tool calls in the trace.
trace.distinct_tool_countintNumber of different tools called in the trace.
trace.estimated_total_costfloatEstimated cost of all LLM calls in the trace. See Model pricing for how cost is computed.

The Explorer lists the full set of trace fields, including trace.llm_call_count, trace.input_tokens, trace.output_tokens, trace.total_tokens, and trace.max_llm_duration_nano. See Run a query for the complete table.

Span attributes come from the GenAI semantic conventions. Reference them with fieldContext: attribute in selectFields and groupBy.

AttributeHolds
gen_ai.request.modelThe model that the call requested, for example gpt-4o.
gen_ai.tool.nameThe name of a tool called by the model.
gen_ai.usage.input_tokensThe number of input tokens consumed.
gen_ai.usage.output_tokensThe number of output tokens produced.

For every attribute that SigNoz reads from GenAI spans and the source keys it maps by default, see AI Observability Telemetry Requirements.

Examples

All examples use type: builder_ai_query and signal: traces. The start and end values are epoch timestamps in milliseconds; replace them with your query range. stepInterval accepts a number of seconds (60) or a duration string ("60s").

Raw spans from AI traces with many tool calls

Return up to 100 spans from the ai-agent service whose trace has more than 10 tool calls, newest first. requestType: raw returns individual spans.

{
  "schemaVersion": "v1",
  "start": 1640995200000,
  "end": 1640998800000,
  "requestType": "raw",
  "compositeQuery": {
    "queries": [
      {
        "type": "builder_ai_query",
        "spec": {
          "name": "A",
          "signal": "traces",
          "filter": {
            "expression": "service.name = 'ai-agent' AND trace.tool_call_count > 10"
          },
          "order": [
            {
              "key": {
                "name": "timestamp",
                "fieldContext": "span"
              },
              "direction": "desc"
            }
          ],
          "limit": 100
        }
      }
    ]
  }
}

Raw spans with selected gen_ai fields

The same filter as above, with explicit output columns: the span name plus the requested model, tool name, and input and output token counts.

{
  "schemaVersion": "v1",
  "start": 1640995200000,
  "end": 1640998800000,
  "requestType": "raw",
  "compositeQuery": {
    "queries": [
      {
        "type": "builder_ai_query",
        "spec": {
          "name": "A",
          "signal": "traces",
          "filter": {
            "expression": "service.name = 'ai-agent' AND trace.tool_call_count > 10"
          },
          "selectFields": [
            {
              "name": "name",
              "fieldContext": "span"
            },
            {
              "name": "gen_ai.request.model",
              "fieldContext": "attribute"
            },
            {
              "name": "gen_ai.tool.name",
              "fieldContext": "attribute"
            },
            {
              "name": "gen_ai.usage.input_tokens",
              "fieldContext": "attribute"
            },
            {
              "name": "gen_ai.usage.output_tokens",
              "fieldContext": "attribute"
            }
          ],
          "order": [
            {
              "key": {
                "name": "timestamp",
                "fieldContext": "span"
              },
              "direction": "desc"
            }
          ],
          "limit": 100
        }
      }
    ]
  }
}

Average cost by model (scalar)

Compute the average estimated per-trace cost for each model, most expensive first. requestType: scalar returns one summary value per group. When you group by model, each model gets only the cost of its own spans, so a trace that calls two models does not count its full cost under both.

{
  "schemaVersion": "v1",
  "start": 1640995200000,
  "end": 1640998800000,
  "requestType": "scalar",
  "compositeQuery": {
    "queries": [
      {
        "type": "builder_ai_query",
        "spec": {
          "name": "A",
          "signal": "traces",
          "aggregations": [
            {
              "expression": "avg(trace.estimated_total_cost)"
            }
          ],
          "groupBy": [
            {
              "name": "gen_ai.request.model",
              "fieldContext": "attribute"
            }
          ],
          "order": [
            {
              "key": {
                "name": "avg(trace.estimated_total_cost)"
              },
              "direction": "desc"
            }
          ],
          "limit": 10
        }
      }
    ]
  }
}

Cost by model over time (time series)

Sum the estimated per-trace cost for each model in 60-second buckets. requestType: time_series with stepInterval is suited to trend charts.

{
  "schemaVersion": "v1",
  "start": 1640995200000,
  "end": 1640998800000,
  "requestType": "time_series",
  "compositeQuery": {
    "queries": [
      {
        "type": "builder_ai_query",
        "spec": {
          "name": "A",
          "signal": "traces",
          "aggregations": [
            {
              "expression": "sum(trace.estimated_total_cost)"
            }
          ],
          "stepInterval": "60s",
          "groupBy": [
            {
              "name": "gen_ai.request.model",
              "fieldContext": "attribute"
            }
          ],
          "order": [
            {
              "key": {
                "name": "sum(trace.estimated_total_cost)"
              },
              "direction": "desc"
            }
          ],
          "limit": 10
        }
      }
    ]
  }
}

Top traces by cost (trace list)

Return the 10 most expensive traces that have more than 10 tool calls but fewer than 3 distinct tools. requestType: trace returns one row per trace.

{
  "schemaVersion": "v1",
  "start": 1640995200000,
  "end": 1640998800000,
  "requestType": "trace",
  "compositeQuery": {
    "queries": [
      {
        "type": "builder_ai_query",
        "spec": {
          "name": "A",
          "signal": "traces",
          "filter": {
            "expression": "trace.tool_call_count > 10 AND trace.distinct_tool_count < 3"
          },
          "order": [
            {
              "key": {
                "name": "trace.estimated_total_cost"
              },
              "direction": "desc"
            }
          ],
          "limit": 10
        }
      }
    ]
  }
}

Next steps

Is this page helpful

Last updated—October 28, 2026

Edit on GitHub