Runtime lifecycle and health
Console-managed enforcement owns two background responsibilities:
- configuration refresh;
- durable audit delivery.
Close them explicitly during application shutdown.
For a direct integration, use the runtime as a context manager or close it explicitly:
from actionrail import ActionRuntime
with ActionRuntime(agent_id=agent_id, api_key=agent_key) as runtime:
run_application(runtime)
# For an application health endpoint:
status = runtime.health
runtime.flush(timeout=5) and runtime.close(timeout=7) are the direct API
equivalents of the wrapped-agent helpers below.
Normal shutdown
from actionrail import close_reporting
try:
run_application(agent)
finally:
clean = close_reporting(agent, timeout=7)
if not clean:
logger.warning("ActionRail shutdown left durable events pending")
close_reporting() stops configuration refresh, waits for queued reports until the deadline, and stops the reporter worker. A False result does not mean events were discarded. Undelivered rows remain in the local SQLite outbox and resume on the next process start for the same endpoint and agent.
ActionRail also registers process-exit handlers, but an explicit shutdown hook gives the application a bounded deadline and a result it can monitor.
Flush without closing
Use flush_reporting() when a job or test must wait for current reports while leaving the wrapped agent active:
from actionrail import flush_reporting
if not flush_reporting(agent, timeout=5):
raise RuntimeError("ActionRail reports are still pending")
Do not call flush_reporting() on every tool call. Reporting is intentionally batched in the background.
Runtime health
Expose get_runtime_health() through the application’s existing health or diagnostics endpoint:
from actionrail import get_runtime_health
def actionrail_health():
return get_runtime_health(agent)
Representative managed-mode response:
{
"status": "healthy",
"configuration": {
"status": "healthy",
"version": "…",
"monitor": false,
"source": "control_plane",
"control_plane_reachable": true,
"stale_for_seconds": 4.2,
"max_staleness_seconds": 86400,
"enforcement_expired": false,
"last_error": null
},
"reporting": {
"status": "healthy",
"pending_events": 0,
"delivered_events": 18,
"failed_delivery_cycles": 0,
"capacity": 1000,
"last_error": null
}
}
Top-level status is degraded if configuration refresh or audit delivery is degraded. Local configuration without reporting returns inactive for components that are not attached.
Alert on at least:
configuration.enforcement_expired == true;- sustained
configuration.control_plane_reachable == false; - sustained growth in
reporting.pending_events; - any persistent
reporting.last_error; close_reporting()returningFalseduring normal shutdown.
SDK state directory
Configuration snapshots and audit outboxes live under ~/.actionrail/sdk by default. Override the location through either interface:
export ACTIONRAIL_SDK_STATE_DIR=/var/lib/my-agent/actionrail
agent = enforce(
agent,
agent_id=agent_id,
api_key=agent_key,
state_dir="/var/lib/my-agent/actionrail",
)
The directory must be writable by the agent process and persistent across restarts. Do not place it on an ephemeral filesystem if audit recovery or cached startup is required.
The snapshot and outbox do not store the agent key. Source configuration should contain environment references rather than credential values.