nano SIEM
Playbooks

Authoring Playbooks

Slash-command markdown grammar — phases, step kinds, per-kind params, when clauses, and the Visual ↔ Source round-trip

Authoring Playbooks

A playbook is written as markdown with slash-commands. The same document is parsed server-side into a structured step tree and rendered in the authoring wizard's Visual canvas; analysts can flip between Visual and Source freely without losing information.

Minimal example

# Credential reuse · offboarded / dormant account

Agent-first identity investigation for the pattern
"account that shouldn't be active is active."

## Triage

/enrichment: HR status for the user
  system: workday
  employee: {{entity.user}}
  fields: status, end_date, manager, team

/query: last 30d of auth events for this user
  from:   auth-events
  window: 30d
  where:  user = {{entity.user}}

## Investigate

/decision: is this a live user account?
  options:
    - yes · employed and active
    - no · offboarded
    - partial · on leave / role changed
  note_required_on: no, partial

## Contain

/action: rotate or disable the compromised credential
  kind:    iam.key_rotate
  target:  {{entity.user}}
  danger:  medium
  approval: required
  when:    d1 in [no, partial]

Grammar

Title (#)

The first # Heading becomes the playbook title. Exactly one title per doc.

Phases (##)

## Heading starts a phase. The Build canvas maps headings to the four canonical phase buckets — Triage, Investigate, Contain, Close — using keyword matching:

Heading keywordPhase bucket
triageTriage
investigate, analyze, decideInvestigate
contain, respond, actionContain
close, review, wrapClose

Phases can be nested conceptually (you can write ## Phase 1 · establish state — the keyword "establish" matches nothing, so it becomes an unphased block at the top of the canvas). Unphased steps always render above any phased steps.

Steps (/kind:)

/kind: label starts a step. The label is the one-line summary shown at the top of the card; per-kind parameters live on indented key/value lines below.

Seven step kinds:

KindWhat it represents
/queryPull data from a source (e.g. auth-events)
/pivotBranch the investigation on an entity
/enrichmentLook up external context (HR, WHOIS, IPInfo…)
/decisionAsk the analyst to choose among options
/actionMutate the world (rotate a key, isolate a host)
/reviewHuman confirmation step
/noteFreeform note / instruction

Step parameters

Indented key: value pairs under a step become step.params. Values are stored as strings — the parser does not type-coerce. List values use YAML-style dashes:

/decision: is this a live user account?
  options:
    - yes · employed and active
    - no · offboarded

when: clauses

Any step can carry a when: clause that gates its execution on prior decisions:

/action: rotate or disable the compromised credential
  when: d1 in [no, partial]

d1 refers to the first /decision step's answer key (the first word of the chosen option). Supported forms:

  • d1 = yes — equality
  • d1 in [yes, partial] — set membership

Special params

These are lifted out of params into first-class fields on the step:

ParamMoved to
options:step.options
note_required_on:step.note_required_on
id:step.id (overrides the auto-generated id)
when:step.when (parsed)

Per-kind parameters

UDM fields in examples below are the real flat snake_case identifiers from the nano schema. See UDM Fields for the full set.

/query

ParamMeaning
fromSource dataset id (auth-events, edr-network, …)
windowTime window (24h, 7d, 30d)
where / filterBoolean expression over UDM fields
/query: cloud API calls from this user in the last day
  from:   cloudtrail
  window: 24h
  where:  user = {{entity.user}} AND source_type = "cloudtrail"

/pivot

ParamMeaning
onUDM field to fan out on
keysOptional sub-specifier
/pivot: per-source-IP summary
  on: src_ip

/enrichment

ParamMeaning
systemExternal system id (workday, ipinfo, virustotal)
fieldWhat to look up
Any additional keys are passed verbatim to the enrichment call
/enrichment: HR status for the user
  system: workday
  field: employment_status
  employee: {{entity.user}}

/decision

ParamMeaning
options: (list)Answers the analyst chooses from
note_required_onComma-list of answer keys that force a note

The first word of each option is the answer key used by downstream when: clauses.

/action

ParamMeaning
kindDotted action id (iam.key_rotate, edr.isolate_host)
targetEntity / identifier the action hits
dangerlow · medium · high — drives approval routing
approvalauto · required — inline override
reversibleBoolean hint for the operator

/review

ParamMeaning
criteria / hintWhat the analyst is confirming
approverOptional role or user id that must sign off

/note

No params — just a freeform instruction block. Parser emits kind: "note" with the label as the body.

Visual ↔ Source round-trip

The authoring wizard's Build phase exposes both views. Switching is lossless:

  • Visual → Source — the draft's flat step list is re-emitted as slash-command markdown, preserving phase headings via the keyword mapping above and only including params with non-empty values.
  • Source → Visual — the textarea is parsed via the same parser the server uses; the resulting step tree is flattened into the canvas, tagging each step with the phase its heading mapped to.

Short hints that describe what to type (format reminders, example values) render inline beneath the field label in the Visual form. Longer explanatory copy lives behind a ? tooltip icon on the label — the redesign convention.

Validation

Each kind has a soft validator that surfaces a NEEDS INPUT chip on the step card when a required param is missing:

KindRequired
/queryfrom
/pivoton
/enrichmentsystem + either field or key
/decisionat least 2 options
/actionkind, target, danger
/reviewcriteria or hint
/notea non-empty label

Validation does not block publishing — it signals the author — and the counter in the Build toolbar rolls up into the Review phase's policy-check section.

On this page

On this page