The rule sheet

A rule sheet states the rules over your tools as YAML a person can read aloud: a refund over 200 needs a supervisor's approval; closing an account waits for the customer to confirm; nobody deletes a customer. It compiles to the same rulebook a Colang policy becomes, so the guardrail reads a sheet exactly as it reads Colang.

A sheet

rules:
  - action: refund_card
    requires: [supervisor_approved]
    when: { amount_over: 200 }
  - action: charge_card
    requires_confirmation: true
  - action: send_receipt
    after: [charge_card]
    at_most: 1

Every key

One rule per action. Each rule names its action, one of your tools, and says one or more of:

Key What it says What it compiles to
requires: [a, b] the action runs only where every named context holds a deny-by-default flow for the action, guarded on $a and $b
when: {amount_over: 200} when the requirements apply, as conditions on the call's own arguments: <argument>_over, _under, _at_least, _at_most or _is the guard holds only where the condition does; the tool check computes the condition from the call's arguments, so the host cannot set it
never: true the action never runs a flow that refuses it unconditionally
requires_confirmation: true a person confirms each call a confirmation the catalogue declares, enforced by the tool check
confirmation: "…" the same, with the words the person is asked as above, with the wording
after: [tool] the action runs only after each named tool, in the same session the order rule, enforced by the tool check
not_after: [tool] the action never runs after a named tool as above
at_most: 3 the action runs at most that many times in a session as above
check: [{field: quantity, at_most: {from: check_stock.in_stock}}] conditions on the call, all of which must hold: a value, a list, or what an earlier tool returned the tool's own conditions; a value the tool check cannot read refuses the call

Confirmations, order and checks are laid over your tools; the rulebook decides whether an action may happen at all. In the guardrail, the first stop is named your_rules (the rulebook, conditions, limits and spend), order or, for a confirmation, the call waits for the person.

Compiling it

The service compiles a sheet; the decisions are then made on your machine.

$ stalwart rules compile rules.yaml --out-dir compiled

writes rulebook.ir.json, catalogue_overlay.json and rule_sheet.co (the Colang it equals) to compiled/. Pass the folder as Guardrail(..., rules="compiled"). A sheet's path also works (rules="rules.yaml"): it is compiled when the guardrail is made, with QLS_API_KEY.

In stalwart mcp: compile_rules("rules.yaml") writes the same folder, and the other tools read it.

The lints

The sheet is checked against your tools, and each problem is a lint, not a failure:

lint_rules("rules.yaml") in stalwart mcp lists them against the tools the guardrail checks.

What is refused

A sheet the compiler cannot state exactly is refused, naming its line, and nothing is written:

A sheet is refused rather than approximated: an approximation would be a rule you did not write, enforced as though you had.

The limits