Thread-safe
A per-instance lock means concurrent multi-episode monitoring stays correct under load.
SNAGLINE watches your agent's execution stream and flags loops, error cascades, latency drift and goal drift in real time. Zero required dependencies. It can never crash or stall the agent it monitors.
A thin adapter normalises your agent's events into one canonical schema. The monitor runs deterministic detectors on every step. Alerts go to sinks. Nothing calls an LLM, nothing reads your content, nothing blocks.
Raw Python loop, LangChain callback, LangGraph stream, AutoGen, CrewAI, or an HTTP sidecar. Framework-specific code stays quarantined inside adapter modules, so the core never learns about your stack.
Every registered detector sees every event. O(1) amortised per step, no network calls, no LLM calls, no embeddings. Detectors reason over hashes, counts and timings only.
When a detector fires, the risk fans out to every registered sink — console, webhook, Slack, PagerDuty, or your own. Only risk fields travel; never prompts, never responses.
Detector exceptions are caught and logged. Sink exceptions are caught and logged. There is no code path where SNAGLINE can raise into your agent or hold its thread. The guarantee is structural, not aspirational.
Catches retry storms and stuck agents. Keeps a sliding window of action signatures; if the same signature repeats N times inside W steps, it fires.
Catches both fast cascades and slow-burn degradation. Two independent modes: N consecutive errors, or N errors inside a recent window.
Catches sustained performance regression rather than single slow calls. Per-tool running statistics, a frozen healthy baseline, and a cumulative-sum test. A warm-up period suppresses false positives.
Compares the live run against a persisted healthy baseline profile and flags rising error rates, latency several sigma past the healthy mean, and tools that never appeared in the baseline at all. Dependency-free; a no-op until you supply a baseline.
Combines the base detectors into one stronger signal. The default combiner is a transparent noisy-OR over their scores, so confidence rises when independent detectors agree. Slot in a fitted model via one callable when you want to.
Sensible defaults out of the box. Every threshold, window size and sensitivity parameter is a constructor argument on one dataclass — no config files, no environment variables, no hidden state.
One call gives you loop, error-cascade and latency detectors with a console sink attached.
from snagline import Monitor monitor = Monitor.default() # That's it. Three detectors running, # console sink attached, zero deps, # ~2 microseconds of overhead per step.
Override only what matters. Everything else keeps its default.
from snagline import Monitor, Config config = Config( loop_window_size=20, loop_repeat_threshold=5, cusum_k=0.3, cusum_h=3.0, ) monitor = Monitor.default(config=config)
A per-instance lock means concurrent multi-episode monitoring stays correct under load.
Detectors see hashes, timings, counts and booleans. Prompt and response content never enters the monitor, so it cannot leak from it.
Monitor a live agent, or replay an exported trajectory file through the identical schema and
detectors with snagline replay.
Six adapters and three zero-touch auto-instrumenters ship in the box. Anything that speaks HTTP can post events without an adapter at all — or write your own in under fifty lines against a documented protocol.
snagline.autoAny runtime that speaks HTTP can POST events to the built-in server.
snagline serve --port 8787
Pipe hook payloads straight through the CLI. Always exits 0, so it can never break the caller.
Tail a JSONL file, for frameworks that can only append to disk.
Seven sinks ship in the core, and the Slack and PagerDuty ones need no extra dependency — they are stdlib all the way down. Compose them: wrap a noisy sink in dedup, then in batching, and the semantics still hold.
One JSON line per risk to stderr. The zero-config default.
POST the risk payload to any URL. Credentials in the URL are redacted from logs.
Formatted incoming-webhook messages. Stdlib only, no extra install.
Events API v2 alerts, with score mapped onto PagerDuty severity.
Cooldown wrapper that collapses repeat alerts for the same trigger.
Async, rate-limited dispatch on a background worker so slow endpoints never touch your agent.
A sink is one method: emit(risk) -> None. Implement the protocol, register it, and
the monitor's fail-open contract covers your code too — if it raises, the exception is caught
and logged, and the agent keeps running.
Every claim on this page is reproducible from the repository. The proof scripts are the primary artefact; the prose is secondary.
Driven across chaos scenarios with a real create_agent. The callback handler captured tool calls, LLM calls, chain errors and agent decisions, firing all three tier-1 detectors as expected.
Five PostToolUseFailure payloads posted to the HTTP sidecar produced both a loop and an error-cascade FailureRisk, with HookTracker correctly pairing Pre and Post events.
Hand-built trajectory files act as ground truth. Loop, cascade and latency detectors fire on the failing runs, and healthy runs produce zero false positives.
200,000 synthetic steps measured end to end. Median 2.08µs per step, p99 2.31µs — comfortably inside the sub-100-microsecond design target.
Two phases landed deterministic, dependency-free implementations with a heavier
optional upgrade still open: an ESN model behind snagline[ml] and sentence embeddings
behind snagline[drift].
Zero required dependencies. Python 3.10+. MIT licensed.