Skip to main content
The package is installed as loopguard-runtime and imported as loopguard. Start with the callback handler for tool events or the wrapper for supported LangGraph stream updates. This reference tracks the source checkout. The published 0.2.1 wheel has the core entry points, but lacks the checkout’s additional serialized decision display fields and Gemini provider support. See release scope.

LoopGuardCallbackHandler

Constructor budget values should be positive integers. Config-file loading validates that constraint; direct constructors do not apply the same validation. Use handler.raise_error = True to let LangChain propagate callback exceptions. This is inherited framework behavior, not a LoopGuard constructor parameter. See integration for surrounding tool-error handling.

Configuration and lifecycle

from_config(path, interrupt_on_fatal=True) reads the live settings. reset() clears detector state, messages, events, signals, decisions, and alerts before a new run. Prefer a fresh handler per run when running agents concurrently.

Read the result

report()["interrupted"] is the policy’s stop flag. It can be true even when observe-only mode or framework exception handling allowed execution to continue.

LoopGuardInterrupt

This RuntimeError subclass carries decision and alert attributes, which can be None. A policy stop normally provides a GuardDecision; its stop_reason supplies the message. Catch it outside the run and retain the handler’s report.

LoopGuard stream wrapper

LoopGuard.from_config(path, detectors=None, recursion_limit=50) loads live settings. Passing a detector list replaces the configured/default list. guard.stream(agent, initial=None, recursion_limit=None) yields dictionaries. An explicit recursion limit for stream() overrides the instance value. The wrapper stops consuming updates after STOP. It catches runtime exceptions, emits error, and still emits final metrics and done. Inspect errors separately from the interruption flag. initial=None uses the scripted weather-demo input; pass your own initial state for other agents. The lower-level exported stream_run(agent, detectors, initial=None, recursion_limit=50) uses the same message contract.

Report data

Decision actions serialize as lowercase strings: continue, warn, replan, pause, and stop. stop_reason is None for other actions. repeat_rate is the fraction of tool calls beyond the first instance of each distinct signature, not a measure of model quality or wasted tokens.

Saved-trace functions

These functions live in loopguard.ingest rather than the package root:
analyze_trace(trace, detectors=None) returns a TraceReport. analyze_file(path, detectors=None) returns a list of reports. Supply a custom detector list to change offline behavior or add a semantic detector. The functions replay the whole trace and do not execute its tools. TraceReport exposes run_id, steps, events, tool_calls, decisions, alerts, status, looped, and final_decision. looped means any STOP, including failures and budgets, not only a literal loop.

Lower-level public surfaces

Use these when writing an adapter or experimenting with policy. They are not required for normal callback integration. The default callback/wrapper constructors do not expose a custom policy parameter. Use a lower-level Monitor when you need to inject a PolicyEngine. Detector classes are imported from loopguard.detectors; embedders from loopguard.embeddings. See detection and the configuration reference for behavior and defaults.

Evaluation helper

loopguard.evals.convergence_score(step_counts) returns the average ratio of the shortest positive supplied count to each positive count. It ignores nonpositive counts and returns 0.0 when no positive counts remain. This function accepts step counts, not traces or success labels. It does not verify outcomes or measure cost. See agent trajectories and convergence for a runnable example and how to select comparable runs.