Agent Skill · SigNoz

signoz-creating-dashboards

Create a new SigNoz dashboard from a natural-language intent — import a curated template (PostgreSQL, Redis, JVM, k8s, hostmetrics, APM, LLM, etc.) when one fits, or build a custom dashboard from scratch with metric / trace / log panels. Make sure to use this skill whenever the user says "create a dashboard for…", "set up monitoring for…", "build me a dashboard…", "I need observability for…", "import a dashboard template", or asks to track / visualize a service, database, cluster, or AI/LLM platform — even if they don't explicitly say "dashboard". Also use it when someone wants to "monitor", "watch", or "see metrics for" a technology and the natural answer is a dashboard.

Provider: SigNoz Path in repo: plugins/signoz/skills/signoz-creating-dashboards/SKILL.md

Skill body

Dashboard Create

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.

Prerequisites

This skill calls SigNoz MCP server tools (signoz:signoz_create_dashboard, signoz:signoz_list_dashboards, signoz:signoz_list_dashboard_templates, signoz:signoz_import_dashboard, signoz:signoz_get_dashboard, signoz:signoz_update_dashboard, signoz:signoz_list_metrics, signoz:signoz_get_field_keys, signoz:signoz_get_field_values, signoz:signoz_aggregate_logs, signoz:signoz_aggregate_traces, etc.). Before running the workflow, confirm the signoz: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.

When to use

Use this skill when the user wants to:

Do NOT use when the user wants to:

Required inputs (strict)

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:signoz_get_field_keys + signoz: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
Default time range, refresh, 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:

In autonomous mode (no human), escalate to the caller or fill the gap from upstream context. Either way, do not proceed to signoz:signoz_create_dashboard / signoz:signoz_import_dashboard with a guessed value.

Workflow

The flow runs in order: duplicate check → user picks modify-or-create → on create, template lookup decides template-import vs custom-build → no-data probe → per-panel dry-run → preview → save. Duplicate check comes first so we never silently create a second copy of something that already exists. Once the user has chosen to create, the template lookup is an internal implementation detail — if a curated template fits we use it, otherwise we build from scratch. The per-panel dry-run (signoz:signoz_execute_builder_query against every query-bearing panel) is mandatory before save — a saved empty panel from a typo’d attribute or wrong severity filter is the worst failure mode for this skill, and dry-run is the only step that catches it. The user is offered exactly two upfront choices: modify an existing dashboard, or create a new one.

Step 1: Check for duplicates

Call signoz:signoz_list_dashboards. Most installs fit in the default page (limit=50); only paginate when pagination.hasMore=true. Use string values for limit / offset (e.g. "50", "0") — the schema expects strings, not integers.

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.

Step 2: Ask the user — modify or create

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.

Step 3: Create or modify

Step 3a: Modify an existing dashboard

Hand off immediately to signoz-modifying-dashboards with the chosen dashboard UUID and the user’s intent. Do not call signoz:signoz_update_dashboard from this skill — modification is out of scope. (See “Scope boundary” in Guardrails.)

Step 3b: Create a new dashboard

Run the template lookup first. The user has already agreed to create new — the lookup decides how we build it.

Call signoz: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:

Step 3b-i: Import the template

Tool guardrail The only template tools are signoz:signoz_list_dashboard_templates and signoz:signoz_import_dashboard. Do not shell out, fetch raw GitHub URLs, or invent other tool names. signoz:signoz_import_dashboard takes the template path from the catalog entry and creates the dashboard in one call — you do not need to fetch the JSON yourself or call signoz:signoz_create_dashboard afterwards.

Step 3b-i.1: Pre-flight no-data probe (fail fast)

Before calling signoz: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:

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.

Step 3b-i.2: Preview, import, report
  1. Preview Tell the user what’s about to happen in one short paragraph: which template (title, path), what category, what the probe found. In autonomous mode the consumer proceeds; in interactive mode the human can intervene.
  2. Import Call signoz: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.
  3. Report Read the response and tell the user the dashboard’s title, panel count, and section breakdown. Surface the dashboard’s variables (“filter by 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)”.
  4. Customization handling If the user asks for any change to the imported dashboard, hand off to signoz-modifying-dashboards with the new dashboard’s UUID and the requested changes. Do not call signoz:signoz_update_dashboard from this skill.

Step 3b-ii: Custom build (no template, or import failed)

Run this path when the Step 3b template lookup found no match, the user explicitly rejected the suggested template, or signoz:signoz_import_dashboard failed.

Step 3b-ii.1: Gather requirements

Ask the user (skip questions whose answer is already clear from intent):

  1. Signals — metrics, traces, logs, or a combination.
  2. Specific signals — which metrics, which span attributes, which log severities matter most.
  3. Resource scope — which service(s), namespace(s), cluster(s), or environment(s).
  4. Variables — what should be a dropdown vs. a hard-coded filter (typical: service.name, deployment.environment.name, k8s.cluster.name).
  5. Sections — group panels into Overview / Latency / Errors / Saturation, or another structure that fits the domain.

If the user is non-specific (“just make me something useful for X”), apply the defaults table below and surface them in the preview.

Step 3b-ii.2: Discover names and probe data

The MCP guideline applies: always prefer resource-attribute filters. Before authoring panels, confirm the names you’ll use exist and emit data:

  1. Metrics — call signoz: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:signoz_query_metrics on a representative window to confirm it actually has datapoints.
  2. Resource attributes — call signoz:signoz_get_field_keys with fieldContext=resource for the relevant signal to enumerate available attributes; call signoz: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.

Per-panel validation happens later as a hard requirement — see Step 3b-ii.6 and the “Mandatory dry-run before save” guardrail.

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.

Step 3b-ii.3: Read the dashboard MCP resources

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 to signoz:signoz_list_dashboards + signoz:signoz_get_dashboard on an existing dashboard of the same signal type (metrics / traces / logs) and read its widgets array for v5 widget shapes. The mandatory dry-run in Step 3b-ii.6 then backstops any shape errors the fallback misses.

Add signal-specific resources as needed:

Step 3b-ii.4: Build the dashboard JSON

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.

All panels are validated in Step 3b-ii.6 via the mandatory dry-run before save. Author the JSON here as you intend to save it — the dry-run uses the exact shape from queryData.

Defaults the skill applies (and surfaces in the preview):

Field Default When to override
Time range last 1h longer for capacity planning, shorter for live debugging
Refresh manual (no auto-refresh) set 30s–1m only when the user explicitly wants live updates
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
Variables (services) service.name, deployment.environment (or deployment.environment.name — verify which exists via signoz: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 full-width (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

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.

Step 3b-ii.5: Shape check before save

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.

One rule widgets-examples does not call out, but signoz: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.

Step 3b-ii.6: Dry-run before save (mandatory)

Call signoz:signoz_execute_builder_query per panel. The dry-run validates the query is well-formed and confirms data flows under that filter — the per-panel data probe folds in here.

Envelope translation Widget JSON wraps queries in compositeQuery.builder.queryData[] and queryFormulas[], but signoz:signoz_execute_builder_query takes compositeQuery.queries[].{type, spec}. Translate per panel: each queryData[i]{ type: "builder_query", spec: { name, signal, filter: {expression}, groupBy, aggregations } }; each queryFormulas[i]{ type: "builder_formula", spec: { name, expression } }. Preserve the original name (A, B, …) on every builder_query.spec — formula expressions reference inputs by that name (e.g., A * 100 / B), and dropping it makes the dry-run shape diverge from the saved panel so formulas can’t resolve their inputs. The endpoint cannot consume widget JSON directly.

Non-empty response = pass; server error, “filter type mismatch”, or unexpected zero rows = fail (fix the panel JSON before save).

Coverage: dry-run every query-bearing panel, regardless of count or shape. Trivial panels fail silently too (wrong severity filter, wrong resource scope, attribute name shorthand like service instead of service.name) — the same footguns that bite non-trivial panels. Row / header panels (panelTypes: "row") have no query to execute — validate their shape against signoz://dashboard/widgets-examples instead and skip them here.

Step 3b-ii.7: Preview, save, report
  1. 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, and the dry-run has already validated every query-bearing panel against live data.

    Summary: This dashboard tracks [signals] for [scope], with sections [list]. Variables: [list]. Time range default 1h. Dry-run: all [N] query-bearing panels validated against live data (any failures have been fixed pre-save).

  2. Save Call signoz:signoz_create_dashboard with the payload.

  3. Report Tell the user:

    • The created dashboard’s UUID and title.
    • Panel count and section breakdown.
    • Which variables are wired.
    • Two follow-up offers: “Want me to adjust panels, layout, or variables?” and “Want me to wire alerts for any of these signals? (signoz-creating-alerts)”.

Guardrails

Examples

Four canonical flows — template happy path, template choice, duplicate found, custom build — live in references/examples.md.

Skill frontmatter

argument-hint: