@glideco/anomaly
v0.1.1
Published
Heuristic anomaly detector + storm suppression for Glide agent banking. OSS reference impl per OSS plan §M4 — deterministic, explainable signals; no classifier, no ML.
Maintainers
Readme
@glideco/anomaly
Heuristic anomaly detector + storm suppression for Glide agent banking. OSS reference impl per the Glide OSS plan §M4: deterministic, explainable signals; no classifier, no ML; every heuristic is a pure function over a facts snapshot the operator passes in.
Why no ML?
Per the OSS plan §"Critical architectural commitments": "Anomaly signals are heuristics, not a classifier." The signals are INPUTS to UI decision aids; the policy engine has the only hard veto. Heuristics are explainable, version-controllable, testable in isolation, and don't drift.
Usage
import {
StormSuppressor,
newRecipientHeuristic,
makeAmountDeviationHeuristic,
makeVelocityHeuristic,
} from '@glideco/anomaly';
const suppressor = new StormSuppressor();
const heuristics = [
newRecipientHeuristic,
makeAmountDeviationHeuristic({ warnRatio: 3, criticalRatio: 10 }),
makeVelocityHeuristic(),
];
// Operator queries DB for facts, then runs heuristics in parallel.
const facts = await fetchFactsFromDb(proposal);
const signals = (
await Promise.all(
heuristics.map((h) => h({ agentId: 'agent_x', now: Date.now(), facts }))
)
).flat();
// Decide which signals to push to the user; overflow goes to in-app feed.
for (const signal of signals) {
const decision = suppressor.shouldPush(signal, 'agent_x');
if (decision.pass) {
await sendPush(signal);
} else {
await appendToInAppFeed(signal);
}
}Signals
Each heuristic returns zero or more AnomalySignal objects:
interface AnomalySignal {
kind: string; // stable identifier (e.g. 'new-recipient')
severity: 'info' | 'notice' | 'warn' | 'critical';
message: string; // human-readable summary
details: Record<string, unknown>; // free-form payload for UI
timestamp: number; // UTC ms
}Built-in heuristics
| Heuristic | Default severity | What it catches |
| ------------------------------ | ------------------------------- | ------------------------------------ |
| newRecipientHeuristic | notice | First payment to a counterparty |
| makeAmountDeviationHeuristic | warn at 3×, critical at 10× | Amounts well above baseline median |
| makeVelocityHeuristic | warn at 2×, critical at 5× | Burst of tool calls |
| allowlistBypassHeuristic | critical | Attempt to pay outside the allowlist |
| timeWindowHeuristic | warn | Transactions outside business hours |
Storm suppression
const suppressor = new StormSuppressor({
maxPerWindow: 1, // max signals per (kind, agentId) per windowMs
windowMs: 60 * 60 * 1000, // 1 hour
});
const decision = suppressor.shouldPush(signal, 'agent_x');
// → { pass: true } | { pass: false, reason: 'storm-suppressed', overflowCount: N }License
MIT.
