# How ego-browser Integrates with the Chrome DevTools Protocol (CDP) for Browser Control

> Discover how ego-browser integrates with the Chrome DevTools Protocol for robust browser control. Learn about its session management, message transport, and auto-reconnection features.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: internals
- Published: 2026-08-15

---

**The ego-browser package bridges high-level automation helpers to Chrome DevTools Protocol commands through a private `ego` runtime that handles session management, message transport, and automatic reconnection in the closed-source ego lite application.**

The **ego-browser** integration with **CDP** (Chrome DevTools Protocol) enables scriptable browser automation for AI agents by wrapping low-level protocol commands in ergonomic JavaScript helpers. This article examines how the `citrolabs/ego-lite` repository orchestrates CDP communication, from raw message transport to polished driver-level APIs.

---

## CDP Transport Layer: The Core Messaging Infrastructure

All CDP communication in ego-browser funnels through [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts). This file encapsulates the complete transport stack and session lifecycle.

The runtime exposes a native bridge via `ego.sendCDPMessage`, which accepts a JSON-encoded CDP request and returns the parsed response. According to the source code, this function is the sole entry point between the JavaScript harness and the closed-source `ego` native runtime.

Session management happens automatically:

- **Attachment**: The runtime attaches to the browser's CDP session on first use
- **Reconnection**: If the session detaches (e.g., after a page crash), the runtime re-attaches transparently
- **Caching**: Session handles are cached for approximately 2 seconds to eliminate redundant handshake overhead

An internal event queue in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) buffers up to 10,000 CDP events. This queue powers observability helpers like `observe()`, ensuring no events are dropped during asynchronous operations such as screenshots or DOM snapshots.

---

## Evaluating CDP Commands: The cdp() and js() Helpers

The [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) file provides two foundational wrappers for CDP execution:

### cdp(): Direct CDP Method Invocation

```javascript
// Enable network monitoring via CDP
await cdp('Network.enable')

```

The `cdp()` function accepts a CDP method name (e.g., `"Network.enable"`, `"Page.navigate"`) and an optional parameters object. It forwards the request to `browserRuntime.sendCDPMessage` and returns the raw CDP response payload.

### js(): JavaScript Evaluation in Page Context

```javascript
// Extract the page title
const title = await js('document.title')
console.log('Page title:', title)

```

The `js()` helper builds on `cdp()` by invoking the `Runtime.evaluate` CDP method. It automatically wraps expressions in an IIFE with an explicit `return` statement, allowing direct evaluation of top-level expressions without manual wrapping.

---

## Driver Layer: High-Level Actions as CDP Sequences

The `src/driver/` directory translates common automation patterns into precise CDP command sequences. Each driver module abstracts payload construction while preserving full CDP fidelity.

### Navigation ([`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts))

```javascript
await nav('https://example.com')
// Internally calls: cdp('Page.navigate', { url: 'https://example.com' })

```

### Mouse Interactions ([`src/driver/pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/pointer.ts))

```javascript
await click('css:#login-button')
// Maps to: Input.dispatchMouseEvent with calculated coordinates

```

The pointer driver resolves element locators, computes viewport coordinates, and dispatches `Input.dispatchMouseEvent` with appropriate `type` values (`mousePressed`, `mouseReleased`).

### Keyboard Input ([`src/driver/keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/keyboard.ts))

```javascript
await type('css:#username', 'alice')
// Dispatches: Input.dispatchKeyEvent for each character

```

### Screenshots ([`src/driver/screencast.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/screencast.ts))

```javascript
await screenshot({ path: 'login.png' })
// Calls: Page.captureScreenshot with format and quality parameters

```

---

## Session and Event Management for Robust Automation

The [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) event queue serves critical reliability functions:

- **Screenshot synchronization**: `observe()` can capture DOM state without losing intervening CDP events
- **Network tracking**: Buffered `Network.*` events remain available for post-navigation analysis
- **Race condition prevention**: Queued events ensure deterministic behavior during rapid command sequences

The 10,000-entry limit provides headroom for long-running automation scripts while preventing unbounded memory growth.

---

## Error Handling and Transient Retry Logic

When CDP calls fail due to recoverable conditions—typically session detachment during navigation—the runtime throws `ElementResolutionError` with a `transient: true` flag. This signal enables automatic retry in higher-level wait loops.

```javascript
// waitFor in src/driver/waits.ts leverages transient detection
await waitFor('css:.ready', { timeout: 5 })
// Retries CDP element queries until found or timeout exceeded

```

The [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) module implements exponential backoff for transient failures, distinguishing them from permanent resolution failures (invalid selectors, deleted elements).

---

## Summary

- **Transport**: [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) manages CDP sessions via `ego.sendCDPMessage` with automatic reconnection and 2-second session caching
- **Primitives**: [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) exposes `cdp()` for raw CDP calls and `js()` for evaluated expressions
- **Drivers**: `src/driver/` modules map high-level actions (`nav`, `click`, `type`, `screenshot`) to specific CDP methods
- **Reliability**: Event queue (10K entries) and transient error classification enable robust asynchronous automation

---

## Frequently Asked Questions

### What CDP methods does ego-browser support?

ego-browser supports the full CDP surface through the `cdp()` helper. Higher-level drivers in `src/driver/` use common methods including `Page.navigate`, `Input.dispatchMouseEvent`, `Input.dispatchKeyEvent`, `Page.captureScreenshot`, and `Runtime.evaluate`. You can invoke any CDP domain directly via `cdp('Domain.method', params)`.

### How does ego-browser handle browser crashes or disconnections?

The [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) module detects session detachment and automatically re-attaches to the browser's CDP endpoint. Failed calls during reconnection are marked as `transient` errors, allowing wait loops and retries to resume seamlessly once the session restores.

### Can I use ego-browser without the closed-source ego runtime?

No. The CDP integration depends on `ego.sendCDPMessage`, a native function provided exclusively by the ego lite application. The `ego-browser` package is designed as a harness for this runtime, not a standalone CDP client.

### How does the JavaScript evaluation wrapper work?

The `js()` function in [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) takes a JavaScript expression, wraps it in an IIFE with `return`, and executes it via `Runtime.evaluate`. This pattern ensures top-level expressions yield values without requiring explicit return statements from the caller.