sentinel-one/ai-siem/sdl-dashboard

Claude Code and agent skill by sentinel-one/ai-siem

Trust tier 3
  • community
  • ext:[{"type":"hook","description":"Pre/post lifecycle hooks"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Use this skill any time the user wants to create, edit, design, generate, deploy, or debug a SentinelOne Singularity Data Lake (SDL) dashboard. Triggers include: "build me a dashboard", "create a dashboard panel", "write dashboard JSON", "add a panel to my dashboard", "deploy a dashboard to SDL", "I want a dashboard that shows...", "can you make a dashboard for...", "threat dashboard", "SOC dashboard", "network dashboard", "audit dashboard", "O365 dashboard", "hunting dashboard", or any request…

Install

npx vskill@latest install sentinel-one/ai-siem/sdl-dashboard

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

SentinelOne SDL Dashboard Skill

<!-- CONFIG-FILE-ADDRESSING v1 -->

SDL config files: address by `udoId`, and do not trust a REST listing.
REST listFiles / getFile cannot see udoId-addressed /dashboards/ files, so getFile
returns 404 on a dashboard the console is displaying and the listing under-reports (measured on
one tenant: REST 8, GraphQL 17, console 48 files). **If a listing disagrees with what the UI
shows, the listing is wrong until proven otherwise**, change read path before concluding the
object is missing or the token lacks scope. Use the GraphQL configFiles / configFile surface.
A name-addressed addConfigFile to /dashboards/ creates a duplicate instead of updating;
address dashboards by udoId with expectedVersion. content is HJSON, not JSON. S1-Scope
changes which files exist as far as the caller can tell.

This skill helps you design, author, and deploy Singularity Data Lake (SDL) dashboards, from a single panel to a full multi-tab SOC dashboard. Dashboards live as configuration files in SDL and are authored as JSON (or a relaxed JavaScript-literal superset of it). You deploy them with the sdl_put_file MCP tool.

Talk to the tenant through the `s1-secops-mcp` MCP tools. sdl_list_files / sdl_get_file / sdl_put_file inspect and deploy dashboards, powerquery_enumerate_sources and powerquery_schema_discover drive pre-authoring discovery, and powerquery_run validates every panel query. The server runs on the user's machine, so it reaches *.sentinelone.net where the Cowork sandbox cannot, and it reads credentials from environment variables or the OS keychain. If the tools are missing, point the user to the s1-secops-mcp README (s1-secops-mcp/README.md in the s1-secops-skills source repo, mcp/s1-secops-mcp/README.md in ai-siem; not shipped inside the plugin). The local scripts in scripts/ that make no network calls (panel_safety_check.py, render_validation_pdf.py) run anywhere; validate_dashboard.py calls the tenant and is host-only.

Before you start: REST cannot SEE most dashboards

sdl_list_files / getFile omit every udoId-addressed `/dashboards/` file. This is a visibility gap, not just an addressing one, and it makes a live dashboard look deleted.

Symptoms, all observed together on one tenant:

  • getFile returns 404 on a dashboard the console is displaying;
  • the REST listing returns 8 dashboards where GraphQL returns 17 and the console's

Configuration Files tab shows 48 files.

If a listing disagrees with what the UI shows, the listing is wrong until proven otherwise. That contradiction is the signal to change read path, not to conclude the object is missing or that your token lacks scope. Reach for the GraphQL config-file surface (sdl-api/references/config-file-graphql.md):

graphql
query { configFiles { udoId name readOnly version } }
query f($udoId: ID!) { configFile(udoId: $udoId) { udoId name content version } }

Two things that bite immediately after a successful read:

  • `content` is HJSON, not JSON, unquoted keys and relaxed commas. json.loads raises

Expecting property name enclosed in double quotes. Parse with an HJSON reader; you can write plain JSON back.

  • `S1-Scope` is honoured and silently changes what exists as far as the caller can tell. A

site-scoped dashboard is invisible to an account-scoped listing, so "not found" is always scope-relative.

Defaults you apply without being asked

The user should not have to remember any of this. If a prompt has to carry the constraint, the skill has failed. "Build a SOC leader dashboard" is a complete instruction; treat every item below as already requested.

AlwaysNever wait to be told
Put the initial predicate of a `\datasource query inside where (...)`Do not write `\datasource alerts \filter status = 'NEW'`
Run source enumeration and schema discovery before authoring, and use only fields you confirmedDo not assume a field exists because it exists on another tenant
Search the account for a deployed dashboard already doing this, and copy its working patternDo not theorise about why something cannot work before looking
Lead the dashboard description with a bold instruction to set the data selector to All DataDo not ship a `\datasource` or alert-stream dashboard without it
Validate every panel query against the tenant, then check the visual's column contractDo not treat an API pass as a render pass
Match the time unit to the surface: now() ns, inventory createdAt ms, ActivityFeed time sDo not hand-convert without checking the table in the UQL section
Use a chained group for exact distinct counts on inventoryDo not quote estimate_distinct as exact
Terminate number and table panels with `\limit`
Say so plainly when a source is empty on this tenant, and do not ship the panelDo not ship a panel that renders empty and hope nobody looks
Name a panel after what its query actually measuresDo not let a title overstate the query

When a request conflicts with one of these, say which constraint applies and what you did instead, rather than silently following the prompt into a broken panel.


Workflow

This workflow is mandatory for every new or modified dashboard. Steps 0, 1, and 7 are non-negotiable: pre-flight discovery, the safety pre-flight check, and the post-deploy log-evidence report. Skipping any of them produces dashboards that look fine in isolation but mislead, hang, or silently drop data.

  1. Discovery (MANDATORY for every session): Re-enumerate connected data sources (| group UniqueDataSourceNames = array_agg_distinct(dataSource.name) | limit 1000), run schema discovery on every source the dashboard will touch, and validate the discriminator field for any event.type you intend to count. See Pre-authoring discovery below. Never start a panel from a remembered schema.

Execution path for discovery via s1-secops-mcp:

  1. Source enumeration: powerquery_enumerate_sources, or powerquery_run with the array_agg_distinct(dataSource.name) query, at the dashboard's scope.
  2. Schema discovery (full event JSON per source): powerquery_schema_discover per source (issue them in parallel), at the same scope. Persist the field lists with the Write tool if later steps will need them.

0.5. Establish both scopes before authoring anything. Ask, or read from the request: which scope is this dashboard deployed at, and which data should its panels read? If the deployment target is a site, every query panel gets site.id='<siteId>' unless the user explicitly asked for account-wide queries. See Scope doctrine below. Getting this wrong is not a cosmetic error: an unscoped panel on a site dashboard reports another site's numbers, and a site.name filter silently drops alert and asset records.

  1. Understand the ask: What data should the dashboard show? Who is the audience (SOC analyst, manager, customer POC)? What time range makes sense? What posture should each panel reflect (a panel that legitimately returns 0 needs a markdown header explaining the SOC-positive interpretation, see Empty results are valid evidence).
  2. Design the structure: Choose tabs (if multi-topic), then panels per tab. Match panel type to the data shape using the guide in references/panel-type-cheatsheet.md. Key decisions: flows/kill-chains → sankey; KPI vs SLA target → bullet; SOC queue health → gauge; 3D outlier detection → scattered_bubble; time-based density → heatmap; multiple queries in one panel → tabbed table. Where one event.type covers multiple semantic populations (delivery-time vs click-time, scheduled vs on-demand, inbound vs outbound), build separate sections per population, not a mixed section.
  3. Write the JSON: Use the panel type reference below and real examples in references/community-examples.md. Compute explicit x/y/w/h for every panel. Apply the naming-hygiene rule from Panel naming hygiene so titles read as SLA-grade claims.
  4. Validate queries: Sample 3-5 events per source/event-ID to confirm field semantics. Test each panel query with powerquery_run (see the powerquery skill). Run the parallel load test (see Pre-deploy validation), acceptance thresholds: slowest panel ≤ 2s, wall-clock ≤ 5s. Run scripts/panel_safety_check.py against the dashboard JSON (local, no network); resolve every flag before deploy.
  5. Deploy with the GraphQL-backed MCP tools (see references/deployment.md). First deploy: sdl_create_dashboard with name, config (the dashboard JSON as a string), isPublic: true and scope ("<accountId>:<siteId>" for a site); this is the default and the only way to deploy to a site. Record the returned id: it is the udoId (sdl_list_files with pathPrefix: "/dashboards/" resolves it if needed). Every deploy after that: sdl_get_file with udoId for the current version, then sdl_put_file with udoId, content and expectedVersion as the CAS guard. A path-addressed write to an existing dashboard is refused because it duplicates. Save a backup of the prior JSON first. Wait 3s, then re-read by udoId to verify the version bumped AND check the returned content for a canary string from your change.
  6. Iterate: Show the user what was built, explain each panel, offer to tweak. If the dashboard hangs, follow the escalation ladder in Pre-deploy validation.
  7. Log-evidence report (MANDATORY): Replay every non-markdown panel against live data and keep the evidence. A dashboard delivered without an evidence report is incomplete.
  • Replay: one powerquery_run call per panel, with the panel's exact query, the dashboard's time range (hours or startTime / endTime) and the same scope the dashboard is deployed at. Issue the calls in parallel, about 10 per turn, so a 60-panel dashboard takes a few turns, not one long blocking run. Keep maxRows small (for example 20); you need the row count, columns and the first 3 rows.
  • Persist: write the evidence JSON with the Write tool, one entry per panel keyed "<tab>::<title>" with ok, verdict (PASS / WARN / EMPTY / FAIL, or SKIP for markdown), style, query, row_count, columns, sample_rows (first 3 rows verbatim), matchCount, elapsed_s (null when not measured) and error (first 300 characters on failure). Apply the per-style pass conditions in Log-evidence report below. Write the markdown evidence file next to it.
  • Render: run scripts/render_validation_pdf.py <evidence.json> (local, no network) for the PDF (cover, per-tab sections, sample-data tables, empty-result appendix with SOC-meaningful interpretations). Deliver the PDF and the markdown alongside the dashboard.

When a stacked_bar or line panel using | transpose returns 0 rows in validation, cross-check whether the corresponding number panel for the same source shows data; if it does, record it in the Appendix as a confirmed false-empty and do not remove the panel. On the user's host, scripts/validate_dashboard.py automates the same replay and writes the same JSON shape; run it as a background process there, since it takes about 10 s per panel.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
87
Repository forks
38
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Extension points

  • hookPre/post lifecycle hooks

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/sentinel-one/ai-siem/sdl-dashboard/badge)](https://verified-skill.com/skills/sentinel-one/ai-siem/sdl-dashboard)

Something wrong with this skill or its page? Tell us.