Understanding the Helper Context Architecture and Page/Browser Facades in ego-browser
The ego-browser helper context architecture bundles six specialized facades—page, browser, taskSpaces, site, fetch, and cdp—into a single object that provides AI agents with a Playwright-style API for controlling browser tabs, navigation, and task isolation while keeping low-level Chrome DevTools Protocol (CDP) plumbing encapsulated.
The ego-browser package within the citrolabs/ego-lite repository implements a modular helper context architecture that bridges raw CDP operations and high-level agent scripting. Defined primarily in src/helpers.ts, the helperContext function assembles lightweight facade objects that expose browser automation capabilities through an ergonomic, Playwright-inspired interface, allowing agents to drive the embedded browser without managing protocol complexity directly.
The helperContext Entry Point
At the heart of the system lies the helperContext function (lines 22‑50 in src/helpers.ts). This factory function constructs a single context object that aggregates multiple facades, merges any extra helpers supplied by the caller, and attaches a help method that prints JSDoc‑derived documentation.
export function helperContext(extra: any = {}) {
const all = {
page: createPageFacade(),
browser: createBrowserFacade(),
taskSpaces: createTaskSpacesFacade(),
site: createSiteFacade(),
fetch: { server: serverFetch, browser: browserFetch },
cdp,
...extra,
};
return {
...all,
help: (...names: string[]) => { /* prints documentation */ },
};
}
The runtime entry point (src/run.ts) injects this object into the agent’s script scope, making all façade methods globally available.
Core Facades Overview
The helper context exposes six distinct facades, each responsible for a specific domain of browser interaction:
| Facade | Purpose | Creator Function | Key Capabilities |
|---|---|---|---|
page |
Playwright‑style page API | createPageFacade() (lines 64‑84) |
Navigation, locator creation, input actions, screenshots |
browser |
Tab‑level control | createBrowserFacade() (lines 73‑83) |
Listing, switching, opening, and closing tabs |
taskSpaces |
Task‑space lifecycle management | createTaskSpacesFacade() (lines 85‑97) |
Isolated session handling, ownership claims |
site |
Site‑skill data access | createSiteFacade() (lines 99‑107) |
Learned automation skills, tool execution |
fetch |
Network abstraction | Inline (lines 28‑31) | Server‑side and browser‑origin HTTP requests |
cdp |
Raw CDP command dispatcher | Re‑exported (lines 27‑28) | Direct protocol access via src/cdp-eval.ts |
How the Page Facade Works
The createPageFacade() function builds a thin wrapper around lower‑level drivers (nav, pointer, keyboard, waits, observe, etc.), exposing a comprehensive page automation API.
Navigation and State
Methods such as goto, reload, info, url, and title delegate directly to src/driver/nav.ts, providing high‑level navigation controls that automatically handle timeouts and load states.
// Navigation with automatic wait handling
await page.goto('https://example.com');
await page.waitForLoadState('networkidle');
const currentUrl = await page.url();
Locator API and Element Interaction
The locator method returns a strict locator object created by createLocator() (defined in src/driver/locator.ts, lines 20‑112). This object implements actions like click, fill, press, and hover by forwarding to the corresponding driver modules (src/driver/pointer.ts for mouse actions, src/driver/keyboard.ts for text input).
Convenience getters such as getByRole, getByText, getByLabel, and getByPlaceholder build selector strings using internal textSelector and roleSelector helpers before returning a configured locator. All locator methods automatically wait for elements to reach a stable state, mirroring Playwright’s auto‑awaiting behavior.
// Using convenience getters and locator chains
const loginBtn = page.getByText('Log in');
await loginBtn.click();
const items = page.locator('ul > li')
.filter({ hasText: /Item \d+/ })
.nth(0);
await items.click();
Utility Methods
The facade also exposes evaluate for JavaScript execution, screenshot and snapshot for visual capture, setDefaultTimeout for adjusting the global state.defaultTimeout, and direct access to keyboard and mouse helpers.
How the Browser Facade Works
The createBrowserFacade() provides tab‑level control by re‑exporting primitives from src/driver/nav.ts. Unlike the page facade’s element‑focused API, this facade manages the browser’s tab lifecycle.
Key methods include:
listTabs– Returns an array of open tabscurrentTab– Gets the active tab identifierswitchTab– Changes the active context to a specific tabopenOrReuseTab– Opens a new tab or reuses an existing one matching a URL patterncloseTab– Closes a specific tabensureRealTab– Validates that a tab exists and is accessibleiframeTarget– Returns the CDP target for iframe traversal
// Managing multiple tabs
await browser.openOrReuseTab('https://news.ycombinator.com');
const tabs = await browser.listTabs();
await browser.switchTab(await browser.currentTab());
Supporting Facades
Task Spaces
The taskSpaces facade manages isolated task‑space lifecycles, allowing agents to create sandboxed sessions. It exposes list, switch, new, useOrCreate, claim, complete, handOff, takeOver, and waitForAgentControl for ownership and state management.
const space = await taskSpaces.useOrCreate('my-session');
await space.claim(); // Take ownership if user-owned
await taskSpaces.complete(space.id, { keep: true });
Site Skills and Fetch
The site facade provides access to learned automation skills via skills, skillsForUrl, and runTool, enabling agents to execute predefined workflows for specific domains. The fetch facade offers dual interfaces—fetch.server for server‑side requests and fetch.browser for browser‑origin network calls—abstracting HTTP concerns away from CDP details.
Direct CDP Access
For scenarios requiring protocol‑level control, the cdp facade (exported from src/cdp-eval.ts) exposes a direct command dispatcher, allowing raw CDP message construction while maintaining the context’s structural benefits.
Architecture Flow: From CDP to Agent
The helper context architecture follows a layered delegation pattern:
-
Low‑level drivers (
src/driver/nav.ts,src/driver/pointer.ts,src/driver/keyboard.ts,src/driver/locator.ts) interact directly with the CDP bridge viaego.sendCDPMessage. -
Higher‑level helpers (
src/helpers.ts) compose these drivers into coherent facades that group related operations by domain (page interaction vs. tab management). -
helperContextbundles the facades with rawcdpaccess, optional custom helpers, and documentation utilities. -
Runtime injection (
src/run.ts) places this context into the agent’s execution scope, presenting a unified,Playwright‑style surface while keeping CDP complexity encapsulated.
Summary
-
The helper context in
src/helpers.tsacts as the central factory, assembling six specialized facades into a single object for agent consumption. -
Page facade (
createPageFacade) wraps navigation drivers and the locator system to provide auto‑awaiting element interaction and screenshots. -
Browser facade (
createBrowserFacade) exposes tab management primitives fromsrc/driver/nav.tsfor multi‑tab workflows. -
Supporting facades handle task isolation (
taskSpaces), learned automation (site), network requests (fetch), and raw protocol access (cdp). -
All operations route through low‑level drivers that communicate via CDP, ensuring the agent API remains stable while underlying protocol details stay isolated.
Frequently Asked Questions
What is the difference between the page and browser facades in ego-browser?
The page facade focuses on document‑level interactions within the current tab—navigation, element location via getBy* methods, and input actions—while the browser facade handles tab‑level control such as opening new tabs, switching contexts, and listing available targets. Use page for manipulating content and browser for managing windows and tabs.
How does the helper context handle element waiting and timeout configuration?
The helper context implements auto‑awaiting at the driver level, particularly within the locator system in src/driver/locator.ts. When you call methods like click() or fill() on a locator, it automatically waits for the element to become stable and actionable. You can adjust global timeout behavior using page.setDefaultTimeout(), which updates the shared state.defaultTimeout variable accessed by all waiting operations.
What are task spaces and when should agents use them?
Task spaces are isolated execution environments managed by the taskSpaces facade (lines 85‑97 in src/helpers.ts). Agents should use them when performing multi‑step workflows that require state isolation, ownership handoff between agents, or cleanup guarantees. Methods like claim() and handOff() manage concurrent access, ensuring that only one agent controls a specific task space at a time.
Can I extend the helper context with custom functionality?
Yes. The helperContext function accepts an extra parameter (defaulting to an empty object) that spreads into the final context object. Pass custom utilities or domain‑specific helpers when initializing the context, and they will be available alongside the built‑in facades. The help() method also indexes these extra helpers if they include JSDoc comments, making custom extensions discoverable to agents.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →