Guardian is Regent’s ML layer. It watches every agent’s audit stream in real time and produces a risk score between 0 (normal) and 1 (highly anomalous). When the score crosses a threshold, an alert is created.

Why ML, not rules

Mandate enforcement (per-tx limits, daily caps) is rule-based and deterministic — it catches known violations. Guardian catches the unknown ones: agents whose individual actions are all within limits but whose pattern is suspicious.

Examples Guardian catches that mandates miss:

  • An agent suddenly making many tiny trades after weeks of normal pacing
  • An agent triggering many rejections in a short window (probing limits)
  • An agent active at an unusual time of day for its profile
  • An agent whose action types shift dramatically (e.g., started buying, now only selling)

How scoring works

Every audit event triggers a fresh score for that agent:

The model is an Isolation Forest — an unsupervised algorithm that scores how easily a point can be isolated from the rest of a learned distribution. Easily-isolated → anomalous.

The six features

FeatureWhat it measuresWhat an anomaly looks like
amount_zscoreHow far this event’s amount is from the agent’s historical meanA $1,000 trade for an agent that usually does $50
error_rate_1hFraction of recent events that were rejectionsMany rejections in a short window = probing or runaway
event_rate_1hNumber of events per second over the last hourBurst activity vs steady cadence
event_rate_24hSame, scaled to 24 hoursDetects level shifts
hour_of_day_sinTime of day (cyclical encoding)Activity at unusual hours for this agent
unique_event_typesDiversity of action typesAgent suddenly emitting types it never has before

These are computed on Redis rolling windows so scoring stays sub-millisecond.

SHAP explanations

For every score, Guardian computes SHAP factors — per-feature contributions to the risk score. This makes the model auditable and regulator-friendly:

{
  "agent_id": "agent_b1c59d23...",
  "score": 0.587,
  "features": {
    "amount_zscore": 0.0,
    "error_rate_1h": 0.45,
    "event_rate_1h": 0.008,
    "event_rate_24h": 0.001,
    "hour_of_day_sin": 0.71,
    "unique_event_types": 0.18
  },
  "shap_factors": [
    {"feature": "error_rate_1h",     "value": -3.10},
    {"feature": "event_rate_1h",     "value": -0.65},
    {"feature": "event_rate_24h",    "value": -0.44},
    {"feature": "unique_event_types","value":  0.28},
    {"feature": "amount_zscore",     "value": -0.18},
    {"feature": "hour_of_day_sin",   "value": -0.07}
  ]
}

Negative SHAP values indicate features that pushed the score toward anomalous. In the example above, error_rate_1h is the dominant signal — the agent has been rejected unusually often.

This satisfies the EU AI Act’s explainability requirements: every alert can be defended with a per-feature attribution, not “the model said so.”

Alert types

TypeTriggered whenDefault threshold
thresholdScore >= alert threshold0.5 (configurable per-environment)
driftScore delta from previous score >= drift threshold0.2

Alerts are stored with status open and shown on the dashboard. Operators acknowledge or resolve them via the API.

Soft dependency from authorize

When api-payment processes an /authorize call, it asks Guardian for the latest score as a soft dependency: if Guardian is unavailable, the authorize still proceeds. If Guardian returns a score above the hard reject threshold, the authorize is denied with RISK_SCORE_TOO_HIGH.

This means Guardian can act as a second layer of denial beyond mandate limits — agents whose ML risk has spiked are blocked even if their individual action is within the rulebook.