Playbook schema
The keys a playbook file can contain, their types, and which of them the 0.2.1 runtime actually executes. Read the "What runs in 0.2.1" section before you write rules.
About the example
Field examples such as PII_SSN_EXTRACT and RULE-PCI-DSS-PAN-BLOCK come from the built-in data-protection pack, which ships with the runtime. The keys themselves describe any decision pack: eligibility, limits, routing and so on. See Core concepts.
What runs in 0.2.1#
A playbook is a declarative description. In 0.2.1, two engines use it in different ways:
| Engine | How you get it | What it executes |
|---|---|---|
| Built-in example pack | HelixorEngine() | The six codons and the four rule groups of the example pack, compliance.regulatory_pii_guard.v1 (data protection), built into the runtime. The published playbook documents this pack; the engine does not read a YAML file. |
| Compiled pack | helixor-pack compile, then HelixorEngine.load_pack(), run or serve | Your rules (regex and Luhn checksum) and the example pack's built-in checks. Sections it would not execute are rejected at compile time, except the few listed below that are stored but not used. |
For a compiled pack in 0.2.1:
rulesare executed on every payload, together with the example pack's built-in checks. Every match is reported intriggers. The first fatal match decides the action, with your rules checked first, in file order; with no fatal match, the first warning decides.hard_rulesandcodonsare limited to the built-in ones. The compiler accepts the example pack's four hard rules and six codons only if unchanged, and rejects anything else withUnsupportedPackDeclarationError. Executing your own is Planned.default_actionis not used. A payload that breaks no rule always getspermit_clean_payload.actionsis not enforced. The action names come from the rule IDs (see Action naming) and are not checked against this list.invariants,remediesandbudgetare accepted but not executed.
Fixed in the next release: declarations are enforced
actions, when present, must list every action the pack can return:permit_clean_payload, the four built-in actions (block_glba_ssn_leakage,block_pci_dss_pan_leakage,block_hipaa_phi_leakage,redact_and_permit_contact_pii) and<block|redact>_<id>for each of your rules. A list that leaves one out fails withUnsupportedPackDeclarationErrornaming the missing actions. Omittingactionsis allowed.default_actionmay only bepermit_clean_payload, or omitted; any other value is rejected.budgetaccepts onlymax_latency_ms(positive) andmax_tokens(0 or more; the engine spends none). Any other key is rejected.max_latency_msis checked on every decision, and a slower decision raisesDecisionBudgetExceededErrorwith its result withheld.invariantsandremediesare still accepted and not executed.
The checks run at compile time and again at load, so a pack compiled by 0.2.1 whose declarations break them fails to load with PackDeclarationUnsealError; recompile it from a corrected playbook. The examples on this site list every action, so they compile with 0.2.1 and with the next release.
The same checks run again when a pack is loaded, so a pack sealed by an older compiler with declarations the engine ignores fails to load instead of running without them.
Known issues in 0.2.1
- A blocked value can stay in
clean_text. When a block rule fires and nothing else was redacted,clean_textbecomes[BLOCKED: Prohibited Content]. When another rule redacted something, the text keeps the blocked value and only the other redactions are applied. - Capturing groups narrow the match. With a pattern such as
(AB)(C), only the first group,AB, is reported and redacted.
Workaround: never forward clean_text from a result whose action starts with block, and write patterns with non-capturing groups, (?:...).
Fixed in the next release. Redact rules replace every whole match by position, overlapping matches merge into one redaction, and any fired block rule makes clean_text [BLOCKED: Prohibited Content]. A pattern such as (ACCT)-(\d{6}) reports and redacts ACCT-123456, the whole match.
Example#
A valid playbook for a compiled pack. Quote any string value that contains ": ", such as descriptions. Unquoted, YAML reads the colon as a new key and compilation fails with CompilerError: Failed to parse YAML playbook.
pack_id: custom.internal_code_guard.v1
version: 1.0.0
name: Internal Project Code Guard
kind: compliance
description: "Blocks internal project codes: never send them outside."
budget:
max_latency_ms: 1.0
max_tokens: 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+\b'
action: block
default_action: permit_clean_payload
Compiled and run, Release PROJ-ZEUS-9 today returns action block_project_code. It has one trigger, project_code, with severity FATAL, and clean_text is [BLOCKED: Prohibited Content]. See Custom rules for the full walkthrough.
Top-level keys#
| Key | Type | Required | In 0.2.1 |
|---|---|---|---|
pack_id | string | yes | Identifies the pack and is sealed into the container. Your license must allow it (see License file). Convention: <domain>.<name>.v<n>. |
version | string | no | Default 1.0.0. Reported as the pack version. |
name | string | no | Display name. Defaults to pack_id. |
kind | string | no | Free-form category, default safety_guard. Appears as law on triggers from your rules. |
description | string | no | Stored. |
budget | map | no | max_latency_ms, max_tokens. Documents intent; not enforced. Enforced in the next release (see above). |
floor | number | no | Confidence floor carried into the manifest. Not stored in a compiled pack. |
actions | list of strings | no | Stored; not enforced. In the next release it must list every action the pack can return (see above). |
rules | list | no | Executed (see below). |
codons | list | no | Only the example pack's built-in codons, unchanged; anything else is rejected. Your own: Planned |
hard_rules | list | no | Only the example pack's built-in hard rules, unchanged; anything else is rejected. Your own: Planned |
invariants, remedies | list, map | no | Stored; not executed. |
default_action | string | no | Not used; permit_clean_payload is always returned. In the next release any other value is rejected. |
required_solvers, solver_id, solver_constraints | list, string, list | no | Checked against your license's licensed_solvers at compile and load time. A solver_constraints entry with a type and no solver ID counts as solver solver.tcn.basic. Solver behavior is out of scope for this reference. |
forecasting_config, belief_config | map | no | Stored; out of scope for this reference. |
Unknown top-level keys are ignored by the compiler. There is no schema validation beyond the checks listed under Compile-time checks.
rules#
The custom rules a compiled pack executes. All of them run on every payload, in order; every match is reported, and the first fatal match decides.
| Key | Type | Meaning |
|---|---|---|
id | string | Required. Rule ID. Appears as rule_id and in the action name. |
type | string | regex (the default) or luhn_checksum. Any other value is rejected. |
pattern | string | Required for regex. A Python regular expression, matched case-sensitively with no flags anywhere in the text. Single-quote it in YAML so backslashes survive. An invalid pattern is rejected at compile time. |
min_length, max_length | int | For luhn_checksum: digit counts to consider, default 13 and 19. Runs of digits, optionally separated by spaces or hyphens, that pass the Luhn check match. |
action | string | block gives action block_<id> and severity FATAL. redact gives redact_<id> and WARNING, and replaces each match in clean_text with [REDACTED_<ID>]. block_or_redact, found in older catalog packs, is read as block. Any other value is rejected. Default block. |
codons#
Codons describe how to extract typed state from input. The example pack's six codons have this shape. A compiled pack accepts only those six, with their built-in patterns.
| Key | Type | Meaning |
|---|---|---|
code | string | Unique codon ID, for example PII_SSN_EXTRACT in the example pack. |
kind | string | Default codon. |
codon_type | string | extract_pattern, checksum_validator, range_filter or custom. |
trigger | string | on_input, on_condition or on_remedy. Only on_input is used today. |
params | map | For extract_pattern: pattern, optional extra *_pattern keys, and flags (a list of MULTILINE, IGNORECASE, DOTALL, ASCII). |
checksum | string | luhn keeps only matches that pass the Luhn check. |
binds_to | string | The boolean state field set when there is a match, for example has_ssn. |
matches_field | string | Optional state field that holds the matches. |
remedy_template | string | Replacement text for each match in the remedy, for example "[REDACTED_SSN]" in the example pack. |
hard_rules#
Declarative rules over state, as used in the example pack's playbook. A compiled pack accepts only the example pack's four, unchanged; your own are Planned.
| Key | Type | Meaning |
|---|---|---|
id | string | Rule ID, for example RULE-PCI-DSS-PAN-BLOCK in the example pack. |
condition | string | An expression over state, for example state.has_ssn == True or state.has_email == True or state.has_phone == True. |
action | string | One of actions. |
description | string | Becomes the result's reason. Quote it. |
severity | string | fatal, warning or info. |
Severities#
| In YAML | In results | Meaning |
|---|---|---|
fatal | FATAL | The payload must not proceed, remedied or not. |
warning | WARNING | The payload may proceed after the remedy is applied. |
info | not emitted | Documentation only. |
Action naming#
| Prefix | Meaning | Examples |
|---|---|---|
permit_ | Proceed unchanged. | permit_clean_payload |
redact_ | Proceed with remedy.clean_text. | redact_and_permit_contact_pii, redact_<rule id> |
block_ | Stop. | block_glba_ssn_leakage, block_<rule id>, block_custom_rule_<literal> |
Name your rule IDs in lower case with underscores (project_code) so the generated action names read well. Branch on trigger severity rather than parsing action names.
Compile-time checks#
helixor-pack compile fails with an error when:
- the file is not valid YAML, or its root is not a mapping (
CompilerError); pack_idis missing (CompilerError);- your license neither lists the
pack_idinlicensed_packsnor has thecustom_playbook_compilationfeature (LicenseEntitlementError); - a declared solver is not in
licensed_solvers(LicenseEntitlementError), or the solver declarations cannot be read (PlaybookParseError, aCompilerError); - a rule has no
id, an unsupportedtypeoraction, nopattern, or a pattern that is not a valid regular expression; or a codon or hard rule is not one of the example pack's built-in ones, unchanged (UnsupportedPackDeclarationError, which lists every problem).
It does not check action names against actions, or the contents of invariants and remedies. See Playbooks and Testing policies.