Case Study · SENTINEL

SENTINEL — Trust & Safety Triage Agent

A fully local LangGraph triage agent that routes marketplace abuse reports to policy-cited enforcement actions, with layered guardrails and a CI-regressed golden-set eval gate.

Two binary criteria in CI — routing accuracy ≥ 90% and zero ungrounded escalations before any merge.

Problem
Marketplace abuse reports needed consistent, policy-grounded enforcement decisions — without hallucinated citations or unchecked escalations.
Role
Architected the LangGraph state machine, wired policy-RAG with Chroma, enforced structural citation grounding, layered input/output guardrails, and built the CI golden-set eval gate.
Stack
Python, LangGraph, Ollama (Llama 3.1), Chroma, Instructor/Pydantic, FastAPI, LLM Guard / Llama Guard, SqliteSaver, Docker, OpenInference/Phoenix, GitHub Actions
Impact
90% routing accuracy (PASS gate) · 0 ungrounded citations across 75 cases · 0.699 mean Ragas faithfulness

SENTINEL ingests synthetic marketplace abuse reports across four categories — fraud, refund abuse, account takeover (ATO), and content violations — and routes each to a recommended action (approve / restrict / escalate / ban) grounded in retrieved policy text, cited by section ID.

Two grounding measures, deliberately separate: structural enforcement (citations must come from the retrieved set — code-enforced, 100%) and Ragas semantic faithfulness (how much of the rationale is literally supported by policy text — 0.699 mean, an honest baseline for improvement).

Context: all metrics are from live local-model runs on Ollama (Llama 3.1, temp=0). No cloud dependencies; runs offline on a single machine.

CI-gated golden-set evaluation

SENTINEL — Safety-Enforced Triage & Evaluated Layered Guardrails

Context: A marketplace platform needed automated trust-and-safety triage that routes fraud, refund abuse, ATO, and content-violation reports to policy-cited enforcement actions — without drifting on borderline cases.

Problem: Open LLMs hallucinate citations and under-escalate high-risk edge cases when unguarded. A naive RAG + LLM pipeline would produce plausible-sounding but unverifiable enforcement decisions.

What I built: A 7-node LangGraph state machine (guard_input → classify → policy_retrieve → decide → route → guard_output → human_review) wiring Chroma policy-RAG with structural citation enforcement, Instructor/Pydantic structured outputs at temp=0, LLM Guard / Llama Guard layered rails, and SqliteSaver checkpointing for human-in-the-loop interrupts on all high-risk actions.

Impact: 90.0% routing accuracy on the PASS gate run · 0 ungrounded citations across 75 live cases · 0.699 mean Ragas faithfulness. Eval also surfaced a reproducible under-escalation bias on 4 borderline cases — an actionable model-improvement signal.

Tradeoff I made: Two-layer grounding rather than one: structural enforcement guarantees zero hallucinated citations at code level; Ragas tracks rationale fidelity separately and honestly at 0.70 — not claimed as 1.0.

90%

routing accuracy (20-case gate, PASS)

Cases
18/20 correct · 2 misses (under-escalation bias)
Threshold
≥ 90% required to open gate
Run
GitHub Actions · live Ollama (Llama 3.1)

0

ungrounded citations (75 cases)

Mechanism
_enforce_grounding rejects citations outside retrieved set
Coverage
All escalate/ban actions — 75-case run
Type
Code-enforced invariant, not model promise

0.699

mean Ragas faithfulness

Median
0.75 · 8 perfect scores (1.0)
Judge
Ollama llama3.1 via ragas 0.4.3
What it measures
Semantic NLI check: rationale claims vs. retrieved policy text

Architecture: 7-node LangGraph state machine

Pipeline

guard_input — prompt-injection and PII scan (LLM Guard / Llama Guard with offline builtin fallback).

classify — Llama 3.1 via Instructor + Pydantic (Mode.JSON, 3-retry auto-repair) → Classification(category).

policy_retrieve — Chroma top-k=4, category-filtered policy chunks from 20 section-ID-keyed policy sections.

decide — Llama 3.1 + Instructor → Decision(action, rationale, citations[]) at temp=0.

route — risk-tier assignment: approve → auto-approve queue · restrict/ban → enforcement queue · escalate → human-review queue.

guard_output — structural citation check (_enforce_grounding): any citation outside the retrieved set fails the decision before it leaves the graph.

human_review — LangGraph interrupt() on all ban/escalate actions; SqliteSaver checkpointing so paused cases survive restarts; FastAPI approve/resume endpoints drive the review queue.

Architecture diagram

SENTINEL triage workflow: abuse report through input guardrails, policy-RAG retrieval, classify and decide, to grounded routing and eval gate

abuse report -> input guardrails -> policy-RAG retrieve -> LangGraph classify + decide -> grounded routing + CI eval gate

Before & After

Before

Unguarded LLM triage produced plausible-sounding enforcement rationales with hallucinated or out-of-scope policy citations, with no automated regression check on accuracy.

unverifiable citations · no CI gate

After

Structural enforcement holds 0 ungrounded citations across 75 live cases; 90% routing accuracy passes the CI gate; Ragas semantic faithfulness (0.699) provides a separate, honest signal on rationale quality.

90% routing · 0 ungrounded · 0.699 Ragas faithfulness

Execution Footprint

Core stack and operating patterns used to deliver the outcomes above.

Tech stack

LangGraph FastAPI Docker

Techniques / models / operations

Policy-RAG Grounding Structured Outputs (Instructor/Pydantic) Layered Guardrails Human-in-the-Loop (LangGraph interrupt) CI Golden-Set Gate Ragas Faithfulness Evals OpenInference / Phoenix Tracing