Writing policies and rules

This manual follows the work in the order a workspace administrator usually does it: define actions and optional Complyee reviews, choose facts, publish and enforce context contracts, write and test rules, handle approvals, and investigate decisions. Nothing here changes a workspace; it is safe to keep open while you build.

1. Define the actions this workspace answers for

An action is the exact name of a step an application may ask Agent Control Room to judge, such as document.read or library.write. Add a custom action or import an editable copy from the action catalogue, then give it a clear label and say what its payload fingerprint covers.

  • The action catalogue is a set of suggestions, not a permission list. Importing an action does not grant it or send anything to Complyee; the caller must actually ask about that action and consultation must be enabled separately.
  • An imported action is a detached, editable copy. Changing the catalogue later does not silently change a workspace.
  • Retired removes an action from new rule-authoring choices. It does not remove the action from existing rules or revoke earlier decisions; review those rules separately.
  • An undeclared action is refused, whatever the workspace default says. A declared action may be allowed by a matching grant rule or by a grant default. Refusal is the safer default because new actions cannot then become allowed merely by being declared.
  • Each agent also carries its own list of actions it may ask for, on the Agents page. That list is a second, narrower gate in front of the rules: an action the agent may not ask for is refused at the registry before any rule runs, and the decision records no policy or rule.
  • Leaving that list empty means any declared action, and that is the normal setting. The list is picked from this workspace's declared actions, so a name that matches nothing can no longer be typed in by mistake.
  • You may register agents before declaring any actions — an agent registered with an empty list simply follows the vocabulary as it grows. Narrow its list once the actions exist.
  • Retiring an action does not rewrite agents that already name it. Review those agents separately, as you would the rules.
  • For each action, choose Off (no Complyee consultation), Advisory (Path B: attach a reading without changing the rule's answer), or Gate (Path C: a restrictive check after local rules). Pair and test the workspace's Complyee service before turning consultation on. This feature implements the ACR–Complyee request and assessment contract; it does not assume another policy library is compatible. Complyee never grants permission or overrides a rule that refused or asked for a person.
  • For Gate, choose what happens when a rule allowed the step but the library cannot explicitly support it: Ask a person first or Refuse. An unavailable, late, conflicting, prohibiting or insufficient reading follows that setting. A specific ‘requires approval’ reading always holds the step for a person, even when the fallback is Refuse. A supported reading leaves an Allow in place; it does not create one.
  • Give the action a useful description, or have the caller supply a plain-language actionDescription for this exact step (1–2,000 characters). Keep descriptions and context facts free of personal data, secrets, document content and raw payloads. The library receives the agent and action keys, bounded description and up to 40 context facts — not the payload or prompt. Extra context fields can also be forwarded; send only facts suitable for the paired library.
  • A local Gate does not run when the workspace delegates decisions to a remote policy engine. Advisory review can still be recorded there, but it does not change that engine's answer.

2. Choose the facts needed to govern each action

A context contract belongs to one action and describes the facts its caller is expected to supply. Add custom facts or detached copies from the condition catalogue. Each fact card gives the field a technical name and a human label, then records its kind, meaning and expected supplier.

  • The condition catalogue suggests useful business facts, their meanings, agreed values and likely suppliers. Importing one does not make it required, enforce it, or add a rule.
  • The workspace context contract is the actual expectation for this action. Rule conditions are separate: they decide what valid information means for permission.
  • Choose Agreed values for a closed list, Text for unrestricted text, True/false for a JSON boolean, and Number for figures that may need limits, units or whole-number checks.
  • Use literal top-level context keys, for example {"resource.classification":"internal","page_count":12}, not nested objects. A required boolean false is present and valid.
  • Only use facts that trusted application code can supply. Agent Control Room checks shape and declared limits, not whether a claim is true or where it came from.

3. Publish, test and enforce context contracts

A published contract tells integrators what to send without blocking requests. When the caller is ready, a workspace administrator may enforce that contract for that action. Enforcement checks information before any policy rule runs.

  • Required means required when enforced. While the contract is only published, the marker is advisory and existing rules continue to decide.
  • Once enforced, a missing, empty, wrong-type, unlisted or out-of-range required fact produces context_validation_failed. The result is Not decided: no rule ran, no permission was issued and no person was asked. Optional facts are checked when supplied; undeclared extra fields are accepted.
  • Values are not normally converted between types. For a Number fact, the administrator may deliberately enable accepting a number sent as text; otherwise 7 is valid numeric input and "7" is the wrong type.
  • Check sample checks only the sample against the draft contract. It does not run the rules, create an approval, grant permission or prove that every caller is ready.
  • The public API page is the specification for caller behaviour, including discovery, frozen context, request identifiers, retries and context_validation_failed handling.
  • Replacing rules through the API without sending actions preserves the existing vocabulary and contracts. Sending actions deliberately replaces the complete vocabulary.

Piloting enforcement — one action at a time

The safe path is one action, in one workspace, with one integrator that has agreed the facts and the failure handling. The readiness confirmation exists because Agent Control Room cannot see whether caller code is ready.

  • Publish first. Let the integrator send the facts in ordinary traffic while they are still advisory, then confirm them in Decisions.
  • Agree that context_validation_failed means “not decidable yet”: record the named fields, correct the request and ask again. Never retry the same incomplete request blindly or act without a grant.
  • Verify a normal grant with complete facts, a missing-fact failure, an approval that is approved and claimed, and a safe retry before enforcing.
  • Know the rollback: return the action to published only and save. The facts remain visible, the pre-rule check stops for new requests, and the relaxation is recorded.
  • Watch one complete business cycle before enforcing another action.

4. Write policies and rules

A rule is a list of conditions, an effect, and optional obligations. Every condition must hold for the rule to match — they are joined with AND, never OR. To express “either of two situations”, write two rules.

  • Conditions — what must be true about the request: which agent, which action, what the resource reference starts with, a field the caller sent, the time, the day, the caller's network.
  • Effect — Allow, Refuse, or Ask a person first.
  • Obligations — how long a grant stays usable, and whether the approver must write a reason.
  • A rule with no conditions matches everything. That is almost never what you want on a granting rule.

5. Order decides the answer

Policies are evaluated in their given order, and within each policy its rules in order. The first rule that matches answers; nothing after it is considered. A disabled policy is skipped entirely. If nothing matches, the workspace default applies.

  • Put narrow refusals and approval holds above broad grants, not below them.
  • A broad grant near the top quietly makes everything below it unreachable.
  • Worked example: rule 1 holds file.delete for approval when the record is under legal hold; rule 2 grants file.delete in the test environment; the default refuses. A production delete matches neither rule and is refused; a test delete of a held record is held for a person, because rule 1 comes first.

6. The nine condition types

  • Agent is one of — restricts the rule to named, registered agents. Leave it out to mean any agent.
  • Action is one of — the exact action keys, matched as plain strings. document.read and document.Read are different actions.
  • Resource starts with — a prefix of the resource reference, for example contracts/2026/. Prefixes are how a rule is scoped to part of an estate.
  • There is no resource — the request names nothing, typical of actions like model.invoke.
  • Request field equals one of — a named field the caller sent has one of these values. This is the workhorse; see the next section.
  • Request number compares — a number the caller sent is below, at most, above, at least, or between the figures you set. Use it for permission thresholds, such as allowing up to 14 pages and asking a person from 15. Whether the number is valid at all belongs to the action's context contract, not here.
  • Time of day is within — a window in a chosen time zone; wraps past midnight when the end is before the start.
  • Day of the week is one of — the days the rule applies, in a chosen time zone.
  • Caller network is one of — the caller's address falls inside these CIDR ranges.

7. Use catalogue facts in rule conditions

“Request field equals one of” can compare any field, which makes it powerful and shapeless. The condition catalogue gives it shape: a curated list of business facts worth checking, with agreed values, the system that must prove each one, and the actions it suits. In the rule editor, tick an action and the relevant facts appear under “Suggested conditions”.

  • Field names are literal. resource.classification is the whole key the caller sends, not a path into a nested object.
  • Pick values deliberately. Selecting every listed value still requires the field to be present and equal one of them; remove the condition only when the fact should not affect matching.
  • Only check facts your systems can always prove. Missing fields never match, so an unreliable fact turns a grant into an intermittent refusal.
  • Standard facts for security scanners (sec.dlp_verdict, sec.pii_detected, sec.pii_categories_band, sec.secrets_detected, sec.prompt_injection_score, authz.external_verdict) and agent hand-offs (delegation.initiator_agent, delegation.via_agent, delegation.hop_count, delegation.human_origin) are published so every integrator names them the same way. ACR reads the verdict or the chain; it never scans content or tracks chains itself.
  • Worked example for agent hand-offs, in this order: first, a rule that refuses when Request number compares delegation.hop_count is above 2; second, a rule that asks a person first when delegation.human_origin equals false; then the rule that grants the action. A step passed on three times is refused, a step no person started waits for a person, and a short chain started by a person is allowed.
  • Worked example for circuit breakers, in Workspace settings: set Grants per chain to 50 in 60 seconds, Delegated steps per grant to 20, Grants per workspace to 1,000 in 60 seconds and a hold period of 300 seconds. An orchestrator that loops and keeps handing out work trips its own chain after its 21st hand-off or 51st grant in a minute; that chain is refused for five minutes while every other chain carries on. If the whole fleet surges past 1,000 grants a minute, every new grant is refused for five minutes. An administrator can close an open circuit early, and that is recorded in the audit trail.

8. Keep valid ranges separate from permission thresholds

A context contract asks whether information is valid. A rule asks what permission follows from valid information. Keeping those questions separate makes failures predictable and explanations accurate.

  • Example contract: page_count is a required Number, whole numbers only, from 1 through 500. Both limits count. A submitted value of 600 produces Not decided because it is outside the agreed range; it is not a policy refusal.
  • Example rules: a Request number compares condition allows page_count below 15; a later rule asks a person first when page_count is at least 15. Both 14 and 15 are valid facts, but they lead to different permission outcomes.
  • Worked example of a counted limit: on the rule that grants data.export, set at most 5 grants per 3600 seconds and not again within 60 seconds. Only issued grants count — refusals, waiting requests and repeated answers to the same request do not. When the limit is reached the rule answers Refuse and names the time the next slot opens. The count belongs to that rule alone — grants from other rules for data.export do not use it up — and renaming the rule restarts it from zero. For a cap across every rule, use the workspace circuit breakers.
  • For an exclusive boundary, turn off that limit counting. “Less than 15” excludes 15; “at most 15” includes it.
  • Number contracts reject numeric text unless the administrator explicitly accepts it. Numeric rule comparisons accept a finite number or numeric text; missing or non-numeric input simply does not match that rule.

9. Use trusted facts and exact payloads

Every fact in a request is supplied by the application around the agent. If the agent itself can choose what to send, the condition is decoration. Resolve classification, recipients, environment, counts and scan results in trusted code before asking for a decision.

  • Agent Control Room never inspects content. It receives a one-way fingerprint of the payload, not the payload.
  • A grant is bound to that fingerprint. Change what the step would touch and the grant no longer applies — you must ask again.
  • Rule evaluation is deterministic for its inputs and saved rules. Optional policy-library readings can vary over time, so Agent Control Room records and reuses a reading for the same waiting step instead of re-consulting on every retry or claim. It also retains decisions, approvals, claims, counted grants and safe-replay receipts.
  • How often a rule may grant is the one figure the engine counts for itself. Other cumulative limits, such as a daily spend total, belong in the calling service or another authoritative system that supplies a trusted fact.
  • A fact can be asked to carry its provenance: who asserted it and when it was observed. Name the services whose word you accept and the longest age you will trust, and the caller sends { value, assertedBy, observedAt } instead of a bare value. Worked example: source_system is required, provenance required, accepted asserters document-service, maximum age 300 seconds. An assertion from the agent itself, or one observed an hour ago, is Not decided — no rule runs.

10. Follow an approval from request to claim

Ask a person first does not issue permission. It opens an approval request and returns its reference to the caller. The screen and API use one lifecycle vocabulary so administrators and callers can describe the same state.

  • Waiting for a person means nobody has answered. If nobody answers before the request deadline, it becomes Approval request expired. A refusal becomes Refused by approver.
  • Waiting for approval claim means a person approved and the caller may claim for 15 minutes. This claim window is separate from the lifetime of the grant that will be issued.
  • The caller claims by repeating the identical decision request. It then becomes Approval claimed, creates a resulting Granted decision, and receives a short-lived, single-use grant for the exact payload. If nobody claims in time, it becomes Approval claim expired.
  • The original policy reason is historical: it explains why the first request was held. It remains past tense while the live approval status moves forward.
  • Worked example of separation of duties: on the rule that holds deployment.release, tick that the agent's registered owner may not approve it. The owner recorded on the Agents page then sees the reason in the queue instead of an approve button, and the engine refuses the attempt even if the request is made another way. The owner may still refuse the step.
  • Require an approver note for irreversible work; Decisions shows that note, the answer and claim times, the claim deadline, and the resulting decision.
  • A Gate that holds a rule-allowed step opens the same human approval queue as a rule hold, with reason library_gate_held. The recorded policy-library assessment, citations and corpus fingerprint are shown alongside the step where available. The approver decides; the library cannot approve for them.
  • While that approval is open, retries reuse its recorded reading. When a person approves and the caller claims the identical step, the resulting grant inherits that reading rather than asking the library again. The decision trail distinguishes the held request, the approval and the resulting grant.

11. Test before saving

Before saving, the editor shows what the new rules would have answered for recent decisions from this workspace. Review changed answers and remember that this comparison cannot prove whether an external caller supplies the right facts.

  • Look for a granting rule with no conditions, a grant default, or a broad grant above a narrow refusal or approval hold.
  • Check action keys exactly. document.read and document.Read are different strings.
  • Confirm every request field has a trusted supplier. A missing field does not match a rule.
  • If a request was refused with no policy and no rule recorded, look at the agent's own list of actions it may ask for before looking at the rules — that gate runs first.
  • Pause all agents while rewriting when no new step should proceed under the old rules.

12. Investigate answers in Decisions

Decisions shows the current outcome and the recorded reason. Workspace administrators can open Details to compare every declared fact with what the caller submitted and what the contract expected.

  • Not decided means no policy rule ran, usually because an enforced context contract could not validate the request. Refused means the rules or workspace default did answer and did not permit it.
  • For a fact failure, compare Declared fact, Expected, Submitted and Check. A numeric failure appears as Outside the agreed range; a provenance failure as No acceptable provenance or Observed too long ago, with the asserter and observation time shown beside the submitted value.
  • Approval details show the approver's decision and note, answer time, claim deadline, claim time and resulting decision. The timing line on the row summarises the live stage.
  • Older records may not contain a saved contract snapshot. Historical expectations unavailable means ACR cannot safely reconstruct the comparison; it is not evidence that the caller omitted the fact.
  • A revoked grant remains in the record as history but can no longer authorise the step.
  • A local rule-backed grant that passed a supporting restrictive Gate has a Gate supported badge and a ‘Granted · Rule allowed + policy library gate supported’ detail heading. This means the rule allowed and the recorded assessment supported it; it is not a human approval or an independent verification of the caller's facts. Details include assessment ID and corpus fingerprint when supplied, plus the payload fingerprint and evidence-record path.
  • Workspace administrators can use Export recent decisions (CSV) for the latest 200 decision records. It separates the authorization path (rule and supporting gate, human approval, or ordinary grant) and includes policy, rule, reason, payload fingerprint, library assessment, citations, timestamps and evidence-record path. Intermediate claim-request rows are omitted from the export, not deleted from the underlying record. This spreadsheet-safe snapshot is not the separate administrative audit stream, a signed CSV, or a complete historical export; keep the underlying decision and approval records for audit review.

13. Five worked policies

  • Exporting data — Action is data.export; resource.classification equals confidential or restricted; effect: require approval, approver reason required. A second rule grants data.export when classification is public or internal.
  • Sending external email — Action is email.send; recipient.class equals external or public; effect: require approval. A rule above it refuses outright when security.scan_result equals fail.
  • Deleting files — Rule 1: action file.delete with record.legal_hold equal to true or unknown, effect reject. Rule 2: file.delete with operation.mode equal to soft_delete and resource.environment equal to test, effect grant. Everything else falls to the default refusal.
  • Deploying — Action is deployment.release; resource.environment equals prod; day of the week Monday to Thursday; time of day 08:00–16:00; effect: require approval. A grant rule covers dev and test with no window.
  • Granting access — Action is authorization.permission.grant; identity.target_privilege equals admin or break_glass; effect: require approval with a reason. Ordinary privilege is granted to the named provisioning agent only.

This manual explains administration and interpretation. The public API page remains the authoritative integration reference for request shapes, retries, approval polling and error codes. A workspace's own policies, actions and decisions are visible only to signed-in administrators.