Sentinel hooks into the OpenHands EventStream and runs instant AST analysis on every file write. When it detects duplication, complexity spikes, or bloat โ it warns the agent inline. The agent self-corrects in the same session.
Three integration paths. Zero configuration.
from openhands_sentinel import Sentinel
from agent_vcr import VCRRecorder
recorder = VCRRecorder()
sentinel = Sentinel(recorder=recorder)
# Attach to any OpenHands runtime
sentinel.attach(runtime.event_stream)
# Done. Every FileWrite is now guarded.
# Install
$ pip install ai-agent-vcr
# Scan any directory
$ sentinel scan ./my-project
# With strict thresholds
$ sentinel scan ./src --max-complexity 6
# Output: per-file report + audit .vcr
Four components. One feedback loop. Zero external calls.
Hooks into the OpenHands EventStream. Converts FileWrite + FileEdit events into analysis targets. Includes oversized-frame guardrails (issue #7402).
The orchestrator. Receives file events, dispatches to CodeAnalyzer, decides severity, generates agent warnings, and records VCR frames.
Python AST-based analysis engine. Trajectory-aware: tracks function definitions across all files in the session to detect cross-file duplicates.
Records every analysis result as a VCR frame. Creates a time-travel-debuggable audit trail of the agent's quality trajectory.
The loop: Event โ Analyze โ Warn โ Agent Self-Corrects โ Event โ Analyze โ Clean โ
End-to-end flow of a single agent session with Sentinel.
FileWrite event
Intercepts event
Dispatches analysis
AST inspection
Recorded to .vcr/
โโโโโโโโโ SENTINEL SESSION โโโโโโโโโ
โถ STEP 1 Agent writes auth/utils.py
๐ก๏ธ Analyzing auth/utils.py...
Functions found: hash_password, verify_token, generate_salt
โ CLEAN โ No violations detected
๐ผ Recorded as frame #1
โถ STEP 2 Agent writes api/handlers.py
๐ก๏ธ Analyzing api/handlers.py...
Functions found: handle_auth_request, hash_password
โโโ VIOLATIONS DETECTED โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CRITICAL hash_password() duplicates auth/utils.py:8
โ CRITICAL handle_auth_request() is 109 lines (max: 40)
โ CRITICAL Cyclomatic complexity: 32 (max: 8)
โ WARNING Parameter count: 9 (max: 5)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Injecting MessageAction into EventStream...
โ Agent acknowledges warning
๐ผ Recorded as frame #2 (with violations)
โถ STEP 3 Agent rewrites api/handlers.py
๐ก๏ธ Re-analyzing api/handlers.py...
Functions found: handle_auth_request (imports hash_password)
โ CLEAN โ All 4 violations resolved!
๐ผ Recorded as frame #3
โโโโโโโโโ SESSION COMPLETE โโโโโโโโโ
๐ผ Full audit trail: .vcr/sentinel-session.vcr
๐ Quality: 4 violations caught โ 4 self-corrected โ 0 remaining
Five classes of code quality violations, all detected via Python's built-in AST module.
Cross-file detection. When an agent defines hash_password() in a new file but it already exists in auth/utils.py, Sentinel catches it instantly. Trajectory-aware โ tracks all definitions across the session.
Cyclomatic complexity analysis via AST branch counting. Default threshold: 8. A function with 32 nested if/else/for/while/try paths gets flagged before the agent compounds the complexity.
Detects functions that exceed the line-length threshold (default: 40 lines). AI agents routinely generate 100+ line handlers. Sentinel enforces decomposition.
Functions with more than 5 parameters (configurable). A symptom of god-functions that try to do everything. Forces the agent to use config objects or decompose.
Detects when a file grows by more than 50% in a single write. Prevents the "append-only" pattern where agents keep adding to the same file instead of creating new modules.
VCRRuntime detects oversized recording frames (the OpenHands issue #7402 pattern) and warns before they pollute the audit trail. Keeps recordings fast and lean.
Three classes. Minimal surface area. Maximum impact.
The AST-based analysis engine. Stateful โ maintains a cross-file function registry for duplicate detection.
config.max_function_length โ Max lines per function (default: 40)config.max_complexity โ Max cyclomatic complexity (default: 8)config.max_params โ Max parameters per function (default: 5)config.max_growth_pct โ Max file growth % (default: 50)Parses Python source, runs all checks, returns AnalysisResult with violations list and file metrics.
Registers function definitions from a file into the cross-file registry. Called automatically on first analysis.
The orchestrator. Connects CodeAnalyzer to VCRRecorder and the OpenHands EventStream.
recorder โ VCRRecorder instance for audit trailconfig โ AnalysisConfig for thresholdsSubscribes to an OpenHands EventStream. Automatically intercepts FileWrite and FileEdit actions.
Manually trigger analysis on a specific file. Returns AnalysisResult.
Generates a formatted warning string suitable for injecting as a MessageAction into the agent's stream.
Run Sentinel standalone from any terminal.
# Basic scan
$ sentinel scan ./src
๐ก๏ธ Scanning ./src ...
auth/utils.py CLEAN โ
api/handlers.py 3 violations
models/user.py CLEAN โ
services/payment.py 1 warning
Summary: 4 files scanned | 3 critical | 1 warning
๐ผ Audit trail: .vcr/sentinel-scan.vcr
# Custom thresholds
$ sentinel scan ./src \
--max-complexity 6 \
--max-length 30 \
--max-params 4
# JSON output for CI pipelines
$ sentinel scan ./src --format json | jq '.violations'
The OpenHands team is building a verification stack with critic models. Here's why Sentinel complements โ not replaces โ that approach.
| Metric | Critic LLM | Sentinel |
|---|---|---|
| Latency per check | 2-8 seconds | <2ms |
| Cost per check | $0.003 - $0.02 | $0.00 |
| Requires internet | Yes (API calls) | No |
| Deterministic | No (LLM variance) | Yes (AST-based) |
| Catches duplicates | Sometimes (limited context) | Always (trajectory-aware) |
| Catches logical bugs | Yes (LLM reasoning) | No (structural only) |
| Catches security issues | Yes (if prompted) | No (structural only) |
| Dependencies | API key + network | Python stdlib only |
| Enterprise-ready | Data leaves your infra | 100% air-gapped |
Run Sentinel as the first pass โ instant, free, deterministic structural checks on every write. Use critic LLMs as a second pass for semantic/logical review on high-risk changes. Sentinel catches the low-hanging fruit at zero cost, so the critic model only runs on code that's already structurally sound.
Where everything lives in the codebase.
agent-vcr/
โโโ src/
โ โโโ openhands_sentinel/ # NEW โ The Sentinel package
โ โ โโโ __init__.py # Exports: Sentinel, CodeAnalyzer
โ โ โโโ analyzer.py # AST engine (314 lines)
โ โ โโโ sentinel.py # Orchestrator (325 lines)
โ โ โโโ cli.py # CLI entry point
โ โ โโโ py.typed # PEP 561 marker
โ โ
โ โโโ agent_vcr/
โ โโโ integrations/
โ โโโ openhands.py # Existing ACIDWorkspace
โ โโโ openhands_hook.py # NEW โ VCRRuntime hook
โ
โโโ examples/
โ โโโ sentinel_demo.py # Self-contained demo
โ
โโโ docs/
โ โโโ index.html # Main docs (updated)
โ โโโ sentinel/
โ โโโ index.html # โ You are here
โ
โโโ pyproject.toml # v0.6.0, sentinel CLI registered
Three lines of code. Zero configuration. Ship cleaner agents today.
pip install ai-agent-vcr