--- title: Anomaly detection description: Spotting spend that does not look like your normal pattern — how the baseline is built, what token velocity measures, and why a fixed threshold is wrong. keywords: LLM spend anomaly, agent cost spike detection, token velocity, unusual agent spend eyebrow: Cost & usage --- # Anomaly detection A fixed threshold cannot work across fleets. A $40 session is unremarkable on one machine and an emergency on another, and any number you pick is wrong for somebody. So anomaly detection compares against **your own history**. ## What is measured **Session cost** against the distribution of your recent sessions on the same runtime. A session several standard deviations above your normal is flagged. **Token velocity** — tokens per unit time. This catches a runaway *before* the total is large, which is the whole point. A session burning tokens ten times faster than your normal is interesting after two minutes, not after it has cost $50. ```bash curl -s localhost:8900/api/token-velocity | jq curl -s localhost:8900/api/usage | jq '.anomalies' ``` **Forward progress** — cost accumulating without work being produced. A session that spends steadily and changes nothing is a different shape from one that spends steadily and ships. ```bash curl -s localhost:8900/api/forward-progress | jq ``` ## The baseline Same machinery as the Guard [behavioural detectors](/docs/guard/detectors/): - A minimum sample before a baseline is used at all, so three sessions cannot define normal. - Learned values clamped to a band around the shipped default, so a period where everything was expensive cannot teach the system that expensive is normal. - Per-cohort, so a runtime you use for large refactors does not make your cheap runtime look anomalous by comparison. → [Thresholds and baselines](/docs/guard/thresholds/) ## Anomalies versus Guard They overlap and they are not the same: | | Cost anomaly | Guard detector | |---|---|---| | Looks at | Spend rate and totals | Tool-stream structure | | Catches | Unusual spend, whatever the cause | Loops, no progress, repeated failures | | Misses | A cheap session going nowhere | An expensive session doing real work | A session can be a cost anomaly and perfectly healthy — a genuinely large task. A session can be stuck and cheap. Watching only one leaves a real gap. ## Acting on it An anomaly is a signal, not a verdict. What to do with one: 1. **Open the session.** The transcript almost always explains it in the first screen. 2. **Check the detectors.** If Guard also flagged it, it is very likely a loop. 3. **Check cache behaviour.** A sudden cost rise with no change in work is often a cache that stopped hitting — a prompt prefix changed, and every turn is now paying full input price. → [Reducing spend](/docs/cost/optimization/) 4. **Check the model.** A configuration change that moved a routine task onto a frontier model looks exactly like this. ## Alerting on them Wire an alert on the anomaly signal rather than on a fixed dollar amount: ```bash curl -s localhost:8900/api/alerts/rules -X POST \ -H 'content-type: application/json' \ -d '{"name":"spend anomaly","metric":"anomaly","threshold":1,"action":"webhook"}' ``` → [Alerts](/docs/dashboard/alerts/) ## Tier `anomaly_detection` is a Pro feature.