Detectors and alerts
HalvorAI watches how each agent behaves and raises an alert when something departs from its own history. Detection runs in the background after each event. It reports and never blocks a payment.
The detectors are deterministic rules with documented thresholds, not a model. Every alert comes with a plain-language explanation, so an analyst never sees a bare score.
Baselines
Section titled “Baselines”Each agent gets a baseline from the last 30 days of its settled and authorized events: payments per hour (median, 95th percentile, maximum) and by hour of day, the typical amount and its spread, the mix of rails, the set of payees and categories, the usual time between payments, and the failure rate. An agent with fewer than 20 events is learning: only the rule-based detectors fire for it until it has history.
Baselines are recomputed nightly and updated after new events arrive.
The detectors
Section titled “The detectors”| Detector | Fires when | Severity |
|---|---|---|
loop | Five or more payments to the same payee for the same amount within ten minutes, at a steady interval. A retry loop. | High |
velocity_spike | Payments in the last hour exceed three times the usual peak, or the usual maximum plus five. | Medium |
amount_outlier | An amount far above the agent’s usual range and over $50. | Medium |
new_payee | The agent pays someone it has never paid. High when the payee is new to the whole organization and the amount is large. | Low or high |
scope_drift | The agent starts using a category or rail it has not used in 30 days, three or more times in a day. | Medium |
mandate_breach | A payment fell outside the owner’s mandate, or a closed mandate’s values differ from the event. | High |
evidence_invalid | A cryptographic check on the payment’s evidence failed. | High |
sanctions_hit | A payee matched a sanctions list. See screening. | High |
attribution_gap | More than 10% of a day’s events had no agent or no instruction. Daily digest only. | Low |
Prompt injection and a hijacked agent usually show as a combination: a new payee, an unusual amount, an odd hour. When two medium findings hit the same agent within an hour, HalvorAI raises one high composite alert instead of several.
An example of what an alert says:
agt_07 paid Example Market Data $0.01 forty times in 6 minutes at a steady interval. This looks like a retry loop.
Alert lifecycle
Section titled “Alert lifecycle”An alert has one open record per agent, detector and time window (an hour for loop and velocity_spike, a day for the
rest). Later matching events are added to the same alert instead of creating a new one, so a burst is one alert.
An alert’s state follows its latest action:
| Action | Result |
|---|---|
acknowledge | Someone is looking at it. |
dismiss | Closed as not a problem. A reason is required. |
escalate | Moved into a case. |
reopen | Back to open. |
comment | A note, with no state change. |
Dismissal reasons are chosen from a fixed list (expected behaviour, test traffic, duplicate, other) so the overview can show a false-positive rate for each detector. Every action is recorded with who did it and when.
curl "https://api.sandbox.halvorai.com/v1/alerts?status=open&severity=high" \ -H "Authorization: Bearer $HALVOR_API_KEY"
curl -X POST "https://api.sandbox.halvorai.com/v1/alerts/alr_01JA8X.../actions" \ -H "Authorization: Bearer $HALVOR_API_KEY" -H "Content-Type: application/json" \ -d '{ "action": "dismiss", "reason": "test traffic" }'GET /v1/alerts filters by status, severity, detector and agent_id. GET /v1/alerts/{id} returns the alert, its
events, its explanation and its action history. Keys need alerts:read to read and alerts:write to act. To be told as
soon as an alert is raised, use the alert.created webhook.
Why these numbers can be trusted
Section titled “Why these numbers can be trusted”Each detector has a model card describing its purpose, inputs, thresholds and known limits, and is tested against seeded scenarios and normal traffic with no false positives. Thresholds can be tuned per organization by an admin.