Skip to content

Open-source detector library — contributions welcome #142

Description

Overview

Sentinel ships with a set of detectors — pattern-matching rules that run against a reconstructed execution flow graph for each AI agent trace. Each detector produces an Insight: a finding with a title, plain-English explanation, and a specific recommendation.

This issue tracks the open-source detector library and is the starting point for community contributions.


How detectors work

Every detector implements the Detector ABC in services/pipeline/src/sentinel_pipeline/detectors/base.py:

```python
class Detector(ABC):
id: str # snake_case identifier, e.g. "agent_loop"
name: str # human-readable, e.g. "Agent Loop"
severity: Severity # INFO | WARNING | HIGH | CRITICAL

@abstractmethod
def evaluate(self, graph: FlowGraph, signals: Signals) -> list[Insight] | None:
    ...

```

To add a detector:

  1. Create services/pipeline/src/sentinel_pipeline/detectors/<detector_name>.py
  2. Implement the Detector ABC
  3. Register it in detectors/__init__.pyDETECTOR_REGISTRY
  4. Write two tests (in tests/unit/detectors/):
    • One fixture that must trigger the detector
    • One fixture that must not trigger it (false positive guard)

See CLAUDE.md for the full dev guide and how to run tests locally.


Detector status

These detectors operate on a single trace — no cross-trace history or content storage required.

✅ Implemented

Detector File What it catches
Agent Loop agent_loop.py Agents cycling in a loop with no exit condition — same agent 3+ times, or a structural cycle in the flow graph
Sequential Tool Calls sequential_tools.py Independent tools with no data dependency executed serially — quantifies time wasted vs. parallelising
Missing Termination Condition missing_termination_condition.py Long linear workflows (10+ LLM calls) with no max-iteration or token-budget guard — the leading cause of runaway costs
Token Cost Runaway token_cost_runaway.py Single trace exceeding token thresholds (50k input / 10k output / 100k total) — surfaces the top-consuming calls
Retry Storm retry_storm.py Excessive retries in a trace (3+ on one span or 5+ total) masking a persistent upstream failure
Latency Spike latency_spike.py LLM calls significantly slower than peers (rate limiting), oversized context (75%+ of window), or dominating total trace time
Context Cache Opportunity context_cache_opportunity.py Same large context sent to the same model on multiple calls — provider-specific caching advice included
Retrieval Without Grounding retrieval_without_grounding.py RAG flows where retrieved content doesn't reach the LLM — content-mode (Jaccard overlap) and structural-mode detection

📋 Open for contribution

Each of the following detectors operates on a single FlowGraph — no external state or database access needed. Pick one, comment below to claim it, then open a PR.

  • Cascading Failure Propagation (Reliability) — One span failure triggers 3+ downstream failures. Identify the true root cause span, not just the symptoms.
  • Unused LLM Output (Cost) — An LLM span's output is never referenced by any downstream span. The generation cost (tokens + latency) was wasted.
  • Deep Dependency Chain (Performance) — Critical path depth exceeds a threshold. Each sequential hop adds irreducible latency that parallelism can't fix.
  • Redundant Duplicate Calls (Performance) — Same tool called 2+ times with identical input in one flow, first result not cached. Duplicated latency and token spend.
  • Context Window Pressure (Cost / Quality) — Input tokens exceed 80% of the model's context window. Truncation risk, quality degradation, sharp cost increase.
  • Slow Retrieval on Critical Path (Performance) — A retrieval span is on the critical path (blocks all downstream work) and takes longer than 1 second.
  • Agent Handoff Without Context (Quality) — A handoff span carries empty or minimal context to the next agent. The receiving agent will lack the information to continue.
  • Clarification Loop (Quality) — User → agent → user → agent exchange repeats 3+ times with no observable task progress.

Contribution guidelines

  • Keep the detector self-contained — evaluate() receives only FlowGraph and Signals, both already computed
  • Avoid false positives: the "must NOT trigger" test is as important as the one that fires
  • Include evidence: dict in the Insight with the quantitative data that justified firing — this is what shows up in the UI and CLI output
  • Follow the existing detectors as style reference — agent_loop.py for multi-case detectors; sequential_tools.py for single-case

Questions? Drop them in this issue or in the relevant PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions