From s1-secops-skills
Generates SentinelOne Hyperautomation workflow JSON from natural language descriptions, with optional API-based import/export to a live console. Handles triggers, actions, and activation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/s1-secops-skills:hyperautomationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill enables Claude to design and generate valid SentinelOne Hyperautomation workflow
This skill enables Claude to design and generate valid SentinelOne Hyperautomation workflow JSON, explain the logic behind workflows, and optionally submit them to a live console via API.
Sandbox proxy blocked? If import/export API calls to
*.sentinelone.netfail with a connection or proxy error inside the Claude sandbox, use thes1-secops-mcpserver instead. It runs locally vianodeand bypasses the sandbox proxy entirely. Setup: add it toclaude_desktop_config.json(sees1-secops-mcp/README.md). The MCP server exposesha_list_workflows,ha_get_workflow,ha_import_workflow, andha_export_workflow— all running from your machine against the Hyperautomation API.
Before building production workflows, validate your token + scope using the
smallest payload the /import endpoint accepts: a manual trigger with no
inputs. Use this to confirm the API path works end-to-end (import → activate)
before iterating on real action graphs.
{
"data": {
"name": "minimal-smoke-test",
"description": "validates the import path",
"actions": [
{
"action": {
"client_data": {
"collapsed": false,
"dimensions": { "height": 76.0, "width": 256.0 },
"position": { "x": 286.0, "y": -29.0 }
},
"connection_id": null,
"connection_name": null,
"data": {
"action_type": "manual_trigger",
"dynamic_properties": {},
"name": "Manual Trigger",
"static_payload": "{}",
"trigger_type": "dynamic"
},
"description": null,
"integration_id": null,
"tag": "core_action",
"type": "manual_trigger",
"use_connection_name": false
},
"connected_to": [],
"export_id": 0,
"parent_action": null
}
]
}
}
Notes:
dynamic_properties: {} is valid — the manual-trigger node renders with no input fields.POST /workflows/{workflow_id}/{version_id}/activation?siteIds=<id> (returns 204).references/api-integration.md for the
siteIds= pitfall (the wrong shape returns 403 "Insufficient permissions"
that looks like a missing role).When a user asks to build a workflow, follow this process:
Ask (or infer from context):
CRITICAL: Before generating JSON, identify any integration-backed actions (tag = "integration"). These require pre-configured connections in the console that CANNOT be created via API. Always tell the user: "This workflow uses the [X, Y, Z] integrations. Before importing, you must configure connections for these in your Hyperautomation → Integrations section."
Integration-backed actions have "tag": "integration" and a non-null integration_id.
Core actions (Variable, Loop, Condition, Delay, Send Email, HTTP Request without integration,
Break Loop, Snippet, Wait for Slack, Create Interaction) have "tag": "core_action".
Read references/workflow-schema.md to produce a valid workflow JSON.
Read references/building-blocks.md for the correct action type structures.
Read references/functions-reference.md for available functions and their syntax.
Self-check against references/validation-rules.md before presenting the workflow.
If the user wants to submit to a live console, read references/api-integration.md.
Credentials: The plugin's SessionStart hook auto-discovers a credentials.json
dropped directly into the user's Cowork project folder at the start of every session.
If the file is missing, ask the user to drop a credentials.json into their project folder.
Resolution priority (highest wins):
S1_CONSOLE_URL / S1_CONSOLE_API_TOKEN<project folder>/credentials.json (auto-discovered)To read credentials in Python:
import json, os
from pathlib import Path
_creds = {}
for candidate in (
Path.home() / ".claude" / "sentinelone" / "credentials.json",
Path(os.environ.get("COWORK_WORKSPACE", "")) / ".sentinelone" / "credentials.json"
if os.environ.get("COWORK_WORKSPACE") else None,
Path(os.environ.get("CLAUDE_CONFIG_DIR", "")) / "sentinelone" / "credentials.json"
if os.environ.get("CLAUDE_CONFIG_DIR") else None,
Path.home() / ".config" / "sentinelone" / "credentials.json",
):
if candidate and candidate.is_file():
_creds = json.loads(candidate.read_text())
break
S1_CONSOLE_URL = os.environ.get("S1_CONSOLE_URL") or _creds.get("S1_CONSOLE_URL") or None
S1_CONSOLE_API_TOKEN = os.environ.get("S1_CONSOLE_API_TOKEN") or _creds.get("S1_CONSOLE_API_TOKEN") or None
Once resolved, validate them using the two-step test in references/api-integration.md
(system health check + token permission check). Only proceed with import/trigger/activate
after both checks pass. Always use a personal Console User API token, not a Service User
token — see references/api-integration.md for the reason.
| File | Read when... |
|---|---|
references/workflow-schema.md | Always when generating JSON — defines the envelope and action structure |
references/building-blocks.md | Need the exact shape of a specific action type (trigger, loop, condition, etc.) |
references/building-blocks-catalog.md | Picking what to use for a given step / composing multi-action idioms / bootstrapping a SOAR recipe. Mined from 643 active production workflows. Read FIRST when designing a new workflow. |
references/functions-reference.md | Using {{Function.X()}} syntax or PowerQuery patterns |
references/validation-rules.md | Before outputting any workflow — run the checklist |
references/api-integration.md | User wants to import/export/submit to a live console |
The catalog (references/building-blocks-catalog.md) names every reusable block. Use this
table to jump straight to the right starting point:
| User says... | Start with | Composite patterns to layer on |
|---|---|---|
| "When an alert fires, do X" | A1 (Singularity Response Trigger) + recipe C1 | B1 safe-field DEFAULT chain, B2 success/fail branch, B6 add-note |
| "Every day / every N hours, do X" | A3 (Scheduled Trigger) + recipe C2 | B7 SDL ingest, B9 IOC create, B5 JQ shaping |
| "When a webhook hits, do X" | A4 (HTTP Trigger) + recipe C3 | B2 status-code branch, B11 Slack ack |
| "Let an analyst kick this off with parameters" | A2 dynamic Manual Trigger + recipe C4 | B5 JQ shaping, B4 APPEND accumulator |
| "Wait for analyst approval before remediating" | recipe C5 (Slack approval) | B11 Slack interactive, B6 add-note |
| "Periodic posture / UEBA report" | A3 + recipe C6 | B8 PowerQuery, B7 SDL ingest |
| "Page through a paginated API" | B3 (cursor + break_loop) | B4 APPEND accumulator |
| "Summarize this evidence with an LLM" | B12 (OpenAI) | B6 add-note |
| "Create a Threat Intelligence indicator" | B9 (TI IOC create) | B4 accumulator inside loop |
| "Add a note on the alert" | B6 (UAM GraphQL addAlertNote) | always wrap text in Function.HTML_ENCODE |
When in doubt, the load-bearing 17 atoms are:
http_request, variable, condition, loop, singularity_response_trigger,
data_formation, send_email, snippet, break_loop, manual_trigger, wait_for_slack,
delay, http_trigger, scheduled_trigger, create_interaction, wait_for_interaction,
email_trigger. Anything outside this set is exotic; confirm it exists before generating.
Annotated real examples to use as structural references:
simple-linear.md — simple trigger → action → note patternbranching.md — condition with true/false branches + success/fail notesloop-pattern.md — loop with APPEND and BREAK logicintegration-pattern.md — integration-backed HTTP request with connection placeholdersWhen referencing a previous action in {{...}} syntax, use the kebab-case version of the
action's name field. Examples:
{{get-agents-with-active-threat.body.data}}{{sdl-query.body.matches[0].attributes.actor_user_email_addr}}{{singularity-response-trigger.data.id}}{{loop-the-list-of-ipv4.item}}The rule: lowercase, spaces become hyphens, special characters dropped.
Use this when the workflow contains integration-backed actions:
⚠️ Pre-requisite integrations to configure before importing:
- [Integration Name] — used for [action name(s)]. Configure at Hyperautomation → Integrations → [Integration Name] → Add Connection.
- (repeat for each)
Once configured, note the connection name — you may need to update the
connection_namefield in the JSON before importing.
Function.HTML_ENCODE on note text passed to UAM GraphQL. Any quote, ampersand, or angle bracket breaks the mutation string.
✅ Always wrap: \\\"{{Function.HTML_ENCODE(local_var.note)}}\\\".compared_value for comparison_operator: "in" as a raw JSON array.
✅ JSON-string-encode it: "[\"HIGH\",\"CRITICAL\"]".condition_type: "simple": never used in active corpus. Always emit "multi".wait_for_interaction using interaction_id / value field names (older docs).
✅ Real fields are identifier / time_value.singularity-response-trigger.data.scopeId.S1_CONSOLE_API_TOKEN.datasource / savelookup) from an HTTP action bound to the "SentinelOne" mgmt connection. That connection signs as Authorization: ApiToken, but the SDL query endpoints (POST /sdl/v2/api/queries and POST {sdl-host}/api/powerQuery) require Bearer, so the action returns HTTP 500 "Header must start with Bearer".
✅ Bind the "SentinelOne SDL" connection (Bearer by default) on the HTTP action. Notes: the ApiToken-only /web/api/v2.1/dv/events/pq cannot run the datasource command (returns 400) and is just an async wrapper over LRQ, so it is not usable for asset/inventory refresh; /api/powerQuery on the SDL host is synchronous (one call completes a savelookup) while /sdl/v2/api/queries is async. Tenant-validated 2026-06-13.Workflow import, export, and listing use the s1-secops-mcp MCP server, which bypasses the
Cowork sandbox proxy entirely. Use ha_list_workflows, ha_get_workflow, ha_import_workflow,
and ha_export_workflow directly instead of falling back to the mgmt-console-api
skill scripts. The MCP server runs locally on your machine and makes direct HTTPS calls to
*.sentinelone.net without proxy interference.
ha_import_workflow does not scope to a site. It posts to /import with no siteIds, so
on a site-scoped tenant it returns the misleading 403 "Insufficient permissions" — not a role
problem. For a site-scoped deploy, call the REST endpoint directly with the scope param:
POST /web/api/v2.1/hyper-automate/api/public/workflow-import-export/import?siteIds=<id> with
body {"data": <workflow>} (e.g. via the mgmt-console-api POST helper). For an
account-level deploy use the same public endpoint with ?accountIds=<acct>; the v1
/workflow-import-export/import?_scopeId=<acct>&_scopeLevel=account path returns 403. Same
scope rule applies to activation, deactivate, publish, and DELETE — append
?siteIds=<id> or ?accountIds=<acct> to match where the workflow lives. (1), (2), … to the name. To "edit" a
deployed workflow you must delete the old one (REST DELETE, see below) and re-import (or edit it
in the UI).DELETE. DELETE /hyper-automate/api/v1/workflows/{id}?accountIds=<acct>
returns 204 (soft, recoverable delete). Validated end to end (import → publish → delete → gone
from list). A 404 "Object not found" on delete means the id is not under that scope (or already
deleted); match the scope (?accountIds=/?siteIds=) to where the workflow lives.POST /hyper-automate/api/v1/workflows/{id}/publish
(bodyless, scope via ?accountIds=/?siteIds=, returns 204). This transitions Private Draft to
Shared Draft, so the flow appears in the team UI in an inactive (not-running) state. An imported
draft is private to the importer until it is published or activated; use publish to hand off a
reviewed-but-not-yet-runnable workflow, or to surface a draft for deletion.400 ("requires configuration" / "invalid references") when an
integration-backed action has no bound connection or a placeholder is unresolved. Bind the
connection (Hyperautomation → Integrations) and set the keys before activating, then deactivate
to leave it published but not running.npx claudepluginhub sentinel-one/ai-siem --plugin s1-secops-skillsCreates, validates, imports, executes, and exports CrowdStrike Falcon Fusion SOAR workflows using API-resolved action IDs via Python scripts.
Creates and configures Falcon Fusion SOAR workflow YAML for CrowdStrike Falcon Foundry apps. Guides step dependencies, error recovery, and state management for multi-step automation.
Build CrowdStrike Falcon Fusion SOAR workflows. Discover actions via live API, author YAML using our resource schema, validate locally, and save to resources/workflows/. Use when asked to create a Fusion workflow, SOAR playbook, or automate detection response.