Dashboarding
Grafana LabsOfficialPublished by Grafana Labs
- Skill
- Tool integration
- Cloud and DevOps
- Apache-2.0
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to managing Grafana dashboards as code. By interacting with the Grafana HTTP API, users can automate the creation, modification, and deployment of dashboards. It covers the full lifecycle of dashboard management, including defining panel layouts, configuring data sources, setting up template variables, and applying data transformations. The skill emphasizes a workflow where dashboard configurations are maintained as JSON, pushed to the server, and verified through API responses to ensure consistency and correctness.
What it does
- Automates dashboard creation and updates via the HTTP API
- Defines dashboard layouts using a 24-column grid system
- Configures panel types including timeseries, stat, gauge, and logs
- Implements template variables for dynamic dashboard filtering
- Applies data transformations like calculations and filtering
- Validates dashboard state by verifying API responses and performing read-back checks
When to use it
- When you need to script the deployment of dashboards for new services
- When managing dashboard versions as code in a repository
- When you need to apply consistent template variables or annotations across multiple dashboards
- When performing complex data transformations that are easier to define in JSON
- When you want to automate the synchronization of dashboards between environments
Advantages
- Enables version control for dashboard configurations
- Ensures consistency across multiple dashboards through programmatic definitions
- Reduces manual effort in the Grafana UI for repetitive tasks
- Provides a clear path for verifying dashboard deployment success
Usage examples
- “Create a dashboard for this metric”
- The agent generates a JSON payload with the specified panel type and data source, then pushes it to the Grafana API.
- “Add a service dropdown to my dashboard”
- The agent fetches the existing dashboard JSON, appends a query-based template variable for the service, and updates the dashboard via the API.
- “Show errors as a percentage”
- The agent modifies the panel configuration to include a calculateField transformation that computes the error percentage.
- “Export the dashboard JSON”
- The agent retrieves the current dashboard configuration from the API and provides the raw JSON structure.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/grafana/dashboarding/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip dashboarding.zip -d .agents/skills
Documentation by Grafana Labs
Grafana Dashboard Authoring
Dashboards are JSON. Author once, push via API, share by uid.
Prerequisites
Grafana stack (OSS, Enterprise, or Cloud) reachable from your machine
API token with
dashboards:write(Authorization: Bearer <token>)jqfor inspecting responsesThe JSON-schema cheat sheet in
references/json-schema.md
Common Workflows
1. Push a new dashboard via the API + verify
# 1. Build the payload — wrap the dashboard JSON, set folder, mark overwrite
cat > /tmp/dash.json <<'JSON'
{
"dashboard": {
"uid": "demo-svc-v1",
"title": "Demo Service",
"schemaVersion": 41,
"tags": ["demo"],
"time": { "from": "now-1h", "to": "now" },
"templating": { "list": [] },
"panels": [{
"id": 1, "type": "timeseries", "title": "Request Rate",
"gridPos": { "x": 0, "y": 0, "w": 24, "h": 8 },
"datasource": { "type": "prometheus", "uid": "prometheus" },
"targets": [{
"expr": "sum(rate(http_requests_total[5m])) by (status_code)",
"legendFormat": "{{status_code}}", "refId": "A"
}],
"fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] }
}]
},
"folderUid": "",
"overwrite": true,
"message": "initial push"
}
JSON
# 2. Validate the JSON BEFORE you send it (catches trailing-comma typos)
jq empty /tmp/dash.json && echo "json ok"
# 3. POST
RESP=$(curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
"$GRAFANA/api/dashboards/db" -d @/tmp/dash.json)
echo "$RESP" | jq '{status, uid, url, version}'
# Expect: status="success", url="/d/demo-svc-v1/...", version=1 (incremented on each push)
# 4. Verify the round-trip — read it back and confirm one panel + the expected title
curl -s -H "Authorization: Bearer $TOKEN" \
"$GRAFANA/api/dashboards/uid/demo-svc-v1" \
| jq '{title: .dashboard.title, panels: (.dashboard.panels | length)}'
# Expect: {"title":"Demo Service","panels":1}
# 5. Open the dashboard in a browser — confirm the panel renders with data.2. Add a $job template variable to an existing dashboard
# 1. Fetch existing dashboard
curl -s -H "Authorization: Bearer $TOKEN" \
"$GRAFANA/api/dashboards/uid/demo-svc-v1" > /tmp/dash.json
# 2. Edit templating.list — append:
# { "name":"job", "type":"query",
# "datasource":{"type":"prometheus","uid":"prometheus"},
# "query":{"query":"label_values(up, job)","refId":"A"},
# "refresh":2, "includeAll":true, "multi":true, "label":"Service" }
# (Use jq, an editor, or the Grafana UI — schema in references/json-schema.md.)
# 3. Update the panel expr to use the variable: rate(http_requests_total{job=~"$job"}[5m])
# 4. POST it back with overwrite: true. Verify the variable appears in the UI dropdown.3. Compute an "Error %" column with a transformation
{
"id": "calculateField",
"options": {
"alias": "Error %", "mode": "reduceRow",
"reduce": { "reducer": "last" },
"binary": { "left": "errors", "right": "total", "operator": "/" }
}
}Add this to the panel's transformations: []. Verify in the UI panel inspector — the new field should appear and update with the variable selection.
Full schema (panels, units, all transformations, annotations, links): references/json-schema.md.
API reference
# Get
curl -s -H "Authorization: Bearer $TOKEN" \
"$GRAFANA/api/dashboards/uid/<uid>" | jq '.dashboard'
# Search
curl -s -H "Authorization: Bearer $TOKEN" \
"$GRAFANA/api/search?query=kubernetes&type=dash-db" | jq '.[] | {uid,title,folderTitle}'
# Create folder
curl -s -X POST -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" "$GRAFANA/api/folders" \
-d '{"uid":"platform-team","title":"Platform Team"}'For dashboards embedded in app plugins, use @grafana/scenes (skill grafana-o11y:grafana-scenes).
Resources
Files
- ATTRIBUTION.mdAdded by AutoGineer844 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md5.4 KiB
- references/json-schema.md4.5 KiB
references/json-schema.md
Dashboard + panel JSON schema
Dashboard root
{
"title": "My Dashboard",
"uid": "my-dashboard-v1",
"tags": ["service", "production"],
"time": { "from": "now-1h", "to": "now" },
"refresh": "30s",
"timezone": "browser",
"schemaVersion": 41,
"templating": { "list": [] },
"annotations": { "list": [] },
"panels": []
}uid— stable identifier; keep shortschemaVersion—41for Grafana 11+time.from/to— relative (now-1h) or absolute ISOrefresh—"30s","1m","5m",""(off)
Panel
{
"id": 1,
"type": "timeseries",
"title": "Request Rate",
"gridPos": { "x": 0, "y": 0, "w": 12, "h": 8 },
"datasource": { "type": "prometheus", "uid": "${datasource}" },
"targets": [{
"expr": "sum(rate(http_requests_total{job=\"$job\"}[5m])) by (status_code)",
"legendFormat": "{{status_code}}",
"refId": "A"
}],
"fieldConfig": {
"defaults": {
"unit": "reqps",
"thresholds": { "mode": "absolute", "steps": [
{ "color": "green", "value": null },
{ "color": "yellow", "value": 1000 },
{ "color": "red", "value": 5000 }
]}
},
"overrides": []
},
"options": {
"legend": { "calcs": ["mean","max","last"], "displayMode": "table", "placement": "bottom" },
"tooltip": { "mode": "multi", "sort": "desc" }
}
}gridPos: 24-column grid. Widths: full=24, half=12, third=8, quarter=6. Height 1 unit ≈ 30 px.
Panel types
| Panel | Use case |
|---|---|
| Time series | Any metric over time |
| Stat | Single value + sparkline |
| Gauge | % or value against min/max |
| Bar gauge | Side-by-side comparison |
| Table | Multi-column data |
| Heatmap | Distribution over time |
| Logs | Loki log streams |
| Traces | Tempo trace search |
| Text | Markdown docs |
| Candlestick | OHLC / min-max-avg |
| Node graph | Service dependency graph |
Useful units
reqps requests/sec
ops ops/sec
Bps bytes/sec
percentunit 0.0-1.0 as %
bytes bytes (auto-scales)
decbytes decimal bytes (1 KB = 1000 B)
ms / s milliseconds / seconds
dtdurationms 1h 2m 3s
short compact (1.2k, 3.4M)
none raw numberTemplate variables
{ "name":"job", "type":"query", "datasource":{"type":"prometheus","uid":"prometheus"},
"query":{"query":"label_values(up, job)","refId":"A"},
"refresh":2, "includeAll":true, "multi":true, "label":"Service" }
{ "name":"cluster", "type":"constant", "query":"production", "label":"Cluster" }
{ "name":"datasource", "type":"datasource", "pluginId":"prometheus",
"includeAll":false, "label":"Prometheus" }Multi-value variables expand to a regex OR: $job=["api","worker"] → job=~"api|worker".
Chained: label_values(kube_pod_info{namespace=\"$namespace\"}, pod).
Transformations
"transformations": [
{ "id": "merge", "options": {} },
{ "id": "organize", "options": {
"renameByName": { "Value #A": "Request Rate", "Value #B": "Error Rate" },
"excludeByName": { "Time": true }
}},
{ "id": "calculateField", "options": {
"alias": "Error %", "mode": "reduceRow",
"reduce": { "reducer": "last" },
"binary": { "left": "errors", "right": "total", "operator": "/" }
}},
{ "id": "filterByValue", "options": {
"filters": [{ "fieldName":"Error %", "config":{ "id":"greater", "options":{ "value":0.01 }}}],
"type": "include", "match": "any"
}}
]Common IDs: merge, organize, rename, calculateField, filterByValue, groupBy, sortBy, limit, labelsToFields, seriesToRows, partitionByValues.
Links & annotations
"links": [
{ "title":"Go to details", "url":"/d/details?var-service=${__field.labels.service}", "targetBlank":false },
{ "title":"Runbook", "url":"https://wiki.example.com/runbook/${job}", "icon":"external link",
"targetBlank":true, "type":"link" }
]Built-in vars: ${__value.raw}, ${__field.labels.job}, ${__url.params}, ${__from} / ${__to} (Unix ms).
Loki annotation:
{ "datasource":{"type":"loki","uid":"loki"},
"expr":"{job=\"deployments\"} |= \"deployed\"",
"name":"Deployments", "iconColor":"blue",
"titleFormat":"{{service}} deployed", "textFormat":"{{version}} by {{author}}" }Prometheus annotation:
{ "datasource":{"type":"prometheus","uid":"prometheus"},
"expr":"changes(kube_deployment_status_observed_generation{namespace=\"production\"}[5m]) > 0",
"step":"60s", "name":"Deployments", "iconColor":"blue",
"titleFormat":"Deploy: {{deployment}}" }Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Published by
- Grafana Labs
- Publisher
- Grafana Labs (Official)
- Source
- grafana/skills · skills/grafana-core/dashboarding · commit 8fb72a5
- Licence
- Apache License 2.0 (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Grafana Labs.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download dashboarding.zip