Behavioral Drift Detection

ARX continuously monitors agent behavior at runtime and compares it against the declared intent manifest (INV-003). When an agent performs an action outside its declared scope, ARX records a drift event and takes an automated response proportional to the severity. Drift detection operates independently of the policy engine and provides a second layer of behavioral governance.

How Drift Detection Works

The DriftDetector is invoked by the intercept layer before policy evaluation. On every connector call, the detector:

  1. Retrieves the agent's declared_intent from the agents table.
  2. Compares the target connector against permitted_systems.
  3. Compares the operation against permitted_actions (with wildcard support).
  4. If either check fails, records a drift event and determines the automated response.

If the agent has no declared intent manifest, drift detection is skipped entirely. The system does not treat the absence of a manifest as a violation.

Frequency-based drift detection is handled separately by DriftDetector.check_frequency(), which counts the agent's audit log entries in the current clock hour and compares against the max_frequency.per_hour limit in the manifest.

Drift Types

Drift Type Trigger Default Severity
unauthorized_system Agent called a connector not listed in permitted_systems high
unauthorized_action Agent performed an operation not matching any entry in permitted_actions high
frequency_exceeded Agent exceeded max_frequency.per_hour limit medium
unauthorized_data_type Agent accessed a data type not listed in permitted_data_types Varies

Action Matching

The detector uses a two-tier matching strategy for permitted_actions:

  1. Exact match: The operation string is checked against each entry in the list.
  2. Prefix wildcard: If no exact match is found, the operation's prefix (the segment before :) is extracted and prefix:* is checked against the list.

For example, if permitted_actions contains detection:* and the operation is detection:update, the action passes. If the operation is host:isolate and neither host:isolate nor host:* is in the list, drift is detected.

Drift Event Schema

Each drift event is stored in the drift_events table:

Field Type Description
org_id UUID Organization ID.
agent_id UUID Agent that drifted.
drift_type string One of unauthorized_system, unauthorized_action, frequency_exceeded, unauthorized_data_type.
detected_behavior object What the agent actually did (e.g., {"connector": "okta", "operation": "user:delete"}).
declared_intent_snapshot object Full copy of the agent's declared intent at the time of detection.
severity string One of low, medium, high, critical.
response_taken string Automated action taken: alert, throttle, or suspend.

The declared_intent_snapshot captures the manifest as it existed when drift was detected, ensuring that subsequent manifest updates do not obscure what the agent was authorized to do at the time of the incident.

Automated Responses

The response is determined by the drift event's severity:

Severity Response Effect
low alert Drift event is recorded and notifications are sent. Agent continues operating.
medium throttle Drift event is recorded. Agent's request rate is reduced.
high suspend Agent's status is set to suspended in the agents table. All subsequent connector calls are blocked.
critical suspend Same as high. Agent is immediately suspended.

When an agent is suspended due to drift, the intercept layer checks the drift response before policy evaluation. If the response is suspend, the call is denied with a risk score of 100 and an audit entry with status blocked and metadata indicating behavioral_drift as the reason. A drift.detected webhook is also fired.

Suspended agents must be manually reactivated by an administrator after investigation.

Integration with the Intercept Layer

The intercept flow executes drift detection as a pre-check:

  1. intercept_connector_call() invokes DriftDetector.check_drift().
  2. If drift is detected and the response is suspend, the call is immediately denied. The policy engine is never invoked.
  3. If drift is detected but the response is alert or throttle, the drift event is recorded but the call proceeds to policy evaluation.
  4. If no drift is detected, the call proceeds normally.

This ordering ensures that suspended agents are blocked at the earliest possible point, before any policy evaluation or risk scoring occurs.

Monitoring Drift

REST API

Query drift events through the standard API:

GET /v1/drift-events?agent_id={agent_id}
GET /v1/drift-events?drift_type=unauthorized_system
GET /v1/drift-events?severity=high

Registry Dashboard

The ARX registry dashboard provides a dedicated drift monitoring view for CISOs and security leads. The dashboard displays:

Webhooks

Organizations can subscribe to drift.detected webhook events to integrate drift alerts into existing SIEM, SOAR, or incident management workflows. The webhook payload includes the agent ID, connector, operation, drift type, severity, and response taken.

Periodic Drift Checks

In addition to real-time per-call checks, ARX supports periodic drift analysis through a Supabase edge function. This function runs on a configurable schedule and performs frequency-based drift detection across all active agents in the organization.

The periodic check calls DriftDetector.check_frequency() for each agent with a declared max_frequency limit. This catches frequency violations that might not be detected on individual calls if the agent is operating across multiple concurrent sessions.

Relationship to Policy Rules

Drift detection and policy evaluation are independent systems that reinforce each other:

An action can pass policy evaluation but still trigger a drift event if it falls outside the declared intent. Conversely, an action within the declared intent can still be denied by a policy rule. Both systems must permit an action for it to proceed without intervention.