Fail-closed means that when a permission decision cannot be resolved, the system denies the action rather than allowing it. The opposite — fail-open — allows on ambiguity, which is how automated systems cause damage nobody authorised.
Where it applies in Anter
Unrecognised modes or risk classes. If the runtime cannot classify a tool's risk or does not recognise a permission mode, it falls back to ask — the most conservative option — never to allow.
No human available. This is the case that most often surprises people. A run with nobody to answer an approval request — a scheduled run, or an agent-to-agent hop with no operator watching — converts every would-be "ask" into an automatic deny.
It does not block forever waiting for an approver who will never arrive, and it does not quietly proceed. Both alternatives are worse: one hangs your automation, the other performs unapproved actions.
Why not just wait
A pending approval on an unattended run is an unbounded wait. It consumes a run slot, holds state, and eventually times out anyway — having accomplished nothing while looking like progress. Denying immediately produces a clear, diagnosable outcome.
Designing around it
If a scheduled or cross-agent workflow needs to perform a gated action, you have three honest options:
- Grant that specific tool an explicit per-tool allow, accepting the risk deliberately
- Give the path a non-interactive fallback that does not need the gated tool
- Split the workflow — automate the safe part, queue the gated part for human review
What does not work is assuming the tool will run because it usually does in interactive testing. This is the single most common cause of "it worked in the playground but not on a schedule."
Beyond permissions
The same instinct shows up elsewhere in the runtime: hop limits and cycle detection stop chains rather than letting them run away, and exhausted budgets end a run with an explicit termination reason rather than degrading silently.