Each action may additionally publish context: { mode: published | enforced, revision, facts: [{ field, kind, required, values?, label?, meaning?, source?, min?, max?, minInclusive?, maxInclusive?, integer?, unit?, acceptNumericText?, asserters?, provenanceRequired?, maxAgeSeconds? }] }. Kinds are enum (string values), text, boolean and number. A number fact expects a JSON number; its optional limits, whole-number setting and unit describe which numbers are valid information, and a value outside them is reported with the issue code range. A number sent as text is rejected unless the fact sets acceptNumericText. A fact with provenanceRequired expects { value, assertedBy, observedAt } instead of a bare value; assertedBy must be one of the named asserters and observedAt no older than maxAgeSeconds, otherwise the issue codes provenance and stale are returned and the request is undecidable. Required is advisory while the contract's mode is published. When a workspace switches an action's contract to enforced, required facts are checked before any rule runs and a request that omits one, sends the wrong type or an unlisted value is returned as context_validation_failed with contractRevision and contextIssues[] — undecidable rather than refused. Optional facts are validated only when supplied. Catalogue values remain strings without coercion. Extra context fields are permitted.
Revisions change on contract edits; absent context means no published expectations. Remote mode returns the remote engine’s description, not a local enforcement guarantee: when an action is enforced locally and the workspace uses an external engine, decideAction fails closed with context_enforcement_unsupported instead of returning a decision without the check.
The policy engine describes itself: identity, mode, rule set version and source, default effect, and every action it answers for with the payload fields each decision is bound to. The action list is the workspace's own declared vocabulary — key, label, optional description and what the payload hash binds — maintained by its administrators; an action absent from it matches no rule and falls to the default effect, which is a refusal. The current describePolicyEngine response does not include an action's policy-library consultation mode or Gate fallback. Read those in Workspace Policies; do not infer Off, Advisory or Gate from the action description.
The optional 43-action catalogue is not returned wholesale: only imported or manually declared workspace actions appear. Imports never overwrite local definitions or install rules; existing broad grants or a grant default can nevertheless cover a newly imported action.
Map provider operations to exact consequence-based keys (for example, an outbound email to email.send rather than generic api.mutate). Suggested conditions use literal top-level context keys: {"recipient.class":"internal"} or {"record.legal_hold":false}, not nested objects. The corresponding Request field equals one of condition uses recipient.class = internal or record.legal_hold = false. A Request number compares condition tests a numeric context field against a threshold (below, at most, above, at least, between) and is the place for permission thresholds; a contract's limits only say whether the number is valid at all. Missing facts fail that equality check, not necessarily the entire ordered rule set.
Trusted application code must populate facts, freeze context for retries, and bind safety-relevant intent into payloadHash. Descriptive binding notes do not cause ACR to inspect content, scan files, enforce budgets or configure connectors. This is the contract an external engine must implement to be swappable. A policy-engine operation — when the workspace uses an external engine, that engine's own answer is returned.