Consoles go down. A cloud region has an outage, a VPN drops, a laptop boards a plane, a plant’s uplink fails. The agents keep working through all of it. The question for a vendor is not whether their control plane can be unreachable. It is what their product enforces while it is.
Where the decision lives
Two designs answer that question very differently.
Gateway-only and proxy-only designs
Every agent call is judged by a service in the network path, between the agent and the model or tool. When that service is unavailable it has two options: refuse every call, which stops the agents, or pass every call through unchecked, which keeps them working with no control at all. Either way the outage is a security event.
On-device enforcement
Each call is judged on the device where the agent runs. The console signs policy and receives alerts, but it is not in the path of a call. An outage delays alerts and policy updates. It does not switch enforcement off.
A vendor may combine the two, so ask about each enforcement point separately. These five questions get to the answer.
Five questions to ask any vendor
1. Where is each call decided?
On the device, or in a service across the network? If the answer is a service, ask what that service does when it cannot be reached, and whether the agent keeps running meanwhile.
2. With the console unreachable, which policy is enforced, and how does the device know it is genuine?
A cached policy is only as good as the check on it. If the device trusts any file in the right place, whoever can write that file writes the policy. Ask whether the cached copy is signed, and what happens when the signature does not verify.
3. If no policy can be verified at all, what happens, and who chose that?
A fresh install that has never reached its console, or a device whose copies were deleted, has nothing to enforce. The answer should be a default someone chose on purpose and can state, not whatever the code happens to do.
4. When the product itself cannot decide, does it fail open or closed?
Engines throw, time out and meet input they cannot read. Ask who sets the answer, whether it can differ per enforcement point, whether a refusal raises an alert, and whether the user running the agent can change it.
5. What happens to the alerts raised during the outage?
Ask where they wait, how many and for how long, what happens when that store is full, and whether you are told when anything is dropped. “They are sent later” without a bound is not an answer.
How MoorAI answers
MoorAI for Agents (free, open source under MIT) runs in the coding agent’s pre-tool hook. The MoorAI Management Server signs each tenant’s policy and receives the alerts.
1. On the device
The pre-tool hook decides each tool call on the device, before it runs, and so do the MCP gateway and the model proxy routed to a model inside the network. Enforcement needs no network. When the console stops answering, tool calls do not wait on it: after a policy fetch gets no answer, later calls skip the fetch for a window that grows to at most five minutes, and one call in eight still tries.
2. The cached copy, then the last-known-good copy, each verified
When the console does not answer, the device enforces its cached policy. When no cached copy verifies, it enforces its last-known-good copy: the last policy whose signature verified, checked again on the way in. Every copy is checked against the console’s signing key before it is used, and a copy that fails the check counts as no policy, never as a weaker one. A policy older than its maximum age is still enforced, and an alert says how old it is. Enforcing the cached copy or the last-known-good copy is reported to the console as an alert.
3. The offline posture the administrator chose
If nothing verifies, the device applies the offline posture its administrator set in the signed policy, a root-owned machine latch, or the machine’s admin binding. Fail closed applies a small, reviewable fail-closed default: it blocks secrets, personal data, payment-card data and health data, asks before destructive commands, and makes every MCP tool call ask. Otherwise an enrolled device applies the built-in prevention defaults, which hard-deny a reverse shell and local secret-value egress and ask before credential-file access, destructive tool calls, unsanctioned installs and unapproved model endpoints. Applying the fail-closed default is reported to the console as an alert, and an operator-signed break-glass marker can lift it to recover a locked-out machine.
4. Open or closed, chosen per surface by the administrator
The coding-agent hook, the model proxy, the MCP gateway and the Inference hooks server each have a fail mode. It is read from the root-owned machine configuration first, then the signed policy; user-writable state is never read. Each surface has its own default, and the hook’s is open: a call it could not evaluate proceeds and is recorded as unevaluated. Set to closed, that call is denied and a content-free FAIL_CLOSED alert is raised. On the hook only the pre-tool check can fail closed; other events fail open, so a fault never blocks a prompt or keeps a session from stopping.
5. A bounded outbox, delivered when the console answers
An alert the coding-agent hook cannot deliver waits in the alert outbox on the device, and is retried and sent once the console answers again. An entry leaves the outbox only when the console acknowledges it, and the tool call never waits on the network for any of this. The outbox holds up to 5,000 alerts, 4 MiB, 16 KiB per alert, for 30 days. When it is full, the oldest are dropped down to 90% of each bound. Every drop is counted and reported to the console as an alert of its own, with the sequence numbers of what was dropped, so a gap has an explanation. On disk the queue is content-free. A device that never reaches its console can export its queued alerts to a file with moorai-outbox export and hand them over.
An alert counts as evidence once it reaches the console, and your SIEM when the console streams to one.
A short scorecard
| Question | A good answer | A red flag |
|---|---|---|
| Where is each call decided? | On the device, with no network needed | Only in a gateway or proxy across the network |
| Which policy while offline? | A cached copy, signature checked before use | Any file in the right place is trusted |
| Nothing verifies? | A default the administrator chose and can state | No one can say |
| The product cannot decide? | Open or closed per surface, set by the administrator, with an alert on refusal | One fixed answer, or a setting the agent’s user can change |
| Alerts during the outage? | Queued with stated bounds, drops counted and reported | Lost, or “sent later” with no bound |
The Management Server is free to self-host with no user limit; the hosted console is a free trial, then contact us.
Sources
- MoorAI. MoorAI on GitHub, agent README sections “Air-gapped deployment”, “Fail open or fail closed: the administrator decides” and “Store-and-forward alerts”.
See also: What’s new in MoorAI: fail mode and living off the AI and Local LLMs and AI agents in air-gapped OT.