Skip to content

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.

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.

DetectorFires whenSeverity
loopFive or more payments to the same payee for the same amount within ten minutes, at a steady interval. A retry loop.High
velocity_spikePayments in the last hour exceed three times the usual peak, or the usual maximum plus five.Medium
amount_outlierAn amount far above the agent’s usual range and over $50.Medium
new_payeeThe 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_driftThe agent starts using a category or rail it has not used in 30 days, three or more times in a day.Medium
mandate_breachA payment fell outside the owner’s mandate, or a closed mandate’s values differ from the event.High
evidence_invalidA cryptographic check on the payment’s evidence failed.High
sanctions_hitA payee matched a sanctions list. See screening.High
attribution_gapMore 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.

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:

ActionResult
acknowledgeSomeone is looking at it.
dismissClosed as not a problem. A reason is required.
escalateMoved into a case.
reopenBack to open.
commentA 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.

Terminal window
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.

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.