Enforcement Modes¶
autonomy runtime start evaluates every proposed action against the loaded
policy (and the execution-decision model)
and, by default, enacts the result: a deny/defer blocks the action, an invalid
or reject verdict fail-closes, and a replace verdict substitutes the authorized
action. The --enforcement flag selects whether the runtime enacts decisions or
only observes them (#1373).
--enforcement¶
Value |
Aliases |
Behavior |
|---|---|---|
|
— |
Default. Every decision is enacted: deny/defer block, invalid/ |
|
|
The real policy + execution-decision model are evaluated and the would-be policy decision is WAL-recorded exactly as enforce mode would compute it, but the policy verdict never blocks — the original proposed action is forwarded unchanged, never dropped, held, replaced, or rejected on the policy verdict. (A separate in-execute governance layer — the |
An unset or unrecognized value falls back to enforce (the fail-safe default —
enforcement is never silently disabled by a typo); an unrecognized value also
prints a startup warning.
What monitor mode does¶
In monitor mode the runtime still runs the full decision path — so the WAL is a truthful record of what enforce mode would have done — but skips policy-side enactment and forwards the original action (the in-execute governance layer below is not suppressed):
The policy-layer (would-be) decision — the verdict the runtime chose not to enact — is stamped
enforcement_mode: monitorandenforced: false, so replay and audit consumers can tell a would-be verdict from an enacted one. The frame’soutcome(and anyverdict/reason_codes) is the real, unshaped policy result.The stamp is per-decision, not per-server. A deny from the in-execute governance layer (the
executeToolegress allowlist / mediators — a separate layer monitor mode does not suppress; see below) is a real enforced block and is recorded as an ordinary deny frame without the monitor stamp, so consumers never mistake a genuine runtime block for an observed-only verdict.
/v1/toolreturnsdecision: allowregardless of the would-be verdict. A gradedverdictrides the response as observability metadata, but noauthorized_actionsubstitute is offered — monitor forwards the original, it does not authorize a replacement.It is orthogonal to
--decision-only: in decision-only mode the runtime returns this allow to the external republisher (the governed bridge), which then forwards the original message on the real domain.
Monitor mode suppresses policy enforcement and the runtime vetoes. The
in-execute governance layer inside executeTool (the tool.http_get
allowlist / egress-DLP, the MAVLink/ROS2 mediators) is a separate layer and still
applies when the runtime itself delivers in-process; for the external-bridge
(decision-only) topology it is not on the path.
Use cases¶
Ungoverned baseline. Run the real policy in monitor mode with
--capture-action-input so the raw
action reaches the actuator while every would-be verdict + action input is logged.
Then A/B the baseline WAL against governed bundle versions with
policy verify replay --from-wal. Unlike shipping an always-allow bundle, you
observe what your actual policy would decide without it affecting behavior.
Shadow / canary policy evaluation. Load a new or revised policy in monitor mode
in production to see what it would decide — the decisions land in the WAL for
review while behavior is unchanged — before flipping the same deployment to
--enforcement=enforce.
$ autonomy runtime start --policy ./bundle \
--decision-only --enforcement=monitor --capture-action-input
runtime start: MONITOR mode — policy verdicts are evaluated + WAL-recorded but NOT enforced; the original action is forwarded on the verdict (separate in-execute guards may still reject)
Pair monitor mode with --capture-action-input whenever you intend to replay: the
autonomy.action_input frames are what policy verify replay --from-wal
re-evaluates against a candidate bundle.