Understanding Task Spaces in ego-lite: Isolated Browsing Contexts for AI Agents
Task spaces in ego-lite are isolated browsing contexts that allow AI agents to manage multiple workflows simultaneously without interference, each maintaining separate tabs, history, and DOM snapshots.
Task spaces serve as the fundamental isolation mechanism in citrolabs/ego-lite, an open-source browser automation framework designed specifically for AI agent orchestration. This core abstraction enables agents to execute concurrent scripts across distinct browsing environments, ensuring that navigation history, DOM state, and tab collections remain segregated between different units of work.
What Are Task Spaces in ego-lite?
Task spaces are containerized browsing contexts that encapsulate all browser state required for a specific workflow. Each space maintains its own set of tabs, navigation history, and DOM snapshots, preventing cross-contamination between concurrent operations. According to the source code in package/ego-browser/src/helpers.ts, the runtime injects a taskSpaces façade into every agent script via helperContext(), providing a unified API for context management.
Core Concepts and Ownership Models
The Task Space Façade
The taskSpaces object exposed to agent scripts bundles all operations needed to manage isolated contexts. The façade is constructed by createTaskSpacesFacade in package/ego-browser/src/helpers.ts and includes methods for creation, switching, completion, and ownership transfer. This design pattern ensures that agents interact with a consistent interface regardless of underlying Chrome DevTools Protocol (CDP) complexity.
Agent-Owned vs User-Owned Spaces
Each task space carries an ownership property that determines operational permissions. Agent-owned spaces can be switched, modified, or completed directly by the running script. User-owned spaces require specific transfer mechanisms before the agent can manipulate them. Ownership transitions are handled through three primary methods: claim, handOff, and takeOver. These checks are enforced via underlying CDP calls, with public API signatures declared in package/ego-browser/src/format.ts (lines ~650-770).
Managing Task Spaces: Key Operations
Creating and Reusing Contexts
The taskSpaces.useOrCreate(nameOrId) method, implemented in package/ego-browser/src/helpers.ts (lines ~885-892), retrieves an existing space by numeric ID or name, or instantiates a new one if no match exists. This atomic operation ensures idempotent context initialization across script reruns.
Once created, taskSpaces.switch(idOrName) activates a specific space, directing subsequent helper calls to operate within that context's tabs and snapshots. The concrete implementation resides in switchTaskSpace at line ~249 of package/ego-browser/src/helpers.ts.
Transferring Control with Handoffs
Collaborative workflows require seamless transitions between automated and manual control. The taskSpaces.handOff(idOrName) method transfers an agent-owned space to a user, while taskSpaces.takeOver(idOrName) reclaims user-owned spaces for agent control. These functions map to handOffTaskSpace and takeOverTaskSpace within the façade.
For step-wise human-in-the-loop processes, taskSpaces.waitForAgentControl(idOrName, options) blocks execution until the agent regains ownership, defined at line ~300 of package/ego-browser/src/helpers.ts. This synchronization primitive enables complex approval workflows without polling overhead.
Completing and Cleaning Up
When a workflow terminates, taskSpaces.complete(idOrName, { keep }) closes the task space. Setting keep: true preserves the space's tabs for future reference, while the default behavior removes all associated resources. This functionality is implemented in completeTaskSpace at line ~292 of package/ego-browser/src/helpers.ts.
Internal Architecture and CDP Integration
Internally, ego-lite represents each task space as a numeric identifier (taskSpaceNumericId) mapped to a dedicated CDP session. This mapping lives in the runtime's shared state (src/state.ts) and refreshes automatically whenever snapshots occur. If a script references a space with an empty mapping, the runtime triggers an automatic re-snapshot via the browser runtime (src/browser-runtime.ts), ensuring reference validity across script rounds.
The CDP transport layer manages session attachment and isolation, guaranteeing that DOM operations in one task space cannot affect another's execution context. This architectural decision provides the reliability required for production AI agents handling multiple concurrent browsing tasks.
Practical Implementation Examples
The following example demonstrates a complete workflow using task spaces in ego-lite:
// Create or reuse a task space called "research"
const research = await taskSpaces.useOrCreate('research');
// → { id: 3, name: 'research', owner: 'agent' }
// Switch to that space so further calls operate within it
await taskSpaces.switch(research.id);
// Open a tab inside the active space
await browser.openOrReuseTab('https://news.ycombinator.com');
// Perform actions on the page
await page.waitForLoadState('networkidle');
const titles = await page.locator('a.storylink').allTextContents();
console.log(titles);
// Hand the space off to a human user for manual inspection
await taskSpaces.handOff(research.id);
// Reclaim control when ready
await taskSpaces.takeOver(research.id);
await taskSpaces.waitForAgentControl(research.id);
// Close the space but keep tabs for later reference
await taskSpaces.complete(research.id, { keep: true });
Summary
- Task spaces in ego-lite provide isolated browsing contexts that segregate tabs, history, and DOM state between different AI agent workflows.
- Ownership models distinguish between agent-controlled and user-controlled spaces, with explicit transfer mechanisms via
handOffandtakeOver. - Core operations include
useOrCreatefor idempotent initialization,switchfor context activation, andcompletefor resource cleanup. - CDP integration ensures robust isolation through numeric ID mapping and automatic session management in
src/state.tsandsrc/browser-runtime.ts. - Human-in-the-loop support via
waitForAgentControlenables sophisticated collaborative automation workflows.
Frequently Asked Questions
How do task spaces prevent interference between concurrent AI agent scripts?
Task spaces maintain completely isolated CDP sessions and DOM snapshots for each context. When an agent switches between spaces using taskSpaces.switch(), the runtime directs all subsequent browser operations to that specific CDP session, ensuring that navigation, element selection, and JavaScript execution remain confined to the active space's tabs and history.
Can multiple task spaces exist simultaneously in ego-lite?
Yes, the runtime supports multiple concurrent task spaces, each identified by a unique numeric ID stored in src/state.ts. Agents can create new spaces with useOrCreate(), switch between them dynamically, and maintain separate browsing sessions indefinitely, limited only by system resources and browser memory constraints.
What happens if a script references a task space that no longer exists?
If the mapping between a task space reference and its CDP session becomes stale, the runtime automatically triggers a re-snapshot mechanism via src/browser-runtime.ts to rebuild the internal state map. This ensures that valid references remain functional across script reruns without manual intervention.
How does ownership transfer work between agents and human users?
Ownership transfer utilizes two primary façade methods: handOff() converts an agent-owned space to user-owned status, while takeOver() reclaims it for the agent. The waitForAgentControl() function provides blocking synchronization, allowing scripts to pause until a user explicitly returns control, facilitating seamless human-in-the-loop automation workflows.
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 →