Skip to main content
Start with mode: observe: every action is decided exactly as enforce mode would decide it, executes regardless, and records what would have been blocked. After a week ctrlrun stats tells you what enforcing will cost, in refusals and in approval requests, before a single refund waits for a human. Then change one line. Prerequisites: a policy for the actions your agent already performs, and the decorator or the gateway in front of them. The blocks below simulate a week in a few calls.
1

Observe

runnable
runnable
Both emails went out, including the one to gmail.com. Observe mode is not a dry run: it executes, and it asks no human. What it adds is the counterfactual on every receipt.
2

Read the numbers

runnable
Counted from the local store and nothing else: no network, no upload. --since 7d narrows the window and --json gives the same numbers to a script.
3

Fix the policy, not the count

Each would have needed approval is a real approval request you will field once you enforce. If the rate is wrong, the band is wrong: raise the autonomous limit for the action, or add a rule for the case that dominates. Each would have been denied is an action your agent performs today that will stop, named by the rule; decide whether that is the point. A duplicate is a retry loop you did not know about.
4

Enforce

Change the line, redeploy, and the same receipts now carry refusals instead of counterfactuals:
Nothing else changes: same policy, same store, same evidence format. Every would_have becomes a BLOCKED receipt or an approval request, and ctrlrun stats reports less and says so.

What observe mode will not do

It will not stop an action the policy would deny, and it will not ask a human. Run it on traffic you would run unprotected today. It is one line for the whole deployment; there is no per-action observe. An adapter’s pre-invocation predicate answers “no approval needed” in observe mode, for the same reason: a human’s no must not stop what observe mode promises to run.

If it didn’t work

  • PolicyError: mode is refused anywhere but the top level: mode: is inside an action entry.
  • ctrlrun stats shows enforce mode reports less: the store was written in enforce mode; there are refusals to count, not counterfactuals.
  • A receipt has no would_have: it was written before mode: observe was in force.

Next