helixordevelopers

Playbooks

A playbook is the source of a decision pack: a YAML file that names the pack, lists its actions, declares how facts are extracted and states the rules. This page explains each section, using the built-in example pack (data protection, compliance.regulatory_pii_guard.v1) as the worked example.

About the example

This page uses the built-in data-protection pack so you can read a complete, working playbook without writing one first. The same sections describe any decision pack: eligibility, limits, routing and so on. See Core concepts.

The whole file at a glance#

pack_id: compliance.regulatory_pii_guard.v1
version: 1.0.0
name: Regulatory PII and Sensitive Data Guard
kind: compliance
description: "Fail-closed PII inspection for GLBA, PCI-DSS, HIPAA and GDPR/CCPA."

budget:
  max_latency_ms: 1.0
  max_tokens: 0

actions:
  - permit_clean_payload
  - block_glba_ssn_leakage
  - block_pci_dss_pan_leakage
  - block_hipaa_phi_leakage
  - redact_and_permit_contact_pii

codons:
  - code: PII_SSN_EXTRACT
    kind: codon
    codon_type: extract_pattern
    trigger: on_input
    params:
      pattern: '\b(?!000|666|9\d{2})\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b'
    binds_to: has_ssn
    matches_field: ssn_matches
    remedy_template: "[REDACTED_SSN]"
  # ... card (with checksum: luhn), health ID, email, phone, IP

hard_rules:
  - id: RULE-GLBA-SSN-BLOCK
    condition: state.has_ssn == True
    action: block_glba_ssn_leakage
    description: "Statutory violation: Social Security Number (GLBA / FCRA) detected"
    severity: fatal
  # ... PCI-DSS, HIPAA (fatal), contact details (warning)

default_action: permit_clean_payload

Quote descriptions that contain a colon

A value such as Statutory violation: ... must be quoted, or YAML reads the second colon as a new key and the file fails to parse.

Identity#

KeyPurpose
pack_idRequired. Stable, dotted, ends in a major version: <domain>.<name>.v<N>. Licenses grant packs by this ID, so changing it is a breaking change.
versionSemantic version of this revision. Bump it on every change you ship.
name, kind, descriptionHuman-facing metadata.

Budget#

budget.max_latency_ms and budget.max_tokens record the pack's intended envelope: under a millisecond, zero model tokens. They document intent for reviewers; the runtime does not enforce them in 0.2.1. In the next release a compiled pack enforces them: max_latency_ms is checked on every decision, a slower decision raises DecisionBudgetExceededError with its result withheld, and any other budget key is rejected. Set max_latency_ms with room for your slowest host.

Actions and the default#

actions is the closed set of outcomes the pack may return. default_action names the outcome when no rule fires; a compiled pack always returns permit_clean_payload then. In the next release a compiled pack enforces both: actions, when present, must list every action the pack can return, including the five of the built-in checks, and default_action may only be permit_clean_payload. See Playbook schema. Name actions so callers can route on the prefix, as the example pack does:

  • permit_… the payload may proceed unchanged,
  • redact_… the payload may proceed as remedy.clean_text,
  • block_… the payload must stop.

Codons#

Each codon extracts one typed fact from the input into state. The keys that matter:

KeyMeaning
codeUnique codon ID, upper snake case.
codon_typeextract_pattern for regular-expression extraction. Also defined: checksum_validator, range_filter, custom.
triggeron_input: run on every evaluation.
params.patternThe regular expression. params.flags takes MULTILINE, IGNORECASE, DOTALL, ASCII.
checksumluhn discards matches that fail the Luhn check.
binds_toThe boolean state field set when anything matches.
matches_fieldThe state field that holds the matches.
remedy_templateReplacement text for each match in remedy.clean_text.

Rules#

A rule pairs a condition over state with an action and a severity (fatal, warning or info). Rules are evaluated in file order; put the most severe first.

What runs in 0.2.1#

The playbook format is ahead of the pack compiler. Know which parts execute. The compiler rejects declarations a compiled pack would not execute, with UnsupportedPackDeclarationError, instead of sealing them silently:

SectionBuilt-in example packPack you compile
The example pack's built-in codons and rulesRunRun
rules entries with type: regex or type: luhn_checksumn/aRun on every payload, next to the built-in checks
Your own codonsn/aRejected at compile time; executing them is Planned
Your own hard_rulesn/aRejected at compile time; executing them is Planned
budget enforcementNot in 0.2.1. For a pack you compile: fixed in the next release (max_latency_ms checked on every decision)

To add your own detection today, declare regex rules:

pack_id: acme.project_codes.v1
version: 1.0.0
actions: [permit_clean_payload, block_project_code, block_glba_ssn_leakage,
          block_pci_dss_pan_leakage, block_hipaa_phi_leakage, redact_and_permit_contact_pii]
rules:
  - id: project_code
    type: regex
    pattern: '\bPROJ-[A-Z]+-\d[A-Z]\b'
    action: block
default_action: permit_clean_payload

How regex rules behave in 0.2.1:

  • Every rule and every built-in check runs on every payload, and every match is reported in triggers. The first fatal match decides the action, with your rules checked before the built-in ones; with no fatal match, the first warning decides.
  • The returned action is block_<id> (here block_project_code) with severity FATAL for action: block, and redact_<id> with severity WARNING for action: redact. Name the rule id so that the result reads well, and list the same name under actions for reviewers.
  • A redact rule replaces each match with [REDACTED_<ID>], the rule ID in upper case. When a block rule fires and nothing else was redacted, remedy.clean_text is [BLOCKED: Prohibited Content]; otherwise the blocked value stays in clean_text, so never forward the text of a blocked result. Fixed in the next release: any fired block rule withholds the whole text.
  • Use non-capturing groups, (?:...). With a capturing group, only the first group's text is reported and redacted. Fixed in the next release: the whole match is reported and redacted.

Compile it with your license and run it; see Packs and the custom rules tutorial. The full key list is in the playbook schema reference.

Writing good playbooks#

  • Anchor patterns with \b and test them against both true and near-miss inputs.
  • Prefer a checksum where the identifier has one; it removes most false positives.
  • Avoid nested quantifiers such as (a+)+. Patterns run on every payload with no timeout.
  • Keep a golden test set next to the playbook and run it in CI before compiling. See Testing policies.