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:
- Create
services/pipeline/src/sentinel_pipeline/detectors/<detector_name>.py
- Implement the
Detector ABC
- Register it in
detectors/__init__.py → DETECTOR_REGISTRY
- 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.
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.
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
DetectorABC inservices/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
```
To add a detector:
services/pipeline/src/sentinel_pipeline/detectors/<detector_name>.pyDetectorABCdetectors/__init__.py→DETECTOR_REGISTRYtests/unit/detectors/):See
CLAUDE.mdfor 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
agent_loop.pysequential_tools.pymissing_termination_condition.pytoken_cost_runaway.pyretry_storm.pylatency_spike.pycontext_cache_opportunity.pyretrieval_without_grounding.py📋 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.Contribution guidelines
evaluate()receives onlyFlowGraphandSignals, both already computedevidence: dictin theInsightwith the quantitative data that justified firing — this is what shows up in the UI and CLI outputagent_loop.pyfor multi-case detectors;sequential_tools.pyfor single-caseQuestions? Drop them in this issue or in the relevant PR.