writing-skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
datadog-dashboardsCorrects the wrong defaults a model has when building Datadog dashboards, verified against Datadog's docs in July 2026. Use when creating, editing, or reviewing a Datadog dashboard — choosing widgets, writing metric/log/span queries, or emitting widget JSON. Covers the queries that render a plausible number and are still wrong — `.as_count()` is appended au…
Independent GitHub snapshot · Automated classification · Original documentation governs
.as_count() is appended automatically in the graph editor but never through the API, so programmatic counts silently average; p95 resolves only on distribution metrics, and averaging one is an average of averages; ratios need .as_count() on both sides or they divide interpolated averages. Also covers grounding queries in metrics that exist rather than invented names, wire type strings that diverge from UI names (Pie Chart is sunburst, Table is query_table), and Datadog's own layout standard. Assumes the Datadog MCP server is connected. NOT for Terraform or raw Dashboard API management, monitor and SLO authoring, or non-Datadog observability tools.The decisions Datadog forces when you build a dashboard, and how to settle them. Every rule names the wrong default it corrects; there is no rule for what the model already gets right.
Pinned to a date, not a version. Datadog ships continuously, so every claim here was verified against docs.datadoghq.com in July 2026. Re-verify before trusting anything version-shaped — deprecations here (q, default, is_read_only, week_before()) still parse today.
Assumes the Datadog MCP server is connected (https://mcp.<site>/v1/mcp, toolsets=dashboards,widgets). Widget schemas are deliberately not restated in this skill — get_widget_reference returns them current at call time, and a copy here would go stale. If the server is not connected, set it up first (ship-endpoint-follows-the-site); this skill does not cover Terraform or raw API management.
Use this skill when:
.as_count() divergence biteslogs / spans / rum queries with search + compute + group_byscope-ask-audience-and-decision runs before anything is builtThis skill is NOT for:
scope-not-every-question-is-a-dashboard covers recognising when the request is one of those| # | Category | Prefix | Covers |
|---|---|---|---|
| 1 | Purpose & Scope | scope- | Audience, the decision it drives, variables over duplication, when it should not be a dashboard |
| 2 | Grounding in the Account | disco- | Confirming metrics, tags, and facets exist before querying them |
| 3 | Query Semantics | query- | The queries that return a number and are wrong |
| 4 | Choosing the Widget | widget- | Matching question to visualization; the pairs that are not interchangeable |
| 5 | Dashboard JSON | json- | What widget validation cannot see or cannot explain |
| 6 | Layout & Readability | layout- | Datadog's own standard for structure, display types, titles, sizing |
| 7 | Shipping It | ship- | Validate-and-smoke-test before writing; region endpoints |
scope-ask-audience-and-decision — Four questions before the first widget; the answers belong in description, not in chatscope-one-dashboard-many-variables — Six services is one dashboard; variable dropdowns only offer values the board's own widgets queryscope-clone-before-building — Presets exist for 1000+ integrations and are invisible to GET /dashboard; search, don't listscope-not-every-question-is-a-dashboard — "Tell us when X" is a monitor; a narrative is a notebookdisco-never-invent-metric-names — A wrong metric name renders an empty graph, never an errordisco-read-type-and-unit-first — DogStatsD increment() is stored as a RATE; type decides the modifier, unit decides the titledisco-absence-is-not-proof — Metrics age out of discovery in 24h but are retained 15 monthsdisco-log-attributes-need-facets — Unfaceted attributes cannot be grouped, and no API lists facetsquery-append-as-count-explicitly — The costliest default. The UI appends .as_count(); the API does not, and rolls up with avgquery-percentiles-require-distributions — p95: needs a distribution with percentiles enabled; avg: of a p95 is not a percentilequery-aggregate-before-dividing — A ratio without .as_count() sums per-interval ratios and can read 150%query-gauge-gaps-are-interpolated — Up to 5 minutes of fabricated points fill each gap by defaultquery-rollup-changes-the-number — The same widget means something different at each time framequery-event-sources-take-objects — Logs and spans take search+compute+group_by; interval is milliseconds, percentiles are pc95query-scope-syntax-does-not-mix — {env:prod AND !region:x} is invalid; a wildcard after $var matches nothingquery-top-n-subtotals-are-partial — The total under a top list is the sum of the visible rowswidget-match-the-question — Timeseries answers one question; rankings, single values, and deltas want other widgetswidget-heatmap-is-not-distribution — One has time on the x-axis, the other quantitywidget-reuse-alerting-primitives — Embed the SLO and monitor instead of guessing a threshold linejson-type-strings-differ-from-ui-names — Pie Chart is sunburst, Table is query_table, Monitor Summary is manage_statusjson-queries-and-formulas-not-q — q and every *_query field are deprecated; data_source is profiles, not profile_metricsjson-layout-follows-reflow-type — Under reflow_type: auto, layout must be omitted, not merely ignoredjson-template-variables-take-defaults — defaults is an array; singular default is deprecatedjson-dashboard-tags-are-constrained — Max 5, team:-shaped; is_read_only is deprecated but restricted_roles is notlayout-put-widgets-in-groups — About and Overview first, streams last, nothing bare on the backgroundlayout-display-type-follows-metric-shape — Area for volume, bars for counts, lines for comparisonlayout-let-datadog-render-units — Alias every formula; the axis already shows the unitlayout-size-for-the-medium — A wallboard and a triage board cannot be the same dashboardship-validate-before-upserting — Smoke-test the query and validate per widget before the writeship-endpoint-follows-the-site — EU, AP, and UK orgs need their own MCP host; GovCloud is unsupportedRead a reference file when its decision comes up. Each rule names the wrong default it corrects, then shows the canonical form — with an incorrect/correct contrast only where the wrong way is a real trap.
Three shortcuts worth taking first:
Building a dashboard from a request? Run scope-ask-audience-and-decision, then disco-never-invent-metric-names, before emitting anything. Skipping either produces a board that is fluent and useless.
Reviewing a dashboard whose numbers look wrong? Start with query-append-as-count-explicitly and query-percentiles-require-distributions. Together they account for most Datadog panels that are confidently incorrect, and neither leaves a trace in the UI.
Porting dashboard JSON written before 2025? json-queries-and-formulas-not-q and json-template-variables-take-defaults are the deprecations that still parse, so nothing points you at them.
Section definitions — category structure and ordering rationale
Rule template — for adding new rules
AGENTS.md — auto-built table of contents across all rules