# How ego-browser Drives Browser Automation for AI Agents: A Deep Dive into the CDP Architecture

> Discover how ego-browser drives browser automation for AI agents by translating high-level commands into Chrome DevTools Protocol messages. Learn about its CDP architecture.

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

---

**ego-browser is a lightweight Node.js harness that exposes high-level automation helpers (`click`, `goto`, `waitForSelector`) which internally translate actions into Chrome DevTools Protocol (CDP) messages sent to the embedded *ego* runtime.**

This browser automation layer, developed in the [citrolabs/ego-lite](https://github.com/citrolabs/ego-lite) repository, gives AI agents a Playwright-like API without the overhead of heavy frameworks. The architecture prioritizes low-level CDP efficiency, session resilience, and task-space isolation—critical requirements for autonomous agents operating at scale.

## The Three-Layer Architecture of ego-browser Automation

ego-browser organizes its automation capabilities into distinct architectural layers. Each layer abstracts complexity while maintaining direct access to the underlying Chrome DevTools Protocol.

### CDP Transport Layer: Session Management and Message Routing

The foundation sits in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts). This module maintains a single **page session**, buffers incoming CDP events, and handles automatic re-attachment when sessions drop.

Key responsibilities include:

- `Target.attachToTarget` — establishes the initial connection to the active tab
- `Page.enable`, `DOM.enable` — enables domain-specific events for the session
- `ensureSession()` — lazily bootstraps connections on first helper invocation
- `browserCdp()` — injects the current session ID when callers omit it

Session loss is transparently handled. The runtime detects disconnections and re-attaches without throwing errors to the consuming AI agent.

### Helper Façade: The Public API Surface

[`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) re-exports all automation primitives and implements **task-space management**. This is the layer most AI agents interact with directly.

Core functions exported include:

- Navigation: `goto(url)`, `reload()`, `goBack()`
- Interaction: `click(selector)`, `fill(selector, value)`, `hover(selector)`
- Observation: `waitForSelector(selector)`, `screenshot(options)`, `evaluate(fn)`
- Task isolation: `newTaskSpace()`, `useOrCreateTaskSpace()`

The façade also normalizes errors. CDP-level exceptions get transformed into descriptive messages that agents can parse programmatically.

### Driver Modules: Concrete Action Implementation

Five specialized drivers in `src/driver/` compose raw CDP commands into coherent actions:

| Driver | File | Capabilities |
|--------|------|--------------|
| **Pointer** | [`driver/pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/pointer.ts) | `click`, `drag`, `scroll`, mouse event dispatch via `Input.dispatchMouseEvent` |
| **Keyboard** | [`driver/keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/keyboard.ts) | `type`, `pressKey`, form submission, `Input.dispatchKeyEvent` |
| **Navigation** | [`driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/nav.ts) | `Target.navigate`, URL changes, iframe targeting |
| **Observation** | [`driver/observe.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/observe.ts) | Screenshots, element-center calculation, DOM snapshots |
| **Waits** | [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts) | Load events, selector polling, network idle detection |

Each driver imports `cdp()` from [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) to send commands through the runtime layer.

## How Element Resolution Bridges Selectors to CDP Object IDs

AI agents work with human-readable selectors. CDP requires `objectId` references. [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) bridges this gap.

The resolver accepts multiple locator syntaxes:

- `loc=css:.button.primary` — CSS selector with explicit prefix
- `xpath=//button[@id='submit']` — XPath expression
- `@3` — numeric reference to previously resolved element

Resolution failures get classified as **transient** (element not yet in DOM, retry advised) or **permanent** (invalid selector, immediate error). This classification powers intelligent retry logic in wait utilities.

Successful resolution returns a CDP-compatible `objectId` that pointer and keyboard drivers consume directly.

## The Automation Flow: From Helper Call to Browser Action

Understanding how ego-browser executes a typical `click()` call reveals the full stack:

1. **Helper invocation** — `click('button#submit')` in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)

2. **Element resolution** — [`element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/element-resolver.ts) parses the CSS selector and queries the DOM via `DOM.querySelector`, returning an `objectId`

3. **Focus preparation** — `DOM.focus` ensures the element is interactive

4. **Pointer dispatch** — [`driver/pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/pointer.ts) calculates coordinates (or uses element-center from [`driver/observe.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/observe.ts)) and sends `Input.dispatchMouseEvent` with `type: 'mousePressed'` then `'mouseReleased'`

5. **Result propagation** — Success returns void; failures throw normalized exceptions

Navigation flows differ slightly. `goto(url)` uses [`driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/nav.ts) to call `Target.navigate`, then [`driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/driver/waits.ts) polls for `Page.loadEventFired` or network idle conditions.

## Task-Space Isolation for Multi-Agent Safety

AI agents in production require **browser context isolation**. ego-browser implements *task spaces*—dedicated browser contexts with separate cookies, localStorage, and tab ownership.

Functions in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) manage this:

- `newTaskSpace()` — creates fresh browser context with unique identifier
- `useOrCreateTaskSpace(id)` — returns existing context or initializes new one
- Ownership rules prevent agents from interfering with each other's sessions

This design enables safe concurrent operation without the memory overhead of separate browser instances.

## Practical Code Examples for AI Agent Integration

These snippets demonstrate typical ego-browser usage via the CLI or module import:

```javascript
// Navigate and establish session
await goto('https://example.com');

// Wait for critical element
await waitForSelector('[data-testid="content-loaded"]');

// Interact with form
await fill('input[name="search"]', 'automation tools');
await click('button[type="submit"]');

// Extract data via evaluation
const results = await evaluate(() => {
  return Array.from(document.querySelectorAll('.result'))
    .map(el => el.textContent);
});

// Capture visual state
await screenshot({ path: 'results.png', fullPage: true });

// Clean task-space when done
await closeTaskSpace();

```

For programmatic use, import the helpers directly:

```javascript
import { goto, click, evaluate, newTaskSpace } from '@ego/browser';

async function runAgentTask() {
  await newTaskSpace('agent-42');
  await goto('https://tasks.example.com');
  // ... automation logic
}

```

## Key Implementation Files Reference

| File | Purpose |
|------|---------|
| [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts) | CDP session lifecycle, raw transport |
| [`src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/cdp-eval.ts) | Low-level CDP request wrapper, `runtimeValue()` parsing |
| [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) | Public API, task-space utilities |
| [`src/element-resolver.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/element-resolver.ts) | Selector parsing, `objectId` resolution |
| [`src/driver/pointer.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/pointer.ts) | Mouse actions, coordinate dispatch |
| [`src/driver/keyboard.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/keyboard.ts) | Keystroke simulation, input injection |
| [`src/driver/nav.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/nav.ts) | URL navigation, frame targeting |
| [`src/driver/observe.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/observe.ts) | Screenshots, DOM snapshots |
| [`src/driver/waits.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/driver/waits.ts) | Polling primitives, event awaiting |

## Summary

- **ego-browser** provides lightweight browser automation for AI agents through a three-layer CDP architecture
- The **CDP transport layer** in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) handles session persistence and automatic re-attachment
- **Helper functions** in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) expose a Playwright-like API while managing task-space isolation
- **Driver modules** compose raw CDP commands for pointer, keyboard, navigation, observation, and wait operations
- **Element resolution** translates human-readable selectors into CDP `objectId` references with intelligent failure classification
- Task-space primitives enable safe multi-agent concurrency without full browser instance overhead

## Frequently Asked Questions

### What makes ego-browser different from Playwright or Puppeteer?

ego-browser intentionally minimizes dependencies and abstraction layers. While Playwright bundles multiple browser engines and extensive assertion libraries, ego-browser focuses exclusively on CDP-based Chrome automation with a smaller footprint. This makes it suitable for AI agents running in resource-constrained environments where startup time and memory usage matter.

### 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 implements transparent re-attachment. When `browserCdp()` detects a closed session, `ensureSession()` re-establishes the `Target.attachToTarget` connection using stored context information. This resilience happens without surfacing errors to AI agent code, allowing continuous operation across transient failures.

### Can AI agents use custom Chrome flags or DevTools extensions?

Yes. The embedded *ego* runtime accepts Chrome startup parameters. Agents can enable specific features by configuring the runtime before helper invocation. However, the public API intentionally abstracts these details—advanced customization requires direct CDP calls through `cdp()` with domain-specific commands.

### What selector strategies perform best with ego-browser's element resolver?

CSS selectors with the `loc=css:` prefix resolve fastest due to direct `DOM.querySelector` mapping. XPath expressions work for complex traversals but incur minor parsing overhead. Numeric `@N` references are fastest when reusing previously located elements across multiple actions, avoiding repeated DOM queries.