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 and does not add a step to Complyee or any other application; the caller must actually ask about that action.
- 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.
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.
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.
- 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.
- Each decision is a pure function of the request and your saved rules, so the same question is always answered the same way. Agent Control Room is not stateless: it deliberately 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.
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.
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.