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/*.json
  • CursorParser → Cursor-specific log paths
  • ClineParser, 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:

  1. Create a new parser module in Sensor/adr_sensor/parsers/
  2. Implement log location and decoding logic
  3. Return AgentEvent instances with normalized fields
  4. 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 AgentObserver class in Sensor/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 AgentEvent objects.
  • 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →