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

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 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. 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 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 click, drag, scroll, mouse event dispatch via Input.dispatchMouseEvent
Keyboard driver/keyboard.ts type, pressKey, form submission, Input.dispatchKeyEvent
Navigation driver/nav.ts Target.navigate, URL changes, iframe targeting
Observation driver/observe.ts Screenshots, element-center calculation, DOM snapshots
Waits driver/waits.ts Load events, selector polling, network idle detection

Each driver imports cdp() from 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 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 invocationclick('button#submit') in src/helpers.ts

  2. Element resolutionelement-resolver.ts parses the CSS selector and queries the DOM via DOM.querySelector, returning an objectId

  3. Focus preparationDOM.focus ensures the element is interactive

  4. Pointer dispatchdriver/pointer.ts calculates coordinates (or uses element-center from 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 to call Target.navigate, then 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 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:

// 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:

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 CDP session lifecycle, raw transport
src/cdp-eval.ts Low-level CDP request wrapper, runtimeValue() parsing
src/helpers.ts Public API, task-space utilities
src/element-resolver.ts Selector parsing, objectId resolution
src/driver/pointer.ts Mouse actions, coordinate dispatch
src/driver/keyboard.ts Keystroke simulation, input injection
src/driver/nav.ts URL navigation, frame targeting
src/driver/observe.ts Screenshots, DOM snapshots
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 handles session persistence and automatic re-attachment
  • Helper functions in 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 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.

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 →