What Are Ego-Lite Spaces and How Do They Prevent Interference?
Ego-Lite Spaces are logical containers that isolate browser tabs and their state, enforcing strict ownership rules—either "agent" or "user"—to ensure automation code cannot interfere with human-controlled sessions or other concurrent tasks.
Ego-Lite, developed by CitroLabs as an open-source browser automation framework, introduces Task Spaces (commonly called spaces) to solve the fundamental problem of shared browser interference. Each space wraps a single browser tab along with its associated state—including reference maps, snapshots, and Chrome DevTools Protocol (CDP) sessions—creating deterministic boundaries for automation workflows that may involve both scripted agents and human users.
Understanding Task Spaces in Ego-Lite
A Task Space is the fundamental unit of isolation in the Ego-Lite architecture. Rather than operating directly on browser contexts, automation scripts interact with named spaces that encapsulate all tab-specific resources. This design allows multiple automation tasks to coexist within the same browser instance without cross-contamination.
When you invoke taskSpaces.useOrCreate() or taskSpaces.switch(), the framework selects that specific space as the active context. All subsequent helper calls—such as page.goto(), locator.click(), or browser.close()—operate exclusively on the selected space. The underlying native bridge rejects commands targeting different spaces, ensuring that one task cannot inadvertently affect another tab's state.
Ownership Models and Access Control
Every space carries an ownership flag that determines who may issue commands against it. According to the implementation in src/helpers.ts (lines 18‑32), three ownership states exist:
"agent"– The automation script has full control and may execute any command."agentDelegatedToUser"– Initially agent-owned but temporarily shared; the agent retains ownership while allowing user interaction."user"– The human user currently controls the tab; the agent is restricted to read-only or polling operations.
This ownership model is enforced by the Task-Space Façade created via createTaskSpacesFacade in src/helpers.ts. The façade methods validate ownership before delegating to native ego APIs such as ego.createTaskSpace, ego.useTaskSpace, and ego.claimTaskSpace.
Agent-Only Actions and Protective Errors
When the agent attempts actions like switchTaskSpace, newTaskSpace, or claimTaskSpace on a user-owned space, the façade throws an error immediately. As implemented in lines 52‑63 of src/helpers.ts, the switch method checks ownership before proceeding, preventing the agent from hijacking a user's active session.
If the agent attempts to mutate a user-owned space through lower-level commands, the native bridge raises the EGO_TASK_SPACE_USER_IN_CONTROL error (defined in src/ego-errors.ts). The helpers translate this into a safe, high-level exception rather than allowing accidental page mutations.
How Spaces Prevent Interference
The interference prevention mechanism operates at multiple layers, from the JavaScript façade down to the native browser bridge.
Command Isolation via the Native Bridge
Once a space is selected through taskSpaces.useOrCreate(nameOrId), all subsequent helper invocations are scoped to that space. The native bridge maintains this context and rejects cross-space commands. This ensures that even if multiple automation scripts run concurrently, each operates within its own sandboxed tab environment.
Ownership Validation in the Task-Space Façade
The façade enforces ownership rules through explicit checks before executing sensitive operations:
- Hand-off operations (
handOffTaskSpace) are silently skipped if the space is already user-owned, avoiding unnecessary errors when the user already has control. - Completion (
complete) verifies agent ownership before closing spaces, as shown in lines 66‑73 ofsrc/helpers.ts. - Claiming a user-owned space (lines 24‑28) requires explicit takeover logic that respects the current user's session.
Safe Hand-Off and Takeover Patterns
To facilitate human-in-the-loop workflows, Ego-Lite provides waitForAgentControl, which polls a harmless snapshot until the agent regains ownership (lines 77‑84). This prevents busy-loops and guarantees that automation only proceeds when it truly owns the space, eliminating race conditions between user input and script execution.
Working with Task Spaces: Code Examples
The following examples demonstrate practical patterns for creating isolated spaces and managing ownership transitions without interference.
// Create (or reuse) a space for a research task
const task = await taskSpaces.useOrCreate('research-task');
// The agent now owns `task.id` and all subsequent calls target this tab
await page.goto('https://news.ycombinator.com');
// Hand the space back to the user for review (no interference)
await taskSpaces.handOff(task.id); // Skips if already user-owned
// Later the agent can retake control
await taskSpaces.takeOver(task.id);
await page.locator('text=Ask HN').click();
// When done, close the space (agent-owned) or keep it open for the user
await taskSpaces.complete(task.id, { keep: false });
// Detect whether the agent currently has control before proceeding
try {
await taskSpaces.waitForAgentControl(task.id, { timeout: 120 });
// Safe to run automation now
await page.click('#submit');
} catch (e) {
console.error('Agent never regained control:', e);
}
Core Implementation Details
The interference prevention logic resides primarily in src/helpers.ts, where the createTaskSpacesFacade function builds the public API. Key implementation points include:
- Ownership policy validation (lines 18‑32): Establishes the three-state ownership model and initial checks.
- Switching guards (lines 52‑63): Ensures
switchoperations only proceed when the agent owns the target space. - Claiming logic (lines 24‑28): Handles transitions from user-owned to agent-owned states.
- Completion safety (lines 66‑73): Validates ownership before destroying space resources.
- Control polling (lines 77‑84): Implements
waitForAgentControlusing safe snapshot polling.
Supporting files include src/ego-errors.ts, which defines the EGO_TASK_SPACE_USER_IN_CONTROL constant used throughout the façade, and src/taskspace-e2e.test.mjs, which contains end-to-end tests verifying isolation behavior. Public API signatures are documented in src/format.ts for integration with the help() system.
Summary
- Task Spaces are logical containers in Ego-Lite that isolate browser tabs, state, and CDP sessions to prevent cross-task contamination.
- Ownership flags (
agent,agentDelegatedToUser,user) enforce strict access control, ensuring agents cannot mutate user-controlled pages. - The Task-Space Façade in
src/helpers.tsvalidates all operations, throwing errors or skipping actions that would violate ownership rules. - Native bridge integration rejects cross-space commands and raises
EGO_TASK_SPACE_USER_IN_CONTROLwhen agents attempt unauthorized mutations. waitForAgentControlprovides safe polling mechanisms for agents to resume work only after regaining ownership from users.
Frequently Asked Questions
Can multiple agents control the same space simultaneously?
No. Ego-Lite enforces single-owner semantics through the ownership flag system. While multiple agents might exist in the same browser instance, only the entity holding the current ownership token—either an agent or the user—may issue mutating commands to a specific space. Other agents attempting to access that space will encounter ownership validation errors from the façade.
What happens if an agent tries to click while the user is actively browsing?
The native bridge raises the EGO_TASK_SPACE_USER_IN_CONTROL error, which the helpers in src/helpers.ts translate into a high-level exception. The click command is blocked before reaching the browser's CDP layer, ensuring the user's interactions remain uninterrupted. Agents should use waitForAgentControl to poll for ownership recovery before attempting mutations.
How do I safely transition a task from automation to human review?
Use taskSpaces.handOff(task.id) to transfer ownership to the user. This method safely skips if the space is already user-owned, preventing redundant errors. The agent can later reclaim control via taskSpaces.takeOver(task.id) once the user has finished reviewing, enabling seamless human-in-the-loop workflows without data loss or state corruption.
Where is the space isolation logic implemented in the source code?
The core isolation and ownership logic lives in package/ego-browser/src/helpers.ts within the createTaskSpacesFacade function. This file contains the ownership validation checks (lines 18‑32, 52‑63), the claiming logic (lines 24‑28), and the safe polling mechanism for agent control (lines 77‑84). Error definitions reside in src/ego-errors.ts, while integration tests are available in src/taskspace-e2e.test.mjs.
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 →