Skip to main content

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() returning False during 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.