mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

AI Agents

Uber's ADR: How Production Agent Security Moved from Logs to Dual-Tier Threat Detection

Uber's ADR normalizes telemetry across 7+ AI coding tools and uses two-tier detection to catch prompt injection and unsafe tool use before execution.

Source: github.com
Uber's ADR: How Production Agent Security Moved from Logs to Dual-Tier Threat Detection

Uber open-sourced ADR (Agentic AI Detection and Response) after deploying it in production to secure employee-facing tools like Cursor, Claude Code, and Codex, plus customer-facing support agents. The system normalizes telemetry from 7+ AI coding tools, runs a two-tier detector to catch prompt injection and unsafe tool use, and ships with a 303-task benchmark covering all 17 known agent attack techniques. The MLSys 2026 paper and 836 GitHub stars in early trending signal enterprise demand for agent security infrastructure that goes beyond basic logging.

The observability problem

Most agent security starts with logs. You capture LLM calls, tool invocations, and maybe some user context. But when you run Cursor on macOS, Claude Code on Linux, and internal automation agents on Windows, each tool emits telemetry in a different shape. Cursor logs JSON to a local file. Claude Code streams events over a Unix socket. Codex writes to stdout. You end up with per-tool adapters, brittle parsers, and no unified view of what agents are doing.

ADR’s sensor solves this by normalizing telemetry into a common schema: agent intent, tool use, execution traces, and context. The sensor runs as a local daemon on developer machines and as a sidecar for server-side agents. It hooks into each tool’s native telemetry channel (file watchers, socket listeners, process interceptors) and emits structured events to a central collector.

The schema captures:

  • Intent: the user’s natural-language request or the agent’s internal goal.
  • Tool calls: function name, arguments, and whether the call was approved or auto-executed.
  • Execution traces: command output, file modifications, network requests.
  • Context: workspace path, active files, environment variables.

This normalization layer is the foundation for detection. Without it, you cannot compare behavior across tools or run centralized threat models.

Two-tier detection architecture

ADR’s detector uses a two-tier pipeline to balance recall and cost. The first tier is a high-recall triage model that flags any session with suspicious patterns. The second tier is an agentic reasoning engine that investigates flagged sessions in depth.

Tier 1: High-recall triage

The triage model runs on every agent session. It looks for:

  • Tool calls that touch sensitive paths (~/.ssh, /etc/passwd, cloud credential files).
  • Commands with shell metacharacters or encoded payloads.
  • Unusual sequences (e.g., file read followed by network POST).
  • Divergence from the user’s stated intent.

This tier uses a lightweight classifier (fine-tuned BERT or a small LLM) and runs in under 100ms per session. It produces a binary flag: safe or suspicious. The false-positive rate is intentionally high (around 10-15%) because the cost of escalation is low.

Tier 2: Agentic reasoning

Suspicious sessions escalate to the agentic reasoning tier. This tier uses a larger LLM (GPT-4 or Claude 3.5) with a multi-step reasoning prompt:

  1. Reconstruct the user’s intent from the original request.
  2. Trace the agent’s tool calls and execution flow.
  3. Identify deviations: did the agent do something the user did not ask for?
  4. Classify the deviation: benign (e.g., installing a dependency), risky (e.g., reading SSH keys), or malicious (e.g., exfiltrating data).

The reasoning agent has access to the full session context, including file diffs, command output, and prior tool calls. It generates a structured verdict with a risk score and a natural-language explanation.

This two-tier design prevents alert fatigue. Security teams only review sessions that pass both filters. In Uber’s production deployment, the triage tier processes thousands of sessions per day, but the reasoning tier only sees 50-100.

Escalation triggers

The transition from tier 1 to tier 2 is not just a threshold. ADR uses a rule-based escalation policy that considers:

  • Triage confidence: if the classifier score is above 0.8, escalate immediately.
  • Tool risk profile: auto-escalate sessions involving high-risk tools (e.g., curl, ssh, docker).
  • User role: escalate sessions from users with access to production systems or sensitive data.
  • Time-of-day anomalies: escalate sessions outside normal working hours.

This policy is configurable per organization. Uber’s production config escalates about 5% of sessions to tier 2.

ADR-Bench: 303 tasks, 133 MCP servers, 17 attack techniques

ADR ships with a benchmark that tests agent security under realistic enterprise conditions. ADR-Bench includes:

  • 303 tasks that simulate real developer workflows (e.g., “refactor this function,” “deploy to staging,” “debug this error”).
  • 133 MCP servers that provide tools for file I/O, shell execution, API calls, and database queries.
  • 17 attack techniques from the MITRE ATLAS framework, including prompt injection, tool misuse, data exfiltration, and privilege escalation.

Each task has a ground-truth label: safe or unsafe. The benchmark measures detection accuracy, false-positive rate, and latency.

“Realistic enterprise conditions” means:

  • Tasks use real codebases (anonymized from Uber’s internal repos).
  • MCP servers expose the same tools available in production (file system, Git, Docker, cloud CLIs).
  • Attack payloads are embedded in natural-language prompts, not synthetic test strings.

The benchmark also includes baseline detectors (regex-based, static analysis, and a single-tier LLM classifier) for comparison. ADR’s two-tier detector achieves 92% recall and 8% false-positive rate, compared to 78% recall and 15% FPR for the single-tier baseline.

Why the prevention component is not open-sourced

ADR’s architecture includes a fourth component: ADR Prevention, which blocks unsafe tool calls before execution. This component is deployed in production at Uber but not included in the open-source release.

The reason is the trust boundary. Detection can run asynchronously and flag sessions for review. Prevention must run synchronously and make a binary decision: allow or block. If the prevention logic is wrong, it breaks developer workflows. If it is too permissive, it lets attacks through.

Uber’s prevention component uses a combination of:

  • Static policies: block any tool call that touches /etc/shadow or runs rm -rf /.
  • Dynamic policies: block tool calls that deviate from the user’s intent (as determined by the reasoning agent).
  • Human-in-the-loop: for ambiguous cases, pause execution and ask the user to confirm.

This logic is tightly coupled to Uber’s internal tooling, access control policies, and incident response workflows. Open-sourcing it would require abstracting those dependencies, which is non-trivial.

The absence of prevention in the open-source release reveals a design principle: detection is a commodity, but enforcement is context-specific. Every organization has different risk tolerances, compliance requirements, and operational constraints. ADR provides the observability and detection primitives, but you bring your own enforcement layer.

Telemetry normalization without per-tool adapters

The sensor’s normalization layer is the hardest part of the system to build. Each AI coding tool has a different telemetry interface:

ToolTelemetry interfaceEvent formatSampling rate
CursorJSON log fileNewline-delimitedPer keystroke
Claude CodeUnix socket (JSON-RPC)Streaming eventsPer action
CodexStdout (structured logging)JSON linesPer request
InternalgRPC (Protobuf)Binary messagesConfigurable

ADR avoids per-tool adapters by defining a plugin interface. Each plugin implements three methods:

class TelemetryPlugin:
    def connect(self) -> None:
        """Establish connection to the tool's telemetry channel."""
        pass

    def poll(self) -> Iterator[RawEvent]:
        """Yield raw events from the tool."""
        pass

    def normalize(self, event: RawEvent) -> NormalizedEvent:
        """Map raw event to ADR's common schema."""
        pass

The sensor daemon loads plugins at startup and runs them in parallel. Each plugin polls its telemetry channel and emits normalized events to a shared queue. The daemon batches events and forwards them to the central collector.

This design keeps the core sensor logic tool-agnostic. Adding support for a new tool requires writing a plugin (50-100 lines of Python), not modifying the sensor daemon.

Failure modes and observability gaps

ADR’s two-tier detector has three failure modes:

  1. Triage bypass: an attack evades the high-recall classifier by using novel techniques or obfuscation.
  2. Reasoning hallucination: the agentic reasoning tier misinterprets the session context and produces a false negative.
  3. Telemetry loss: the sensor fails to capture critical events due to tool crashes, network partitions, or rate limiting.

Uber mitigates these with:

  • Continuous red teaming: the offline ADR Explorer engine (not open-sourced) generates adversarial sessions to test detector coverage.
  • Human review loops: security analysts review a random sample of tier-2 verdicts to catch reasoning errors.
  • Telemetry health checks: the sensor daemon emits heartbeat events and alerts if any plugin stops producing data.

The biggest observability gap is cross-session correlation. ADR treats each agent session as independent. If an attacker spreads a payload across multiple sessions (e.g., writes a malicious script in session 1, executes it in session 2), the detector may miss the connection. Uber’s production deployment addresses this with a session graph that links related activities, but that component is not in the open-source release.

Deployment shape

ADR runs in three layers:

  1. Edge sensors: local daemons on developer machines and sidecars for server-side agents.
  2. Central collector: ingests normalized events, stores them in a time-series database (InfluxDB or Prometheus), and forwards suspicious sessions to the detector.
  3. Detector cluster: runs the two-tier pipeline on a Kubernetes cluster with autoscaling.

The detector cluster uses a work queue (RabbitMQ or Kafka) to distribute sessions across worker pods. Each worker runs the triage model locally and calls the reasoning LLM via API. The reasoning tier has a rate limit (10 requests per second) to control costs.

Uber’s production deployment processes 10,000+ sessions per day with a median end-to-end latency of 2 seconds (triage) and 15 seconds (reasoning).

Trade-offs and alternatives

ApproachRecallFPRLatencyCost per session
Regex-based45%30%<10ms$0.00
Static analysis60%20%100ms$0.00
Single-tier LLM78%15%500ms$0.02
ADR two-tier92%8%2s$0.05
Human-only review98%2%10min$5.00

ADR’s two-tier design sits between single-tier LLM classifiers and human review. It achieves high recall without overwhelming security teams. The cost is 2.5x higher than a single-tier model, but 100x cheaper than human review.

The main alternative is to skip detection entirely and rely on prevention. Block all risky tool calls by default and require human approval. This works for high-security environments (e.g., financial services, healthcare) but breaks developer velocity. Uber chose detection-first because it supports both employee productivity and customer-facing agents.

Technical verdict

Use ADR if you run AI coding tools at scale (100+ sessions per day) and need unified visibility across heterogeneous agent platforms. The sensor’s plugin architecture and normalization layer solve the multi-tool telemetry problem that logging alone cannot fix.

Use the two-tier detector if you have security analysts who can review 50-100 flagged sessions daily. The reasoning tier produces actionable verdicts with context, but enforcement still requires human judgment or custom policies.

Avoid ADR if you need synchronous blocking. The 2-second detection latency is too slow for real-time prevention. You will need static policies or a separate enforcement layer that runs before tool execution.

Avoid ADR if you run fewer than 100 sessions per day. The operational overhead (sensor deployment, collector infrastructure, detector cluster) outweighs the value. Start with basic logging and upgrade when volume justifies the complexity.

The missing prevention component means you must design your own enforcement policies based on your organization’s risk tolerance and operational constraints.