| name | xsiam-playbooks |
| description | This skill should be used when the user asks to "create a playbook", "build a playbook", "design a playbook", "XSIAM playbook", "XSOAR playbook", "incident response workflow", "automation workflow", "playbook YAML", or needs to generate playbook definitions for Cortex XSIAM or XSOAR.
|
XSIAM Playbook Development
Generate importable unified YAML files for Cortex XSIAM/XSOAR playbooks. Playbooks define automated workflows with tasks, conditions, and sub-playbook calls. The YAML must match the exact structure and field ordering of a real XSIAM export for successful import.
Before Starting
Read the reference file to understand the playbook YAML format:
references/playbook-format.md — Complete playbook YAML schema: top-level structure, per-task field ordering, task type examples with all boilerplate fields, condition operators, script argument patterns, common flow patterns
What is a Playbook?
Playbooks are automated workflows that orchestrate tasks, integrations, scripts, and sub-playbooks to handle security incidents. They define the sequence of actions, decision points, and data flow for incident response.
When to use which skill:
- Automated incident workflows → playbook (this skill)
- Connecting to external APIs → integration (xsiam-integrations skill)
- Ingesting events into data lake → event collector (xsiam-event-collectors skill)
- Standalone data processing → script (xsiam-scripts skill)
Workflow
1. Gather Requirements
Determine the playbook category:
| Category | Trigger | Typical Pattern |
|---|
| Incident Response | Alert/incident type | Enrichment → Triage → Remediation → Close |
| Enrichment | Sub-playbook call | Parallel lookups → Merge → Output |
| Remediation | Sub-playbook call | Validate → Act → Verify → Report |
| Utility | Manual or sub-playbook | Input → Transform → Output |
Then gather conditional requirements:
- Uses integration commands? → gather brand names, command names, argument mappings
- Has condition/branching logic? → gather decision criteria, branch labels, inline conditions vs script-based
- Calls sub-playbooks? → gather playbook names, input/output mappings, whether any should iterate per list item (
forEach loop), and whether context stays sandboxed (separatecontext: true) or shared
- Needs user input? → gather collection task prompts and options
- Needs error handling? → for each fallible task, choose: stop the playbook (default), continue and ignore the error, or route to an
#error# handler branch
- Has parallel execution? → design fork/merge task topology
- What inputs does it accept? → define
key, default value, required, description
- What outputs does it produce? → define
contextPath, description, type
2. Design the Flow
Map out the task list before generating YAML. Present it as a numbered list for user approval:
"0" (start) → "1"
"1" (title: Enrichment Phase) → "2"
"2" (command: xdr-get-endpoints) → "3"
"3" (condition: Is Malicious?) → yes: "4", #default#: "5"
"4" (command: block-indicator) → "6"
"5" (command: close-incident, close as benign) → "6"
"6" (title: Done)
Each entry shows: task ID, task type, task name, and nexttasks wiring.
Get user approval on the flow before proceeding to YAML generation.
3. Generate the Unified YAML
Build a single .yml file following these ordered sub-steps. The YAML structure must match real XSIAM export format for successful import.
- Top-level metadata —
id (lowercase with hyphens), version: -1, vcShouldKeepItemLegacyProdMachine: false, name, tags (if applicable), starttaskid: "0"
- Tasks dictionary — each task with ALL boilerplate fields in exact field order per the format spec. Generate real v4 UUIDs for
taskid and inner task.id (both must be identical for each task). Position tasks following view layout rules (x: 450 main column, y increments of ~160-180px, branch offsets at x: 730).
- Top-level
view — JSON string with linkLabelsPosition: {} and paper.dimensions computed from task positions
inputs and inputSections — define all playbook inputs with key, value, required, description, playbookInputQuery. Wrap in inputSections with all keys listed. If the playbook has no inputs and no outputs, emit inputs: [] and outputs: [] and omit both section blocks entirely.
outputSections and outputs — define all playbook outputs with contextPath, description, type. Wrap in outputSections.
- Verify omissions — confirm no
fromversion, no tests, no marketplaces, no timeout
4. File Output
Generate a single file:
PlaybookName.yml — the unified YAML ready for import into XSIAM
After delivering the file, print a lightweight summary to the conversation:
- Description — 1-2 sentences on what the playbook does
- Trigger — what starts this playbook
- Dependencies — integrations, sub-playbooks, and scripts used
- Inputs — table with name, description, required, default value
- Flow — numbered steps with condition branches noted
- Outputs — table with contextPath, description, type
This summary is conversation-only — not a separate file. For full playbook documentation, use the xsiam-docs-playbooks skill.
5. Validate Structure
Before delivering, run the structural check and confirm it exits 0 (prints OK). If it errors, fix the YAML before delivering:
python3 -c "
import yaml, re
d = yaml.safe_load(open('PlaybookName.yml'))
tasks = d['tasks']
uuid4 = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\$', re.I)
for tid, t in tasks.items():
assert t['id'] == tid, f'id != key at {tid}'
assert t['taskid'] == t['task']['id'], f'taskid != task.id at {tid}'
assert uuid4.match(str(t['taskid'])), f'taskid not a v4 UUID at {tid}'
for targets in (t.get('nexttasks') or {}).values():
for nt in (targets or []):
assert nt in tasks, f'{tid} points to missing task {nt}'
branches = {k.lower() for k in (t.get('nexttasks') or {})}
for c in (t.get('conditions') or []):
lbl = str(c.get('label'))
assert lbl.lower() in branches, f'condition label {lbl} has no nexttasks branch at {tid}'
seen, stack = set(), [d['starttaskid']]
while stack:
n = stack.pop()
if n in seen:
continue
seen.add(n)
for targets in (tasks[n].get('nexttasks') or {}).values():
stack += (targets or [])
assert seen == set(tasks), f'unreachable tasks: {set(tasks) - seen}'
print('OK')
"
This catches taskid/task.id mismatches, nexttasks pointing at ids that do not exist, inline-condition labels with no matching nexttasks branch, orphaned tasks unreachable from starttaskid, and non-v4 UUIDs — linkage errors the eyeball checks below can miss.
Requires PyYAML (pip install pyyaml); if it isn't installed, skip this check and rely on the checklist below.
6. Validation Checklist
Before delivering, verify:
Structure:
Field Ordering:
Boilerplate:
Conditions:
Sub-Playbooks:
Commands:
Inputs/Outputs:
Omissions:
Key Conventions
- Playbook ID: lowercase with hyphens (e.g.,
incident-enrichment-playbook) — a house convention for generated content; IDs only need uniqueness, and real exports usually reuse the display name verbatim (spaces included), so never "correct" the ID of an existing/OOB playbook
- Playbook name: human-readable with spaces (e.g.,
Incident Enrichment Playbook)
- Task names: verb + noun format (e.g.,
Get Endpoint Details, Block IP Address)
- UUIDs: real v4 format (e.g.,
7c123a77-9e7e-412d-8292-c2a58536723c) — not placeholder patterns
- View positions: main column at
x: 450, branches offset at x: 730
vcShouldKeepItemLegacyProdMachine: false — always present after version
separatecontext on sub-playbook tasks: true (sandboxed, default choice — outputs must be mapped back explicitly); false shares context globally with the parent (deliberate choice; breaks generic polling)
- Error handling — three modes: Stop (default; no
continueonerror), Continue (continueonerror: true + continueonerrortype: "" — ignore the error and proceed), error path (continueonerror: true + continueonerrortype: errorPath + nexttasks.'#error#')