From signoz
Creates a SigNoz dashboard from a natural-language intent, importing curated templates (PostgreSQL, Redis, JVM, k8s, hostmetrics, APM, LLM) or building custom metric/trace/log panels.
How this skill is triggered — by the user, by Claude, or both
Slash command
/signoz:signoz-creating-dashboards <natural-language dashboard intent><natural-language dashboard intent>The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Build a SigNoz dashboard from a user's natural-language intent. The skill
Build a SigNoz dashboard from a user's natural-language intent. The skill targets two consumers: an autonomous AI SRE agent that runs without a human in the loop, and a human at a Claude Code / Codex / Cursor prompt. Both go through the same flow.
This skill calls SigNoz MCP server tools (signoz_create_dashboard,
signoz_list_dashboards, signoz_list_dashboard_templates,
signoz_import_dashboard, signoz_get_dashboard,
signoz_update_dashboard, signoz_list_metrics,
signoz_get_field_keys, signoz_get_field_values,
signoz_aggregate_logs, signoz_aggregate_traces, etc.).
Before running the workflow, confirm the signoz_* tools are
available. If they are not, the SigNoz MCP server is not installed or
configured — run signoz-mcp-setup first to initialize or repair the MCP
connection. Do not fall back to raw HTTP calls or fabricate dashboard JSON
without the MCP tools.
Use this skill when the user wants to:
Do NOT use when the user wants to:
signoz-modifying-dashboards.signoz-explaining-dashboards.signoz-generating-queries.Dashboard creation is a write operation. Guessing here clutters the shared workspace with empty or wrongly-scoped dashboards someone else has to clean up. The skill enforces a soft input contract — most fields have sensible defaults, but a few cannot be guessed:
| Input | Required | Source if missing |
|---|---|---|
| Dashboard intent (NL goal) | yes | $ARGUMENTS or recent user turn |
| Technology / domain (e.g. PostgreSQL, Redis, "payment pipeline") | yes | parse from intent; otherwise ask |
| Modify-or-create choice when duplicates exist | yes | ask the user (Step 2) |
| Resource scope for custom builds (service / namespace / cluster) | yes for custom builds | discover via signoz_get_field_keys + signoz_get_field_values; fall back to a dashboard variable |
| Specific metrics / signals for custom builds | inferred | derive from technology + MCP signoz://dashboard/* resources; surface in preview |
| Layout | inferred | apply defaults (see "Defaults" below) |
If a required input is missing and cannot be discovered, stop before
calling any write tool and ask the user. The host application decides
how the question is surfaced (a structured clarification tool, inline
<assistant_question> tags, an interactive prompt, etc.) — follow the
host's UI rendering rules.
What to include in the question:
service.name → frontend, checkout, payments, inventory;
k8s.cluster.name → prod-us-east-1, staging.In autonomous mode (no human), escalate to the caller or fill the gap
from upstream context. Either way, do not proceed to
signoz_create_dashboard / signoz_import_dashboard with
a guessed value.
The create path starts duplicate check → modify-or-create choice → template lookup. A matching template uses no-data probe → preview → import; a custom build uses no-data probe → build → per-panel dry-run → preview → create. Template lookup is internal; the user's only upfront choices are modify or create.
Call signoz_list_dashboards. Most installs fit in the default
page (limit=50); only paginate when pagination.hasMore=true. Use
pagination.nextOffset directly for the next page; the schema accepts
integer or string limit / offset values.
Match by relevance Compare each existing
dashboard's lowercased name, description, and tags against the
user's technology/domain. Surface only matches a human would recognize
as the same thing — a "redis" dashboard does not match a "postgresql"
request just because both have a database tag. Collect each match's
name, uuid, and createdAt for the next step.
Present exactly two options (no template-import as a separate top-level choice — that's an internal decision in Step 3b):
Wait for the user's choice. "modify" → Step 3a. "create new" / confirm → Step 3b. "stop" → stop.
Hand off immediately to signoz-modifying-dashboards with the chosen
dashboard UUID and the user's intent. Do not call
signoz_update_dashboard from this skill — modification is out
of scope. (See "Scope boundary" in Guardrails.)
Run the template lookup first. The user has already agreed to create new — the lookup decides how we build it.
Call signoz_list_dashboard_templates once with no arguments.
The full catalog (~95 entries) returns in a single call — read it
in-context and pick the best match for the user's intent. When several
entries plausibly fit, present the top 3–5 and let the user choose.
Branch on the result:
Tool guardrail The only template tools are
signoz_list_dashboard_templatesandsignoz_import_dashboard. Do not shell out, fetch raw GitHub URLs, or invent other tool names.signoz_import_dashboardtakes the templatepathfrom the catalog entry and creates the dashboard in one call — you do not need to fetch the JSON yourself or callsignoz_create_dashboardafterwards.
Before calling signoz_import_dashboard, confirm the template's
signals are actually being ingested. The most common silent failure for
template imports is "the template imports cleanly but every panel reads
'No data' because the technology isn't being scraped" — the user only
discovers it after clicking through to a useless dashboard.
Since we don't fetch the template body up front, base the probe on the
catalog entry's category, title, and keywords plus the user's
stated technology. Pick up to ~5 representative signals and check them
— keep the total small:
signoz_list_metrics with searchText set to the technology
prefix (e.g. searchText="postgresql"). Empty result → metric family
is not being ingested. Early out: if this returns empty, declare
"None present" and skip the rest of the metric probes — they will all
return zero. Use timeRange for a relative window, or pass
start/end (unix-ms strings) when you need an exact window instead
of the server default.signoz_aggregate_traces with aggregation=count,
timeRange=1h. No filter is needed for the "is anything flowing"
probe — adding filter="service.name EXISTS" is fragile and
unnecessary. Zero count → no traces flowing.signoz_aggregate_logs with
aggregation=count, timeRange=1h, no filter. Zero count → no logs.service.name, k8s.cluster.name): call
signoz_get_field_values to confirm there are values to pick
from. A dashboard whose top-level dropdown is empty is barely
better than one full of empty panels.Branch on the probe result:
This probe is cheap (a handful of queries, ~hundreds of ms total), and catching the no-data case early avoids the worst UX failure mode of the template path.
title, path), what category, what the
probe found. In autonomous mode the consumer proceeds; in interactive
mode the human can intervene.signoz_import_dashboard with the path
from the chosen catalog entry (e.g. postgresql/postgresql.json).
The server fetches the JSON, validates it, and creates the dashboard
in one call.service.name", "filter by
k8s.cluster.name") so the user knows what knobs they have. Offer
two follow-ups: "Want me to adjust panels, layout, or variables?"
and "Want me to wire alerts for any of these signals?
(signoz-creating-alerts)".signoz-modifying-dashboards with
the new dashboard's UUID and the requested changes. Do not call
signoz_update_dashboard from this skill.Run this path when the Step 3b template lookup found no match, the user
explicitly rejected the suggested template, or
signoz_import_dashboard failed.
Ask the user (skip questions whose answer is already clear from intent):
service.name, deployment.environment.name,
k8s.cluster.name).If the user is non-specific ("just make me something useful for X"), apply the defaults table below and surface them in the preview.
The MCP guideline applies: always prefer resource-attribute filters. Before authoring panels, confirm the names you'll use exist and emit data:
signoz_list_metrics with searchText
tied to the technology (e.g. searchText="postgresql") to get the
exact OTel metric names. Catalog presence ≠ data flowing — for
any metric you intend to use, follow up with signoz_query_metrics
on a representative window to confirm it actually has datapoints.signoz_get_field_keys with
fieldContext=resource for the relevant signal to enumerate
available attributes; call signoz_get_field_values on the
ones you'll use as variables to confirm concrete values exist. Note
that the live data may use older OTel semconv (e.g.
deployment.environment rather than deployment.environment.name)
— always trust the discovered key over the one in the defaults
table.If none of the discovered signals return data, tell the user the dashboard's data isn't being ingested yet, explain the panels will show "No data" until ingestion is set up, and offer to build anyway or stop. Wait for the user's choice before building.
These are the source of truth for the JSON schema, panel types, query builder shape, and layout rules — do not transcribe schema text into this skill, it will rot out of sync with the server. Read the four core resources before authoring widget JSON.
Fallback when the MCP resource-reader is unavailable Some MCP client harnesses do not expose a resource-reading tool. If you cannot read
signoz://...URIs in this session, fall back tosignoz_list_dashboards+signoz_get_dashboardon an existing dashboard of the same signal type (metrics / traces / logs) and read itswidgetsarray for v5 widget shapes.
signoz://dashboard/instructions — title, tags, description,
variables.signoz://dashboard/widgets-instructions — 7 panel types and layout
rules.signoz://dashboard/widgets-examples — complete widget configs with
all required fields (the most important resource — every widget
must include id, panelTypes, title, query, selectedLogFields,
selectedTracesFields, thresholds, contextLinks).signoz://dashboard/query-builder-example — query builder reference,
including operator semantics for filters.items[].op.Add signal-specific resources as needed:
signoz://promql/instructions.
Saved PromQL may reference declared dashboard $var variables, but
signoz_execute_builder_query does not expand them: substitute representative
literals only for dry-runs, never in saved panels. Grafana-only
$__rate_interval / $__interval are invalid. Dotted OTel metric names use
Prometheus 3.x UTF-8 selectors such as {"metric.name.with.dots"}.signoz://dashboard/clickhouse-schema-for-metrics
signoz://dashboard/clickhouse-metrics-example.signoz://metrics-aggregation-guide — required for picking valid
timeAggregation / spaceAggregation per metric type.signoz://traces/query-builder-guide.signoz://logs/query-builder-guide.signoz://dashboard/clickhouse-schema-for-traces
signoz://dashboard/clickhouse-traces-example.signoz://dashboard/clickhouse-schema-for-logs
signoz://dashboard/clickhouse-logs-example.Follow the v5 schema as documented in the resources above. Use OTel semantic attribute names (not shorthand) in filters, groupBy, and variables. Apply the defaults below unless the user specified otherwise.
Dashboard create/update payloads do not persist a default time range or
refresh interval. Panels follow the viewer-selected global range. If the user
asks for a specific window, mention that range in the final handoff instead of
inventing timeRange, defaultTimeRange, or refresh fields. Do not encode a
PromQL range selector inside a Builder query.
Use SigNoz enums and JSON types exactly. panelTypes: "graph" means time series
(never Grafana timeseries); variable types are uppercase (DYNAMIC, CUSTOM).
PromQL queryType is valid only for graph, value, bar, and histogram panels;
table and pie accept builder or clickhouse_sql; list requires builder.
softMax / softMin are numbers, contextLinks is {"linksData": [...]}, and
saved having is an array of clause objects; defer full shapes to the resources.
Keep non-row widget/layout IDs bijective; create/remove both entries together.
Row widgets need no layout entry; preserve matching row layout entries when
present. During import or rebuild, strip the UI drag artifact id
"__dropping-elem__" from both arrays.
Defaults the skill applies (and surfaces in the preview):
| Field | Default | When to override |
|---|---|---|
| Section structure (APM/services) | Overview / Latency / Errors / Throughput | domain-specific (e.g. DB: Overview / Connections / Throughput / Slow Queries) |
| Section structure (infra/runtime) | Overview / Saturation / Errors / Latency | domain-specific |
| Headline panels (services) | request rate, error rate, p50/p95/p99 latency, throughput | omit those that don't apply |
| Headline panels (infra) | resource utilization (CPU, mem), saturation, error/restart counts, throughput | tailor to the technology |
| Counter render unit (rate vs. count) | per-second rate | per-interval increase count over a wider window (24h–7d) for any low-volume / bursty / human-paced counter — requests, error counts, restarts, OOM kills — where /sec renders as tiny decimals (e.g. 0.03/s); gauges (CPU/mem/queue depth) are already absolute and unaffected; note increase rescales its y-axis with the selected range, so prefer it deliberately, not by reflex |
| Variables (services) | service.name, deployment.environment (or deployment.environment.name — verify which exists via signoz_get_field_keys) | add k8s.cluster.name / k8s.namespace.name when k8s-flavored |
| Variables (k8s/infra) | k8s.cluster.name, k8s.namespace.name (or host.name for hostmetrics) | drop service.name — it is rarely populated on infra signals |
| Layout | 2-column grid (w: 6), 12 columns wide; every item has 0 <= x < 12, 1 <= w <= 12, x + w <= 12 | full-width (x: 0, w: 12) for tables and time-series with many series |
| GroupBy on per-service panels | service.name resource attribute | drop when filtering to a single service |
Sections and panelMap A section is a panelTypes: "row" widget
followed in widgets[] by the panels under it. Mirror that grouping in
panelMap: one entry per row, keyed by the row id, listing only the
panels that follow it up to the next row. Do not put every panel under
a single row id — that renders on load but collapses the whole
dashboard when one section is toggled. Each child must match its top-level
layout entry's x, y, w, and h and satisfy the same horizontal bounds.
Title and description The dashboard title should name the technology and the scope clearly: "PostgreSQL — prod-us-east-1", not just "PostgreSQL". Description should answer "what is this for" in one sentence. Tags: technology + signal types + environment when known.
signoz://dashboard/widgets-examples is the source of truth for widget
required fields, panel-type-specific shapes, the canonical
filters.items[].key.id form, operator casing, and common write-shape
errors. Re-skim it before serialising any custom widget JSON.
Every dashboard queryData and queryFormulas entry must carry a positive limit and non-empty editor-model
orderBy (columnName + order). Raw list and trace-request panels default to 100 with timestamp-desc ordering
(raw logs add id); a deliberately smaller list page may match limit to pageSize. Aggregate panels use 100 with
the primary aggregation desc. Formula outputs use 100 with __result desc; every referenced base query uses 10000
because base limits apply before formula evaluation. Find those inputs from every formula expression, including
formulas with disabled: true, following references until every base builder_query leaf is reached. This dependency
walk chooses bounds only; it does not establish deterministic formula-to-formula evaluation order, so dry-run the
complete composite payload. During translation, log/trace bases keep the primary aggregation as their v5 order
key; metric bases translate editor primary-aggregation orderBy to v5 __result while preserving direction.
Formulas use __result in both models. Never pass dashboard orderBy to signoz_execute_builder_query.
Time-series top-N ranks groups over the whole window and can omit a short-lived local spike. Narrow filters/grouping
if formula-input cardinality can exceed 10000.
One rule widgets-examples does not call out, but
signoz_create_dashboard enforces: no JSON.stringify on
arrays/objects layout, widgets, tags, and variables are
native JSON — stringifying them produces errors like
cannot unmarshal string into ... layout of type []LayoutItem.
For every query-bearing panel, read the compact
dashboard-to-query-builder-v5 reference.
When the execution schema can represent the panel, call
signoz_execute_builder_query with the translated payload, never widget JSON.
Dry-run over a short absolute Unix-ms window — usually the last 30-60 minutes,
never the panel's display range by reflex; apply the reference's dry-run hygiene
rules before widening or retrying after a timeout. Use representative variable
values and keep editor aliases unchanged in signoz_create_dashboard.
If the reference's safety gate finds an unsupported execution field, report the
panel as unvalidated and continue only after explicit user acceptance. Server or
validation errors block. Unexpected empty results block unless the user already
accepted absent telemetry. Skip row panels and validate their shape against
signoz://dashboard/widgets-examples.
Preview Emit a one-paragraph plain-language summary of what will be created — no JSON dump. A 20–30 widget payload is hundreds of lines the user cannot meaningfully review in chat. Call out any validation gap the user explicitly accepted.
Summary: This dashboard tracks [signals] for [scope], with sections [list]. Variables: [list]. Dry-run: [N] panels passed. Unvalidated: [none / accepted gaps]. Data: [confirmed / pending ingestion by explicit user choice].
Save Call signoz_create_dashboard with the payload.
Report Tell the user:
signoz-creating-alerts)".signoz_list_dashboards Stopping at page
1 misses duplicates and produces clutter.signoz_list_dashboard_templates before any
signoz_create_dashboard call. If a matching template exists,
import it via signoz_import_dashboard (just inform the user);
only build from scratch when no template matches.signoz_import_dashboard
/ signoz_create_dashboard. A "No data" dashboard is a worse
outcome than one extra confirmation prompt. Skip only if the user has
explicitly opted out for this request.signoz_create_dashboard so the human can
intervene on intent.service.name not service,
host.name not host. Wrong names produce empty panels. Verify the
exact key (deployment.environment vs deployment.environment.name,
for instance) against signoz_get_field_keys rather than guessing —
installs running classic OTel semconv emit the no-.name form.signoz_list_metrics before authoring. Wrong names produce
empty panels and the user only finds out later.signoz://dashboard/* MCP resources. Required widget and queryData
fields are listed in signoz://dashboard/widgets-instructions and
signoz://dashboard/widgets-examples. Never wrap arrays/objects in
JSON.stringify; enforce the widget/layout bijection, field types, and enums
from Step 3b-ii.4.signoz-modifying-dashboards. Do not call
signoz_update_dashboard from this skill.Four canonical flows — template happy path, template choice, duplicate
found, custom build — live in references/examples.md.
npx claudepluginhub signoz/agent-skills --plugin signozGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.
Dispatches multiple subagents concurrently for independent tasks without shared state. Use when facing 2+ unrelated failures or subsystems that can be investigated in parallel.