Task Spaces in ego-lite: Isolated Browsing Contexts for Safe Agent Control
Task spaces in ego-lite are isolated browsing contexts that keep interactive jobs separate and safely managed, each identified by a numeric ID and optional name with strict ownership rules governing agent access.
Task spaces form the core isolation mechanism in the citrolabs/ego-lite browser automation framework. Each space represents a distinct browsing context that prevents cross-contamination between automated tasks. Understanding how to create, claim, and manage these spaces is essential for building robust agent workflows that handle both autonomous and user-interactive scenarios.
What Are Task Spaces in ego-lite?
Task spaces in ego-lite provide isolated environments where automated agents can perform web interactions without interfering with each other. Each space carries a unique numeric id and an optional name (referred to as taskId in the API), allowing developers to reference specific contexts either numerically or semantically.
The runtime maintains strict metadata for every space, including its createdBy field, ownership status, and recentTabTitles. These properties enable the system to track who controls the browsing session and what content is currently active.
Task Space Ownership Model
Every task space operates under one of two ownership modes that dictate who can perform actions:
- agent: Created by the ego-lite agent itself. The agent retains full authority to select, switch, and control the space without restrictions.
- user: Created or seized by the end-user (human). When a space has user ownership, the agent must claim it before performing any automated actions.
- other: Any ownership value outside these two categories triggers an error condition.
This ownership model prevents agents from accidentally interrupting active user sessions while enabling seamless handoffs between automated and manual control.
How to Use Task Spaces in ego-lite
The public API surface for task-space operations resides in src/helpers.ts, where the façade is constructed and injected into user scripts via helperContext(). All methods are asynchronous and return plain objects containing the space's id, taskId, name, createdBy, ownership, and recentTabTitles.
Listing and Creating Task Spaces
To view existing contexts or initialize new ones, use the listing and factory methods:
// List all available spaces
const spaces = await taskSpaces.list();
// Create a new agent-owned space
const newSpace = await taskSpaces.new('checkout-flow');
// Reuse existing or create if missing (creates agent-owned)
const task = await taskSpaces.useOrCreate('checkout-flow');
// Returns: { taskId: 'checkout-flow', id: 1, name: 'checkout-flow', ... }
Switching Between Task Spaces
Agents can only switch contexts for spaces they own. The switch method accepts the numeric ID:
// Switch to an existing agent-owned space
await taskSpaces.switch(7);
Attempting to switch to a user-owned space without claiming it first results in an error.
Claiming User-Owned Spaces
When a user creates a space or takes control via handOff, the agent must explicitly claim control:
// Claim a space by name or ID before using it
const claimed = await taskSpaces.claim('checkout-flow');
// Now ownership transfers to agent
The claim method is the only way to convert a user-owned space to agent ownership.
Completing and Handing Off Control
Task spaces persist until explicitly completed. Use complete to close them, or handOff to transfer control to the user:
// Give control back to the user
await taskSpaces.handOff(task.id);
// Wait until agent regains control
await taskSpaces.waitForAgentControl(task.id, { timeout: 30000 });
// Take back control from user
await taskSpaces.takeOver(task.id);
// Close the space (keep: false closes the tab)
await taskSpaces.complete(task.id, { keep: false });
Complete Code Examples
The following patterns from src/taskspace-e2e.test.mjs demonstrate the full lifecycle:
// 1️⃣ Create (or reuse) a task space and select it
const task = await taskSpaces.useOrCreate('checkout-flow');
console.log('Selected space id:', task.id);
// 2️⃣ Claim a user-owned space before using it
const claimed = await taskSpaces.claim('checkout-flow');
console.log('Now agent-owned:', claimed);
// 3️⃣ Switch to an existing agent-owned space by numeric id
await taskSpaces.switch(7);
// 4️⃣ Hand off the space to the user (so the user can take over)
await taskSpaces.handOff(task.id);
// 5️⃣ Later, take back control
await taskSpaces.takeOver(task.id);
// 6️⃣ Finish the task space (optionally keep the browser tab)
await taskSpaces.complete(task.id, { keep: false });
Error Handling and Edge Cases
When an agent attempts to interact with a user-owned space without claiming it, the runtime returns error code EGO_TASK_SPACE_USER_IN_CONTROL. As defined in src/ego-errors.ts, this error triggers a helpful guidance message on the agent surface rather than exposing raw native errors to end users.
The end-to-end tests in src/taskspace-e2e.test.mjs validate these error conditions, ensuring that the ownership model correctly prevents unauthorized agent actions while providing clear remediation paths.
Implementation Details
The taskSpaces façade is constructed in src/helpers.ts (lines 815-819) and exposed to automation scripts through helperContext(). This architecture keeps the implementation details separate from the public API while providing consistent access to space management functions across the runtime.
Summary
- Task spaces in ego-lite provide isolated browsing contexts identified by numeric IDs and optional names.
- The ownership model distinguishes between agent and user control, requiring explicit claims for the latter.
- Core operations include
useOrCreate,claim,switch,handOff,takeOver, andcomplete. - Attempting to use user-owned spaces without claiming them triggers
EGO_TASK_SPACE_USER_IN_CONTROLerrors. - The API façade resides in
src/helpers.tsand is injected viahelperContext().
Frequently Asked Questions
What is the difference between a task space ID and taskId?
The id is a numeric identifier assigned by the runtime, while taskId (also called name) is an optional string label you provide when creating the space. You can reference spaces by either the numeric ID in methods like switch() or by the string name in methods like claim() or useOrCreate().
How do I handle the EGO_TASK_SPACE_USER_IN_CONTROL error?
When you encounter error code EGO_TASK_SPACE_USER_IN_CONTROL, call await taskSpaces.claim(idOrName) to transfer ownership from the user to the agent. This error prevents agents from interrupting active user sessions, ensuring safe collaboration between human and automated control.
Can multiple agents control the same task space simultaneously?
No. Task spaces enforce single-controller semantics based on the ownership field. Only one entity—either an agent or a user—can actively control a space at any time. Use handOff and takeOver to pass control back and forth between parties.
Where is the taskSpaces API defined in the source code?
The API is defined in src/helpers.ts where the façade object is constructed and injected into scripts via helperContext(). Error codes like EGO_TASK_SPACE_USER_IN_CONTROL are defined in src/ego-errors.ts, and usage examples appear 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 →