Modes
Observe records, assist prompts, enforce denies. One line of config moves between them, and the ledger records the real verdict in all three.
Modes
One line of config moves between three modes, which is the point. A bank runs observe on real traffic, reads the catch report, and flips to enforce when the contracts have stopped surprising them.
| Mode | What happens |
|---|---|
observe | Records the verdict. Stops nothing. This is the default |
assist | A failing check becomes a prompt. Nothing is denied outright |
enforce | BLOCK denies. ESCALATE asks you |
The verdict does not change with the mode
The verdict recorded in the ledger is always the verdict the contract produced. Only the effect on the call changes.
That is what makes an observe-mode ledger a truthful account of what enforce would
have done, and it is why coco report can tell you what enforcement would have
cost you before it costs you anything.
Setting it
Locally, edit ~/.coco/config.json and restart Claude Code.
{ "mode": "enforce" }On the SDK road, the mode is an environment variable on the gate and nothing in your code changes.
COCO_MODE=enforceThe gate reads the mode once at boot rather than per request, so it cannot change underneath a call that is already being decided. Restart the container for a change to take.
A mode change is also on the record without any extra work, because every receipt
carries gate_mode. The ledger itself shows the moment enforcement turned on or
off, so the decision to flip it is auditable from the same rows an auditor already
reads, and who may flip it is who you gave write access to the config.
Assist mode
assist sits between the two. A failing check becomes a prompt without denying
anything outright, and it is a reasonable place to stop for a team that wants a
person in the loop and not a hard stop.
Over HTTP a prompt has nowhere to appear, so in assist mode any failing check comes back as ESCALATE and your harness decides who answers. A non-interactive harness should treat that the way it treats any escalation, park the action and put it in front of a person.
It is a resting place rather than a destination. A prompt on every failing check trains people to approve reflexively, which is the failure mode observe mode exists to avoid from the other direction.
Turning enforcement on
Read the report with the people who own the rules, fix what is drafted wrong, and then flip one setting. Nothing in your code changes.
From that moment the same call comes back like this, and the call does not run.
{"verdict": "BLOCK", "reason": "Coco: The command is a destructive operation with no safe reading in a governed workflow", "mode": "enforce"}When something is blocked and should not be
coco ledger --verdict BLOCKshows the contract and the reason.- Fix the contract, not the ledger. Run
coco compile, then restart. - To stop enforcing immediately, set the mode back to
observe. Nothing is lost and decisions keep recording.
Fixing the contract is the slower answer and it is the right one. A ledger full of blocks nobody agreed with is not evidence of anything.
What observe mode does not protect you from
Observe mode records the verdict and stops nothing, so it stops nothing. A team that runs observe indefinitely ends up with a complete audit trail of harm it did not prevent.
The report is the argument for moving, and the point of the mode is that the argument is made from your own traffic rather than from ours.