Open source / Zero dependencies / 2.08µs per step

Catch agent failures before they cascade.

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.

Get started →

snagline watch · ep-001

live

latency stream · tool:search

nominal
observedfrozen baselinecusum alarm
mean last cusum
0.00µs
Median per step
0
Required dependencies
0
Detectors built in
0
Tests in the suite
01 — How it works

Monitoring that stays out of your way

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.

STEP 01

Adapter normalises events

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.

with watch(monitor, "ep-1") as step: step("tool_call", tool_name="search", latency_ms=120)
STEP 02

Monitor runs detectors

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.

2.08µs median · 2.31µs p99
STEP 03

FailureRisk dispatched to sinks

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.

{"episode_id":"ep-1", "score":0.5, "trigger":"loop", "detail":"action repeated 3x in last 3 steps"}
STEP 04

Fail-open by construction

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.

Hard fail-open guarantee
02 — Detectors

Five failure modes

01 / 05loop

Loop detector

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.

Sliding window
+ SHA-256 action signatures
02 / 05cascade

Error cascade detector

Catches both fast cascades and slow-burn degradation. Two independent modes: N consecutive errors, or N errors inside a recent window.

Consecutive counter
+ windowed counter
03 / 05latency

Latency anomaly detector

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.

Welford mean/variance
+ Page CUSUM + frozen baseline
04 / 05goal drift

Goal-drift detector

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.

Structural baseline comparison
optional embedder for semantic drift
05 / 05ensemble

ML ensemble orchestrator

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.

noisy-OR: 1 − ∏(1 − sᵢ)
pluggable model hook
03 — Configuration

Zero config. Total control.

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.

monitor.pypython

Works today

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.
custom_config.pypython

Tune when you need to

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)
=

Thread-safe

A per-instance lock means concurrent multi-episode monitoring stays correct under load.

#

No content retention

Detectors see hashes, timings, counts and booleans. Prompt and response content never enters the monitor, so it cannot leak from it.

>

Streaming and batch

Monitor a live agent, or replay an exported trajectory file through the identical schema and detectors with snagline replay.

04 — Integrations

Works with any agent runtime

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.

Adapters
01 Raw Python Context manager and decorator for any hand-rolled agent loop. stdlib only
02 LangChain Callback handler covering tool calls, LLM calls, chain errors and agent decisions. snagline[langchain]
03 LangGraph Stream wrapper that reads node transitions as steps. snagline[langgraph]
04 Claude Code Native hook mapping, with Pre/Post tool-use pairing via HookTracker. hooks bridge
05 AutoGen Event translation for AgentChat multi-agent conversations. snagline[autogen]
06 CrewAI Crew and task lifecycle mapped onto the canonical step schema. snagline[crewai]
Auto-instrument · snagline.auto
07OpenAI SDK Patch the client once; every completion becomes a monitored step. snagline[openai]
08Anthropic SDK Same one-line attach for Claude message calls. snagline[anthropic]
09LangChain (auto) Registers the callback handler globally, no per-chain wiring. snagline[langchain]
{}

HTTP sidecar

Any runtime that speaks HTTP can POST events to the built-in server. snagline serve --port 8787

|

Command bridge

Pipe hook payloads straight through the CLI. Always exits 0, so it can never break the caller.

~

File bridge

Tail a JSONL file, for frameworks that can only append to disk.

05 — Sinks

Route risk anywhere

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.

01

ConsoleSink

One JSON line per risk to stderr. The zero-config default.

02

WebhookSink

POST the risk payload to any URL. Credentials in the URL are redacted from logs.

03

SlackSink

Formatted incoming-webhook messages. Stdlib only, no extra install.

04

PagerDutySink

Events API v2 alerts, with score mapped onto PagerDuty severity.

05

DedupSink

Cooldown wrapper that collapses repeat alerts for the same trigger.

06

BatchingSink

Async, rate-limited dispatch on a background worker so slow endpoints never touch your agent.

07

Your own sink

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.

06 — Evidence

Verified, not asserted

Every claim on this page is reproducible from the repository. The proof scripts are the primary artefact; the prose is secondary.

LangChain 1.x
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.
tests/test_integration.py
Claude Code hooks
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.
tests/test_claude_code.py
Fixture trajectories
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.
tests/fixtures/trajectories/
Overhead benchmark
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.
snagline bench · 2026-08-19
07 — Roadmap

Nineteen phases, all shipped

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].

01Core schema — StepEvent, FailureRisk, Config
02Monitor orchestrator with fail-open guarantee
03Loop detector
04Error cascade detector
05Console sink + raw adapter
06Latency anomaly (CUSUM) detector
07Overhead benchmark — snagline bench
08LangChain adapter
09Webhook sink
10HTTP sidecar — snagline serve
11LangGraph adapter
12Claude Code hooks bridge
13Framework bridge docs
14Offline replay CLI — snagline replay
15Dedup / cooldown — DedupSink
16ML ensemble detectorESN pending
17Goal-drift detectorembeddings pending
18AutoGen / CrewAI adapters
19Slack + PagerDuty sinks

Start monitoring in thirty seconds

Zero required dependencies. Python 3.10+. MIT licensed.

View on GitHub ↗