Runtime availability and failure behavior
ActionRail keeps ordinary enforcement in the agent process. The Console is a control plane for configuration, review, and visibility; it is not in the hot path for local policy or grounding checks.
Availability contract
| Condition | Enforcement | Reporting | Human review |
|---|---|---|---|
| Console is healthy | Uses the current validated snapshot. | Batched delivery. | Available. |
| Console stops after initialization | Continues with the active snapshot until its staleness limit expires. | Persists locally and retries. | Fails closed. |
| Process starts while Console is unavailable | Uses a valid, sufficiently fresh cache. | Resumes the durable outbox. | Fails closed. |
| No cache exists on an offline first startup | enforce() raises; it does not start unprotected. | Not started. | Not started. |
| Cached configuration exceeds its staleness limit | Enforcing tool calls fail closed. | Continues to persist report-safe metadata. | Fails closed. |
| A local Source is unavailable | Uses the check’s on_error; default is block. | Records Source health locally first. | An on_error: hold can request review only if Console is reachable. |
Local config= enforcement without agent_id= has no Console dependency. instrument() never blocks the underlying agent; during an outage its reporter persists observation metadata for later delivery.
Configuration lifecycle
enforce(agent_id=...) fetches rules and non-secret Source metadata during initialization. The SDK validates policy syntax and Source construction before activating a snapshot. It stores the result under ~/.actionrail/sdk/config/ by default with owner-only file permissions and without the agent key.
Remote configurations have a deterministic content version derived from rules, monitor mode, and enforcement-relevant Source fields. Every 30 seconds by default, the SDK fetches a candidate in the background.
- An unchanged version confirms the last-known-good configuration.
- A changed version is fully built and validated before activation.
- Activation swaps one complete reference, so concurrent calls see the old or new snapshot, never a partial merge.
- A failed candidate leaves the previous snapshot active and marks health degraded.
The default max_config_staleness is 86,400 seconds. Once the last successful validation is older than that limit, enforcing-mode tools return ACTIONRAIL_CONFIG_STALE without executing. A successful refresh clears the condition, including when it confirms the same configuration version.
agent = enforce(
agent,
agent_id=agent_id,
api_key=agent_key,
endpoint=console_url,
refresh_interval=30,
max_config_staleness=86_400,
)
Set refresh_interval=0 only when the host application manages process restarts for configuration rollout. Set max_config_staleness=None only after explicitly accepting that cached configuration may remain authoritative indefinitely.
Startup states
Do not catch the startup exception and continue with an unwrapped agent unless that fallback is an explicit, separately reviewed application mode. Otherwise a control-plane outage can accidentally become an enforcement bypass.
Health integration
Expose get_runtime_health(agent) from the host application’s health or metrics endpoint. The configuration section includes:
- active content version and monitor mode;
control_planeorcachesource;- last successful validation and latest failure;
- current staleness and configured maximum;
- whether enforcement authority has expired.
Treat overall degraded as alertable. It does not necessarily mean tool calls are blocked yet: the staleness window deliberately separates a brief control-plane interruption from expired enforcement authority.
See Runtime lifecycle for the response schema and shutdown integration.