What Is the Sensor Component in ADR and How Does It Collect Agent Telemetry?
The Sensor is the telemetry-ingestion layer of Uber's ADR (Automated Detection and Response) repository that gathers raw interaction logs from AI coding assistants and normalizes them into a unified, analyzable format.
The Sensor bridges the gap between heterogeneous, platform-specific telemetry produced by AI agents like Claude, Cursor, Cline, Warp, Codex, and Claude Desktop and the downstream security analysis pipelines of ADR. This article breaks down exactly how the Sensor component works under the hood, with reference to the actual source implementation in uber/ADR.
Core Architecture: The AgentObserver Class
At the heart of the Sensor lies the AgentObserver class, defined in Sensor/adr_sensor/observer.py. This class orchestrates the entire telemetry collection pipeline through a four-stage process.
Stage 1: Parser Discovery and Initialization
When instantiated, AgentObserver creates a set of parser objects. Each parser knows how to locate and decode log files for a specific agent:
ClaudeParser→~/.cache/adr_sensor/claude/*.jsonCursorParser→ Cursor-specific log pathsClineParser,WarpParser,CodexParser,ClaudeDesktopParser→ respective default directories
Parsers can use their default directories or accept a user-supplied path override.
Stage 2: Log Parsing and Normalization
Each discovered log file is parsed into an AgentEvent data class, defined in Sensor/adr_sensor/schemas/agent_event_schema.py. This schema normalizes disparate fields across all supported agents into a single consistent structure:
| Normalized Field | Description |
|---|---|
| UUID | Unique event identifier |
| Timestamp | Standardized temporal reference |
| Session ID | Correlated conversation grouping |
| Chat turns | Message sequence within a session |
| Tool usage | Which tools the agent invoked |
| Host metadata | System configuration context |
| Content hash | Integrity verification |
Stage 3: Noise Filtering
The AgentEvent.has_meaningful_content() method filters out low-value telemetry:
- Empty conversations
- Single-message error states
- Known boilerplate strings
This ensures downstream analysis focuses on actionable security-relevant activity.
Stage 4: Aggregation and Output
Cleaned events are aggregated with optional system-configuration records, then output in multiple formats: tabular summaries to stdout, consolidated JSON/JSON-L files, or individual session files for incremental processing.
Code Implementation: Using AgentObserver
The following code demonstrates the exact implementation found in Sensor/adr_sensor/observer.py:
from adr_sensor.observer import AgentObserver
# 1️⃣ Create the observer (default output dir = ./output)
observer = AgentObserver()
# 2️⃣ Ingest logs from every supported agent
events, configs = observer.ingest_all() # source_filter defaults to "all"
# 3️⃣ Show a quick human-readable summary
observer.display_summary(events, configs)
# 4️⃣ Persist the unified telemetry for later analysis
observer.save_to_file(events, configs, output_format="json")
CLI Entry Point
The Sensor exposes a minimal CLI in Sensor/adr_sensor/cli.py that wraps the same pipeline:
# Run from command line
# $ python -m adr_sensor.cli
# This executes:
# - observer.ingest_all()
# - observer.display_summary()
# - observer.save_to_file()
Advanced Sensor Usage Patterns
Saving Individual Session Files
For incremental downstream processing, save each session as a separate file:
from pathlib import Path
output_dir = Path("/tmp/adr_sessions")
saved_paths = observer.save_sessions_to_individual_files(events, output_dir)
print(f"Saved {len(saved_paths)} session files to {output_dir}")
Filtering Already-Processed Sessions
Avoid reprocessing duplicate telemetry when running collection repeatedly:
new_events = observer.filter_entries_by_existing_files(events, output_dir)
print(f"{len(new_events)} new/updated sessions to process")
Key Source Files in the Sensor Component
| File Path | Purpose |
|---|---|
Sensor/adr_sensor/observer.py |
Core AgentObserver orchestrator—creates parsers, aggregates events, displays summaries, writes output |
Sensor/adr_sensor/schemas/agent_event_schema.py |
AgentEvent data class with UUID generation, content hashing, and has_meaningful_content() helper |
Sensor/adr_sensor/cli.py |
Command-line entry point for local or CI pipeline execution |
Sensor/adr_sensor/parsers/ |
Modular parsers: claude_parser.py, cursor_parser.py, cline_parser.py, warp_parser.py, codex_parser.py, claude_desktop_parser.py |
Sensor/README.md |
Package overview, installation, and usage documentation |
Extending the Sensor for New AI Agents
The Sensor's parser-based architecture enables straightforward extension. To add support for a new AI agent:
- Create a new parser module in
Sensor/adr_sensor/parsers/ - Implement log location and decoding logic
- Return
AgentEventinstances with normalized fields - Register the parser in
AgentObserver's initialization
This design ensures ADR maintains a consistent view of agent activity regardless of how the underlying AI assistant ecosystem evolves.
Summary
- The Sensor is ADR's telemetry-ingestion layer, implemented primarily through the
AgentObserverclass inSensor/adr_sensor/observer.py. - Agent telemetry collection works via pluggable parsers that discover, parse, and normalize logs from Claude, Cursor, Cline, Warp, Codex, and Claude Desktop into unified
AgentEventobjects. - Noise reduction happens through
AgentEvent.has_meaningful_content(), filtering empty or boilerplate interactions before downstream analysis. - Flexible output options include CLI summaries, consolidated JSON files, or individual session files for incremental processing.
- Extensible architecture allows new AI agents to be supported by adding parser modules without modifying core collection logic.
Frequently Asked Questions
What AI agents does the ADR Sensor currently support?
The Sensor supports Claude, Cursor, Cline, Warp, Codex, and Claude Desktop as of the latest implementation in uber/ADR. Each agent has a dedicated parser module in Sensor/adr_sensor/parsers/ that handles its specific log format and default storage location.
How does the Sensor handle different log formats from various AI agents?
The AgentObserver delegates format-specific parsing to specialized parser classes. Each parser knows how to locate its agent's logs and extract relevant fields. The parsers then instantiate AgentEvent objects from Sensor/adr_sensor/schemas/agent_event_schema.py, which normalizes heterogeneous data into a consistent schema regardless of source agent.
Can the Sensor run in automated pipelines or only interactively?
Both. The Sensor/adr_sensor/cli.py module provides a command-line interface suitable for CI/CD pipelines, cron jobs, or local development. The CLI calls AgentObserver.ingest_all(), display_summary(), and save_to_file() in sequence, making unattended operation straightforward with appropriate output directory configuration.
Where does the Sensor store collected telemetry?
By default, AgentObserver uses ./output as its working directory. You can override this via the output_dir parameter. The component supports multiple persistence modes: consolidated JSON/JSON-L files via save_to_file(), or individual session files via save_sessions_to_individual_files() for incremental processing workflows.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →