> For the complete documentation index, see [llms.txt](https://docs.kyvvu.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kyvvu.com/policy-authoring/rules-reference.md).

# Built-in Rules Reference

**What you'll learn:** All 27 built-in rule functions, grouped by category, with their parameters and applicable scopes.

***

The engine ships with 27 built-in rules grouped into six categories. Each rule is a pure function: `rule(data, params, context) -> bool`. Returns `True` to pass, `False` to violate.

## Field rules

Applicable to `agent_registration` and `step_execution`.

| Rule                  | What it checks                          | Parameters                        |
| --------------------- | --------------------------------------- | --------------------------------- |
| `field_not_empty`     | Named field has a non-empty value.      | `field: str`                      |
| `field_in_list`       | Named field's value is in an allowlist. | `field: str`, `values: list[str]` |
| `field_matches_regex` | Named field matches a regex pattern.    | `field: str`, `pattern: str`      |

## Path rules

Require task history. `step_execution` only.

| Rule                                   | What it checks                                                                                                                                                                                     | Parameters                                                                                                                                                              |
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `step_directly_preceded_by`            | The immediately preceding step in history is the required type.                                                                                                                                    | `required_step_type: str`, `target_step_types: list[str]` (optional), `target_verb: str` (optional), `target_property_filter: dict` (optional)                          |
| `step_requires_predecessor`            | Some earlier step in history has the required type.                                                                                                                                                | `required_step_type: str`, `target_step_types: list[str]`, `target_verb: str` (optional), `target_property_filter: dict` (optional)                                     |
| `step_preceded_by_without_intervening` | A required predecessor exists with no forbidden steps between.                                                                                                                                     | `required_step_type: str`, `forbidden_intervening: list[str]`, `target_step_types: list[str]`, `target_verb: str` (optional), `target_property_filter: dict` (optional) |
| `step_requires_dedicated_predecessor`  | Each target step has its own unconsumed predecessor — one predecessor cannot authorise two target steps.                                                                                           | `required_step_type: str`, `target_step_types: list[str]`, `target_verb: str` (optional), `target_property_filter: dict` (optional)                                     |
| `step_requires_gate`                   | A matching `step.gate` precedes this step. The gate may be any distance earlier in history (no freshness enforcement).                                                                             | `target_step_types: list[str]`, `target_verb: str` (optional), `gate_check_type: str` (optional), `gate_result: str` (optional, default `pass`)                         |
| `sequence_forbidden`                   | A forbidden ordered sequence (subsequence over history + current step) has not occurred.                                                                                                           | `forbidden_sequence: list[str]`                                                                                                                                         |
| `step_not_after`                       | This step type is forbidden once a forbidden predecessor type has occurred (permanently tainted).                                                                                                  | `target_step_types: list[str]`, `forbidden_predecessor_step_types: list[str]`, `target_verb: str` (optional)                                                            |
| `path_within_root`                     | Allowlist containment: the target path resolves at or under the session `project_root`. Lexical only — `..` is collapsed but symlinks are not resolved; fails open when `project_root` is unknown. | `field: str` (optional, default `target.host`), `target_step_types: list[str]` (optional), `target_verb: str` (optional), `target_verbs: list[str]` (optional)          |
| `history_contains`                     | The history contains a step matching type + optional verb + optional property filter.                                                                                                              | `step_type: str`, `verb: str` (optional), `property_filter: dict` (optional)                                                                                            |
| `current_is`                           | The intended behaviour matches type + optional verb + optional property filter.                                                                                                                    | `step_type: str`, `verb: str` (optional), `property_filter: dict` (optional)                                                                                            |

## Count rules

| Rule                         | What it checks                                                                                               | Scopes           | Parameters                                                                                    |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------- | --------------------------------------------------------------------------------------------- |
| `execution_max_steps`        | Task has not exceeded a maximum count of the given step type.                                                | `step_execution` | `step_type: str`, `max_steps: int`, `verb: str` (optional)                                    |
| `max_consecutive_same_type`  | No run of the same step type exceeds a limit.                                                                | `step_execution` | `step_type: str`, `max_consecutive: int`                                                      |
| `cross_execution_rate_limit` | Agent has not exceeded N of this step\_type in the last M minutes across tasks.                              | `step_execution` | `step_type: str`, `max_count: int`, `window_minutes: int`, `property_filter: dict` (optional) |
| `usage_budget`               | Cumulative usage metric across task history has not exceeded budget. The first occurrence is always allowed. | `step_execution` | `step_type: str`, `property_path: str`, `budget: float`                                       |

## Classification rules

| Rule                                | What it checks                                                                          | Scopes           | Parameters                                                                                                                                       |
| ----------------------------------- | --------------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `step_forbidden_for_classification` | This step type is not permitted for the agent's risk classification.                    | `step_execution` | `forbidden_step_type: str`, `agent_risk_classifications: list[str]`, `forbidden_verb: str` (optional), `target_property_filter: dict` (optional) |
| `working_hours_only`                | Current time is within a permitted window. Supports overnight wraparound and timezones. | `step_execution` | `start_hour: int`, `end_hour: int`, `timezone: str` (optional, default UTC)                                                                      |
| `step_name_in_allowlist`            | This step's name is in the agent's declared tool allowlist.                             | `step_execution` | `agent_field: str`, `target_step_types: list[str]` (optional)                                                                                    |

## Content rules

| Rule               | What it checks                                                                                                                                                            | Scopes           | Parameters                   |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ---------------------------- |
| `pii_in_request`   | Step input does not contain PII matching configured regex patterns. Patterns are required; no defaults. Input is serialised via `json.dumps` so nested dicts are scanned. | `step_execution` | `patterns: list[str]`        |
| `domain_allowlist` | Step's target domain is in an allowlist.                                                                                                                                  | `step_execution` | `allowed_domains: list[str]` |

## Flow rules

| Rule                             | What it checks                                                                                                  | Scopes           | Parameters                                                                                                                                                    |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `conditional_successor_required` | If the previous step matches a trigger type and condition, the current step must satisfy successor constraints. | `step_execution` | `trigger_step_types: list[str]`, `trigger_condition: dict`, `required_step_type: str` (optional), `forbidden_step_types: list[str]` (optional)                |
| `tainted_path_block`             | If any prior step matches the taint pattern, certain downstream steps are blocked.                              | `step_execution` | `taint_step_type: str`, `target_step_types: list[str]`, `taint_verb: str` (optional), `taint_property_filter: dict` (optional), `target_verb: str` (optional) |
| `all_of`                         | Compound: passes iff all sub-conditions pass.                                                                   | Both             | `conditions: list[condition]`                                                                                                                                 |
| `any_of`                         | Compound: passes iff any sub-condition passes.                                                                  | Both             | `conditions: list[condition]`                                                                                                                                 |
| `not`                            | Compound: passes iff the sub-condition fails.                                                                   | Both             | `condition: condition`                                                                                                                                        |

Each sub-condition in compound rules is a dict with `rule_type` and `params` keys.

## Programmatic discovery

Rules are self-documenting. To list all rules programmatically:

```python
from kyvvu_engine import PolicyRule

# All rules for a given scope
rules = PolicyRule.get_all_rules(scope="step_execution")
# → {"field_not_empty": {"description": "...", "scopes": [...], "params_schema": {...}}, ...}

# Validate a rule exists
valid, error = PolicyRule.validate_rule_params("pii_in_request", {"patterns": ["\\d{3}-\\d{2}-\\d{4}"]})
```

The platform dashboard uses this metadata to render dynamic forms when creating policies.

***

## Next steps

* [Creating Policies](/policy-authoring/creating.md) — use these rules to author policies
* [Compound Policies](/policy-authoring/compound.md) — combine rules with `all_of`, `any_of`, `not`
* [OWASP Default Template](/policy-authoring/owasp-default.md) — see 8 of these rules in action


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kyvvu.com/policy-authoring/rules-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
