sentinel-one/ai-siem/sdl-api
Claude Code and agent skill by sentinel-one/ai-siem
- community
Checking that the SKILL.md file is still in the repository.
Use whenever the user wants to read data and manage configuration through the SentinelOne Singularity Data Lake (SDL) API: run queries or manage configuration files (parsers, dashboards, alerts, lookups, datatables) on a Scalyr/SDL/XDR tenant. Trigger on "SDL", "SDL API", "Singularity Data Lake", "Scalyr", "DataSet", or any "*.sentinelone.net/sdl/api/*" URL, and on the method names "query", "powerQuery", "facetQuery", "timeseriesQuery", "numericQuery", "configFiles", "configFile", "addConfigFil…
Install
npx vskill@latest install sentinel-one/ai-siem/sdl-apiSKILL.md
SentinelOne SDL API
<!-- CONFIG-FILE-ADDRESSING v1 -->
SDL config files: address by `udoId`, and do not trust a REST listing.RESTlistFiles/getFilecannot see udoId-addressed/dashboards/files, sogetFilereturns404on a dashboard the console is displaying and the listing under-reports (measured onone tenant: REST 8, GraphQL 17, console 48 files). **If a listing disagrees with what the UIshows, the listing is wrong until proven otherwise**, change read path before concluding theobject is missing or the token lacks scope. Use the GraphQLconfigFiles/configFilesurface.A name-addressedaddConfigFileto/dashboards/creates a duplicate instead of updating;address dashboards byudoIdwithexpectedVersion.contentis HJSON, not JSON.S1-Scopechanges which files exist as far as the caller can tell.Full detail: `sdl-api/references/config-file-graphql.md`
Covers the Singularity Data Lake API (query and configuration-file methods) through the s1-secops-mcp MCP tools, with a per-method reference and a host-only Python client and CLI.
The SDL API lives under <console>/sdl on the Management Console host. It speaks JSON over Bearer tokens (not ApiToken) and is the canonical path for querying the data lake and editing parsers/dashboards/alerts/lookups directly. Raw-log ingestion is via HEC (hec_ingest, see "Raw log ingestion" below).
Primary path: the `s1-secops-mcp` MCP tools. Config files:sdl_list_files,sdl_get_file,sdl_put_file,sdl_delete_file; dashboards:sdl_list_dashboards,sdl_get_dashboard,sdl_create_dashboard,sdl_save_dashboard_layout,sdl_share_dashboard,sdl_delete_dashboard; queries:powerquery_run,powerquery_enumerate_sources,powerquery_schema_discover; ingest:hec_ingest. The server runs on the user's machine, so it reaches*.sentinelone.netwhere the Cowork sandbox cannot. It reads credentials from environment variables or the OS keychain and masks tokens in all output. If the tools are missing, the user has not connected the server: point them to the s1-secops-mcp README (s1-secops-mcp/README.mdin the s1-secops-skills source repo,mcp/s1-secops-mcp/README.mdin ai-siem; not shipped inside the plugin).`SDLClient` and `scripts/sdl_cli.py` are host-only. They run from Claude Code or a terminal on the user's machine, with the same environment variables or keychain entries. They cannot reach the tenant from the Cowork sandbox; never treat a proxy error there as an empty result, because that is how a fabricated schema gets into every downstream panel.
IMPORTANT: the V1 query methods are deprecated; run queries through LRQ
The query methods on the host-only Python client (query, powerQuery, facetQuery, timeseriesQuery, numericQuery) wrap the V1 SDL endpoints (/api/query, /api/powerQuery, etc.) under <console>/sdl. Those endpoints are deprecated and sunset on 2027-02-15 (also applies to the Deep Visibility /web/api/v2.1/dv/events/pq endpoint).
The replacement is the LRQ API, POST /sdl/v2/api/queries on the tenant's own Management Console host (e.g. your-tenant.sentinelone.net). Run it with the powerquery_run MCP tool, which handles auth, the forward tag, polling, cancel, slicing (slices plus merge) and raw-event LOG queries. The wire details live in the mgmt-console-api skill (references/lrq-api.md).
SDL dashboard panels are rendered in the browser. The panel JSON stores the query string and the console executes it when a user loads the dashboard. To validate a panel before or after deploy, run its query once with powerquery_run at the same scope the dashboard uses (see the sdl-dashboard skill).
| Task | Correct tool / path | |
|---|---|---|
| PowerQuery programmatically (any range) | powerquery_run (LRQ at POST /sdl/v2/api/queries on the console host) | |
| Raw events with every parsed field | powerquery_run with queryType: "LOG" | |
| Field schema of a source | powerquery_schema_discover | |
| Dashboard panel validation | powerquery_run per panel, at the dashboard's scope | |
| Quick one-off stats under 24h (deprecated) | V1 methods on the host-only client still work until 2027-02-15 | |
| Config files (parsers, dashboards, lookups) | sdl_list_files / sdl_get_file / sdl_put_file / sdl_delete_file, GraphQL-backed, see below |
STOP: config files are GraphQL, not the REST /api/*File endpoints
POST /sdl/v2/graphql is the canonical config-file surface. The legacy REST endpoints (/api/listFiles, /api/getFile, /api/putFile) are incomplete and must not be used to decide whether a file exists.
Measured live on <console>: REST listFiles returned 1,914 paths, GraphQL configFiles returned 2,264. The entire 350-file gap is /dashboards/ files that carry a udoId, and REST getFile on any of them returns success/noSuchFile.
Tripwire, non-negotiable. If a file is not found by name, or a listing count disagrees with what the console shows, do not conclude the file is absent. The REST listing is incomplete by design. Re-check with configFiles before reporting "not found". A count in the 1,900s when the console says 2,200-plus means you used the wrong surface.
The udoId rule
The console's Configuration Files grid displays a dashboard as:
That display string is not a path. Reading it as one returns no file exists at path. Pass 6554761743556608 as udoId; the file's real name is /dashboards/AI Usage.
udoId assignment is by namespace (verified live): only /dashboards/ files get one. /lookups/, /datatables/, /logParsers/ and /automaticLookups all return udoId: null and are addressed by name.
| Namespace | Address by | Write by name updates in place? | |
|---|---|---|---|
/dashboards/ | udoId | No, it creates a duplicate | |
/lookups/, /datatables/, /logParsers/, /automaticLookups | name | Yes |
Never write a dashboard by name
addConfigFile(name:) updates in place for a name-addressed file but creates a duplicate for a dashboard. Create a dashboard by name once (there is no udoId yet), then address it by udoId forever after. Skipping this is how one tenant accumulated 152 copies of /dashboards/AI Usage and 256 surplus dashboard files overall.
expectedVersion is enforced on both address forms; a stale value is rejected with "There are conflicting changes in the file." and the stored content is left untouched. A deleteConfigFile returning null with no errors array is success, not failure.
Setup: credentials live in the OS keychain or the environment
There is no credentials file. The MCP server and the host-only Python client resolve each value from environment variables first, then the OS keychain (service sentinelone-mcp, account <profile>:<NAME>, profile from S1_PROFILE, default default). The user stores them once on their machine with s1-secops-mcp setup and checks them with s1-secops-mcp status.
S1_CONSOLE_URLandS1_CONSOLE_API_TOKENauthorise every query and config method.S1_SCOPEis the defaultS1-Scope(<accountId>or<accountId>:<siteId>) when the token spans several sites or accounts. Most tools also take a per-callscope.S1_HEC_INGEST_URLandS1_HEC_TOKEN(the SDL Log Write Key) are needed only for raw log ingest.
If a tool reports a missing credential, stop and ask the user to run s1-secops-mcp setup on their machine. Never ask for a token in the chat and never write one to a file.
Workflow
When the user asks for something involving the SDL API:
- Pick the operation. Check
references/methods.mdfor the semantics. For configuration files, use the GraphQL-backed MCP tools (sdl_list_files,sdl_get_file,sdl_put_file,sdl_delete_file), never the legacy REST ones, see the STOP section above andreferences/config-file-graphql.md. Raw-log ingestion ishec_ingest. For queries, usepowerquery_run(LRQ); the V1 query methods are deprecated. - Call the MCP tool. On the user's host only (Claude Code or a terminal),
from sdl_client import SDLClientgives the same operations as Python methods (config_files,config_file,put_config_file,delete_config_file, plus the deprecated V1query,power_query,facet_query,timeseries_query,numeric_query), andpython scripts/sdl_cli.py <method> [args]mirrors the client. - Summarize for the user. Don't dump raw JSON unless asked. For query results, prefer a concise table or CSV; for ingestion, confirm
bytesChargedand the session ID; for config files, show path + version + (truncated) content.
Schema discovery: the right way
Every SDL session must run live schema discovery for every data source it will query, including the S1 internal sources alert, vulnerability, misconfiguration, asset, finding, ActivityFeed, Identity, indicator and every third-party source. Documented schemas drift between sessions due to parser edits, reserved-field rewrites, and ingestion changes.
`asset` and `ActivityFeed`, confirmed live schemas (126 and 41 fields respectively):
dataSource.name='asset': 126 fields of rich device inventory (OCSF class_uid 3004, category_name = 'Discovery'). Key fields:device.agent.uuid,device.name,device.os.{name,version,type},device.agent.{network_status,network_status_title,network_quarantine_enabled,is_active,is_decommissioned,is_uninstalled,scan_status,version,last_logged_in_user_name},device.ip_external,device.hw_info.*,device.network_interfaces[N].*,severity_id,severity_,operation(= OPERATION_UPSERT),s1_metadata.{site_id,site_name,group_id,group_name}. Use this for endpoint inventory panels and asset state tracking. Fields that do not exist:entity.uid,entity_result.*,agent.health.online,agent.uuid(usedevice.agent.uuid).dataSource.name='ActivityFeed': 41 fields of Hyperautomation/management activity audit log (sca:RetentionType = 'ACTIVITY_LOG'). Key fields:activity_type(numeric, NOT a string, e.g. 9207 = workflow execution event),activity_uuid,primary_description,secondary_description,data.workflow_{id,name,execution_url},data.{scope_id,scope_level,scope_name,site_name,user_id},created_at,updated_at,account.{id,name},site_id,context. Useful for Hyperautomation workflow audit and compliance tracking. Not useful for threat hunting.
The actual ingestion pipeline metrics source is `finding` (dataSource.category='metrics', tag='ingestionHealth', fields: batchCt, eventLatency.*, processor, etc.); do not confuse it with asset or ActivityFeed.
Why PowerQuery is the wrong tool for this: PowerQuery's default projection returns timestamp + message only. Naive dataSource.name='alert' | limit 1 hides the actual fields. | columns * is rejected (HTTP 400 "Don't understand [*]"). You can probe specific fields with | columns f1, f2 but you have to already know what to ask for, which defeats the purpose of discovery.
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
- SKILL.md in the repositoryCheckingplugins/s1-secops-skills/skills/sdl-api/SKILL.md
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.
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
[](https://verified-skill.com/skills/sentinel-one/ai-siem/sdl-api)