Rules
Overview
A **rule** limits what the selected asset may do. Write it in one line of plain language and Fencio builds the conditions from it. Rules act on the asset you selected with fencio assets use.
Before you write a rule
An agent reaches its goal through steps. Each step can look reasonable on its own while contributing to an outcome you would never approve. A rule describes the outcome boundary once, so Fencio can judge every step against it.
Rules are **allow-only**: you state what is permitted for the asset. A step that contradicts a permitted boundary is denied, and anything the rule does not constrain stays permitted (all). Exceptions are written inside the boundary with **all except**.
How a rule is constructed
You write one line, or fill individual fields. Fencio turns it into a rule object the enforcement engine can evaluate against evidence. Every field is always present: anything you leave unset is stored as all, never omitted.
The five condition fields
| Field | Question it answers | Example boundary |
|---|---|---|
| `user_request.content` | What content may appear in the request? | Don't let secrets or regulated data into prompts |
| `user_request.context.scenarios` | Which kind of activity is this? | Development and testing, not production operations |
| `asset_impact.data_flow` | What data may cross the asset's boundary? | Keep CRM data inside approved systems |
| `asset_impact.resource_state` | What persistent state may change? | Delete test data, never live CRM records |
| `asset_impact.runtime_operation` | What may run at runtime? | Read and build freely; destructive tests only against an approved test database |
The first two describe the request. The last three are impact: what the action may do. All applicable fields combine with **AND**: every boundary must hold.
The selectors that scope a rule
| Selector | Values | Notes |
|---|---|---|
| `action` | `read`, `write`, `execute` | Deleting a file through file tools is `write`; deleting it by running `rm` is `execute`. |
| `direction` | `request`, `response`, `both` | Default `both`. |
| `target` | `request`, `response`, `both_text`, `tool_call` | Tool-call rules depend on parser coverage. |
| `mode` | `enforce`, `monitor` | Default `monitor`: record what would happen without blocking. |
| `scope` | `org`, `user` | Set at creation. |
| `unknown_handling` | `block`, `review`, `allow_flag` | What to do when the evidence is inconclusive. Tool-call rules default to `block`. |
From a sentence to an enforceable rule
- **Statement**: your line is split into clauses, and each clause is assigned to a field.
- **IQL**: each clause becomes an IQL query over the asset's concepts (
all,in,all except, combined withandandor). - **Compile and bind**: the query is validated against the field's limits and bound to the asset's catalog. An
andbecomes slot-filling, soDELETE AND ENV_FILEbecomesDELETE(target=ENV_FILE). - **Gloss**: every node gets a one-sentence meaning, so the rule stays readable.
- **Sync**: the rule is validated, stored, and pushed to the rule engine that evaluates traffic.
A rule is written in the asset's catalog: the concepts it names must exist there, or Fencio proposes new concepts for you to approve.
Impact enforcement
Impact is the heart of a rule. Two agents can send the same request, run the tests, and get opposite outcomes depending on which database the command reaches. Fencio decides on the impact, not the wording.
The three impact fields
| Field | Asks | Judged over |
|---|---|---|
| `asset_impact.data_flow` | What information moves, and in which direction? | Each inferred flow: direction (inbound or outbound) and what is transferred. |
| `asset_impact.resource_state` | What persistent change happens? | Each inferred impact: a state transition (create, modify, delete) and the resource. |
| `asset_impact.runtime_operation` | What runs? | Each inferred operation: build, run tests, deploy, network request and so on. |
Each is matched by meaning, not by command name. A delete through a file tool and an rm command can both resolve to a delete transition; what matters is the concept the evidence establishes.
How the fields combine
request_matches = content AND scenarios
impact_matches = data_flow AND resource_state AND runtime_operation
allow = action AND direction AND request_matches AND impact_matches
An empty impact set (no flow, no state change, no operation) matches, because there is nothing to violate.
What unknown means
Evidence is not always complete. A rule can leave a slot unfilled, such as delete the files without saying which, and a tool call may not have an active parser contract yet. When the evidence is inconclusive, unknown_handling decides:
- **
block**: deny and report. The default for tool calls. - **
review**: deny and hold for a person to decide. - **
allow_flag**: allow, and flag the step for review.
What the decision is made from
- **Concepts**: the asset's vocabulary. A rule is written in it, and evidence is reported in it.
- **Parsers**: deterministic extractors that turn a tool call into facts: the action, roles, exact paths, hosts and branches. No model, so the same input yields the same facts.
- **Context**: the session and what came before. Tool output is tracked as it flows into later steps, so a value from an untrusted result is visible when it is used.
- **Session and run**: steps are grouped per turn and per run, so a rule is evaluated with the chain that produced it.
Worked example
| Step | Impact field | Evidence | Decision |
|---|---|---|---|
| Read CRM code | `resource_state` | No state change | Allow |
| Edit tests | `resource_state` | Changes test files only | Allow |
| Read fixture | `content` | Permitted development read | Allow, but track `DATABASE_URL` |
| Run tests against the live database | `runtime_operation` and `resource_state` | The operation is allowed, but it would delete live records | **Block** |
Create a rule
Describe the boundary in one line. If the line is ambiguous, Fencio proposes the clauses to confirm rather than guessing:
fencio rules create
List and show
List the rules on the selected asset, and show one in full:
fencio rules list
fencio rules get <rule_id>
Update
Change a rule's name, mode or content:
fencio rules update <rule_id>
Readiness
Show what a rule still needs before it can be enforced, such as a parser fact it depends on:
fencio rules readiness <rule_id>
Parser setup
Configure the parser facts a rule is missing, guided by the readiness report:
fencio rules parser-setup
Organisation enforcement
Show or change whether rules are enforced for your organisation. With enforcement on, each intercepted step is evaluated and blocked when it contradicts a rule. With enforcement off, rules are recorded but not enforced.
fencio rules enforcement
fencio rules enforcement enable
fencio rules enforcement disable
To verify a rule without blocking work, create it in monitor mode first. Run fencio rules update <rule_id> and switch the mode to enforce once you are satisfied with the decisions.
Delete
Delete a rule and stop enforcing it:
fencio rules delete <rule_id>