helixordevelopers

Make your first decision

You write a small function that sends every payload through a decision pack and branches on the action it returns. Here the pack is the built-in example pack (data protection, compliance.regulatory_pii_guard.v1), whose actions fall into three outcomes: permit the payload, forward a redacted copy, or block it. Every later tutorial builds on this function.

Tier 015 minutesBeginnerPython 3.9+

About the example

This tutorial uses the built-in data-protection pack so you can run everything without writing a pack first. The same calls work for any decision pack: eligibility, limits, routing and so on. See Core concepts.

What you'll build#

A script, first_guard.py, that evaluates five payloads (four strings and one dict) and prints the outcome, the rules that fired, the text you may forward and the receipt for each one.

Prerequisites#

  • The runtime installed in a virtual environment. See Installation.
  • You have read the Quickstart, or you know what evaluate() returns.

No license file, account or network access is needed. HelixorEngine() loads the built-in example pack.

Steps#

  1. Create the engine once

    An engine is cheap to call and safe to reuse, so create one at module level and call it for every payload. Creating one per request wastes time and gains nothing.

    from helixor_runtime import HelixorEngine
    
    engine = HelixorEngine()
    print(f"pack={engine.pack_id} version={engine.version} tier={engine.tier}")
    
  2. Map every action to an outcome class

    A pack returns one of a closed list of actions, so you can map every one of them to what your code does next. In the example pack they fall into three classes. Check for block first, because a blocked payload also has invariants_passed == False, just like a redacted one.

    OutcomeHow to detect itWhat you forward
    blockaction.startswith("block")Nothing. The payload must not leave your process, redacted or not.
    permitinvariants_passed is Trueremedy.clean_text, which equals the input.
    redactAnything else. Today that means redact_and_permit_contact_pii.remedy.clean_text, the repaired copy.
    def guard(payload):
        """Return (outcome, text_to_forward, decision)."""
        decision = engine.evaluate(payload)
    
        if decision.action.startswith("block"):
            return "block", None, decision
        if decision.invariants_passed:
            return "permit", decision.remedy.clean_text, decision
        return "redact", decision.remedy.clean_text, decision
    
  3. Evaluate a list of inputs

    Add five payloads that cover every outcome class. The last one is a dict: evaluate() accepts a dict and reads its text, message or payload key.

    inputs = [
        "Move the design review to Thursday at 2pm.",
        "Please email the invoice to billing@example.com or call (415) 555-0100.",
        "New hire paperwork: SSN 123-45-6789, start date Monday.",
        "Charge the renewal to 4111-1111-1111-1111 and email jane@example.com.",
        {"message": "Reach me at (212) 555-0199 after lunch.", "channel": "chat"},
    ]
    
    for payload in inputs:
        outcome, forward, d = guard(payload)
        print(f"\n{outcome.upper():6} {d.action}")
        print(f"       rules   : {[t.rule_id for t in d.triggers]}")
        print(f"       forward : {forward!r}")
        print(f"       receipt : {d.receipt_hash}")
    
  4. Run it
    python first_guard.py
    
    pack=compliance.regulatory_pii_guard.v1 version=1.0.0 tier=COMMUNITY
    
    PERMIT permit_clean_payload
           rules   : []
           forward : 'Move the design review to Thursday at 2pm.'
           receipt : hx_proof_d41e4ee7179255ffa8ed178a
    
    REDACT redact_and_permit_contact_pii
           rules   : ['RULE-GDPR-EMAIL-REDACT', 'RULE-TCPA-PHONE-REDACT']
           forward : 'Please email the invoice to [REDACTED_EMAIL] or call [REDACTED_PHONE].'
           receipt : hx_proof_067cd4020bd4f1ba3ff796ea
    
    BLOCK  block_glba_ssn_leakage
           rules   : ['RULE-GLBA-SSN-BLOCK']
           forward : None
           receipt : hx_proof_6ae04f03dd436188714e822b
    
    BLOCK  block_pci_dss_pan_leakage
           rules   : ['RULE-PCI-DSS-PAN-BLOCK', 'RULE-GDPR-EMAIL-REDACT']
           forward : None
           receipt : hx_proof_c8bb35dc65e91d5219f2d95f
    
    REDACT redact_and_permit_contact_pii
           rules   : ['RULE-TCPA-PHONE-REDACT']
           forward : 'Reach me at [REDACTED_PHONE] after lunch.'
           receipt : hx_proof_0686c07a3cb8f0ad22dea925
    

    Receipts are deterministic, so the same input gives the same receipt on every machine.

  5. Look inside one decision

    The card payload shows two things worth knowing. Every rule that matched is reported in triggers, and the first fatal one decides the action. The remedy covers everything the pack found: here it redacts every category, including the email.

    from helixor_runtime import HelixorEngine
    
    engine = HelixorEngine()
    d = engine.evaluate("Charge the renewal to 4111-1111-1111-1111 and email jane@example.com.")
    
    print("action            :", d.action)
    print("invariants_passed :", d.invariants_passed)
    print("reason            :", d.reason)
    for t in d.triggers:
        print("trigger           :", t.rule_id, t.severity, t.law)
    print("clean_text        :", d.remedy.clean_text)
    print("redactions        :", d.remedy.redactions_count, d.remedy.redacted_categories)
    print("latency_us        :", d.latency_us)
    print("tokens / egress   :", d.tokens_spent, d.egress_bytes)
    print("edition           :", d.edition)
    
    action            : block_pci_dss_pan_leakage
    invariants_passed : False
    reason            : Statutory violation: Credit Card PAN (PCI-DSS Requirement 3) detected
    trigger           : RULE-PCI-DSS-PAN-BLOCK FATAL PCI-DSS Requirement 3
    trigger           : RULE-GDPR-EMAIL-REDACT WARNING GDPR Article 6 & CCPA
    clean_text        : Charge the renewal to [REDACTED_CARD_PAN] and email [REDACTED_EMAIL].
    redactions        : 2 ['Credit Card PAN (PCI-DSS)', 'Email (GDPR/CCPA)']
    latency_us        : 72.79
    tokens / egress   : 0 0
    edition           : COMMUNITY
    

    latency_us varies by machine and is highest on the first call. It covers evaluation only, not license checks or receipt hashing.

Dict input reads one field only

evaluate(dict) evaluates the first of text, message and payload that is present, even if it is empty, and ignores every other key. For example, {"text": "hi", "message": "SSN 123-45-6789"} is permitted. A dict with none of those keys, or with a value that is not a string, raises CodonRuntimeError. To screen a whole record, evaluate each string field, or serialize the record, as the API middleware tutorial does.

How it works#

For each payload the engine runs the pack's codons to extract typed facts into state, then checks every one of the pack's rules in a fixed order. The first fatal rule to match decides the action, and every match is reported in triggers. In the example pack, the codons are pattern extractors (with a Luhn check for card numbers) that build a state such as has_ssn or has_email, and the rule order is SSN, card, health record, then contact details. If no fatal rule fires, any contact detail produces the single redact action with one trigger per category. The remedy is always computed, so a blocked result still tells you what was found without you having to show the value.

A few inputs that look sensitive are permitted by the example pack by design. A phone number needs ten digits, so 555-0100 alone does not match. A 16-digit number that fails the Luhn check is not treated as a card. Put inputs like these in your tests; see Testing policies.

For the full field list, see the Python reference. For how rules and remedies fit together, see Core concepts and Evaluating decisions.

Next steps#