How ego-lite Enables Parallel Execution for AI Agents and Human Users in a Browser
TLDR: ego-lite achieves parallel execution for AI agents and human users in a browser by isolating each actor inside its own task space, a lightweight container that owns a dedicated CDP session, snapshot map, and DOM references, so concurrent agents never share state or collide.
The citrolabs/ego-lite repository provides an open-source runtime for browser automation that supports multiple AI agents — and human operators — working simultaneously inside the same browser process. Its design centers on the task space abstraction found in package/ego-browser/src/helpers.ts, which gives every actor an isolated execution context. This article explains how task-space isolation, session swapping, and resource-safe concurrency combine to deliver genuine parallel execution for AI agents and human users in a browser.
The Task Space Architecture: Foundation of Parallel Execution
A task space is a lightweight container that owns a dedicated Chrome DevTools Protocol (CDP) session, a snapshot map, and a set of DOM references. Because each space tracks its own state independently, multiple agents can run side-by-side without overwriting each other's page data, DOM snapshots, or navigation history.
Task-Space Ownership Flags
Every task space carries an ownership flag that determines what actions are allowed inside it:
agent— The space is controlled exclusively by an AI agent.agentDelegatedToUser— The agent has temporarily handed control to a human.user— A human operator owns the space; the agent must claim it before acting.
The helpers in helpers.ts enforce these flags at runtime. Only agent-owned spaces allow direct browser actions. If an agent attempts to execute a command inside a user-owned space, the runtime throws an EGO_TASK_SPACE_USER_IN_CONTROL error — preventing the agent from unintentionally interfering with a human user mid-session.
Session Isolation Through useTaskSpace
When an agent selects a task space, the runtime swaps the underlying CDP session to the one owned by that space. The browser-runtime.ts layer binds the active task space to its corresponding CDP transport, so every subsequent command — click, navigate, evaluate — operates against that isolated session.
This design means parallel agents never share the same page, DOM snapshot, or navigation stack. Two agents working simultaneously on different task spaces can even interact with two different tabs, pages, or websites without any data leak between them.
Concurrent Resource Safety for Parallel Execution
Parallel execution in a single browser process introduces resource-collision risks, primarily around shared files and global state. ego-lite addresses both.
Sequenced Screenshot Files
Temporary screenshot resources are made unique per process and per task-space operation. In observe.ts, the screenshot implementation constructs a filename from the process ID and a monotonically increasing sequence number:
ego-browser-shot-${process.pid}-${++screenshotSeq}.png
Because the PID and sequence number are both guaranteed unique at runtime, two parallel agents can never overwrite each other's screenshot output — a common source of corruption in naive concurrency implementations.
Scoped Shared-State Singleton
The runtime's global state object in state.ts stores the current task-space ID, environment configuration, and a small set of helper caches. Critically, each agent's code runs in its own Node invocation, which scopes the singleton to that invocation. Parallel runs therefore keep their state fully isolated — there is no shared mutable global across agents.
The Parallel Execution API
The public helper functions in helpers.ts provide a deterministic lifecycle for creating, claiming, and disposing task spaces:
newTaskSpace— Create a new agent-owned space.useOrCreateTaskSpace— Select an existing space or create one.claimTaskSpace— Take ownership of a space currently owned by a user.switchTaskSpace— Switch the active CDP session to a different space.completeTaskSpace— Clean up and release a space.handOffTaskSpace— Temporarily hand control to a human user.takeOverTaskSpace— Regain control from a human user.
Example: Running an Agent in Its Own Space
// Create an agent-owned task space and start working in it
const space = await ego.newTaskSpace('agent-checkout-1');
await ego.navigate('https://example.com/shop');
await ego.click('button=Add to cart');
await ego.screenshot(); // Writes ego-browser-shot-<pid>-<seq>.png
// Switch to a previously created space (agent-owned)
await ego.switchTaskSpace('agent-checkout-1');
// Hand the space to a human user for review, then take it back
await ego.handOffTaskSpace('agent-checkout-1'); // UI shows user overlay
await ego.takeOverTaskSpace('agent-checkout-1'); // Agent regains control
Example: Collaborating with a Human-Controlled Space
// Human-owned space: the agent can read but must claim before acting
await ego.useOrCreateTaskSpace('user-session-42'); // selects user space
// Attempting a click now throws EGO_TASK_SPACE_USER_IN_CONTROL
// Claim it first:
await ego.claimTaskSpace('user-session-42');
await ego.click('button=Proceed');
This human-agent handoff is what enables hybrid workflows — an agent performs the bulk of a task, then hands the space to a human for approval or fine-tuning, then takes it back. No context is lost and no state collisions occur during the transfer.
Key Files That Power Parallel Execution
| File | Role |
|---|---|
| helpers.ts | Core task-space helpers (newTaskSpace, switchTaskSpace, claimTaskSpace, handoff functions) |
| observe.ts | Screenshot logic with per-process sequencing to avoid file overwrites |
| state.ts | Global mutable runtime state that tracks active task space and environment config |
| browser-runtime.ts | CDP transport layer that binds a task space to its isolated session |
| env.ts | Resolves the agent workspace and loads environment variables for each space |
Together, these components give ego-lite the ability to run many AI agents — or a mix of agents and humans — concurrently inside a single browser process, while preserving safety, isolation, and a clean developer-facing API.
Summary
- Task spaces are the isolation boundary — each task space owns its CDP session, snapshot map, and DOM references, so agents never share page state.
- Ownership flags enforce safety —
agent,agentDelegatedToUser, anduserflags dictate who can execute browser actions; violations raiseEGO_TASK_SPACE_USER_IN_CONTROL. - Session swapping is deterministic —
useTaskSpaceandswitchTaskSpaceredirect all subsequent commands to the correct CDP session. - Resource collisions are prevented — screenshots use pid-based sequential filenames and the global state singleton is scoped per Node invocation.
- Human-agent handoffs are built-in —
handOffTaskSpace/takeOverTaskSpaceallow seamless collaboration without losing state.
Frequently Asked Questions
How does ego-lite prevent race conditions between parallel AI agents?
Each agent runs inside an isolated task space with its own CDP session and state snapshot. Because commands act only on the active task space's session, there is no shared mutable state between agents. Screenshots are also uniquely named per process and operation, so concurrent agents cannot overwrite each other's files.
Can a human user and an AI agent work on the same task space simultaneously?
Not simultaneously — but sequentially handoff-friendly. A space can be delegated from agent to user (handOffTaskSpace) and back (takeOverTaskSpace). The agent must claimTaskSpace before running browser actions inside a user-owned space, otherwise the runtime raises the EGO_TASK_SPACE_USER_IN_CONTROL error.
What happens if an AI agent tries to run a command in a human-owned task space?
In helpers.ts, the ownership check raises the EGO_TASK_SPACE_USER_IN_CONTROL error, preventing the action entirely. The agent must first call claimTaskSpace to take ownership before executing click, navigate, evaluate, or any other browser action.
Which files in ego-lite are responsible for task-space parallel execution?
The main implementations live in package/ego-browser/src/helpers.ts (task-space lifecycle functions), package/ego-browser/src/browser-runtime.ts (CDP session binding), package/ego-browser/src/state.ts (per-invocation global state), and package/ego-browser/src/driver/observe.ts (collision-safe screenshot logic).
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 →