# How to Manage Isolated Browser Contexts Using Task Spaces in ego-lite

> Learn to manage isolated browser contexts with ego-lite task spaces. Group tabs, snapshots, and UI state for seamless agent control and ownership management in browser automation.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-21

---

**ego-lite isolates browser automation into independent task spaces that group tabs, snapshots, and UI state, allowing agents to create, switch, claim, hand off, and close contexts while enforcing strict ownership boundaries between agent and user control.**

Developers building browser automation with citrolabs/ego-lite can manage isolated browser contexts through a powerful task space abstraction. Each task space acts as an independent container for browser state, enabling safe context switching and clear control boundaries between autonomous agents and human users. This guide explains how to use the task space API implemented in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) to manage these lifecycle operations effectively.

## What Are Task Spaces?

A **task space** is an isolated browser context that encapsulates a set of tabs, snapshots, and UI state. According to the ego-lite source code, each space exists as an independent context that the runtime tracks with specific ownership metadata. The ownership model defines who controls the space: `agent` (full agent control), `agentDelegatedToUser` (agent lent control to user), or `user` (original user ownership).

This isolation ensures that CDP (Chrome DevTools Protocol) commands execute within a bounded environment, preventing accidental interference with other automation tasks or user browsing sessions.

## Core Task Space Operations

### Listing Existing Spaces

To retrieve all task spaces with their metadata, the runtime exposes `listTaskSpaces()` in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) at line 107. This helper reads from the internal `ego.listTaskSpaces` bridge and normalizes the result for agent consumption.

```javascript
const spaces = await taskSpaces.list();
console.log(spaces);

/* Output:
[
  { taskId: "t1", id: 1, name: "research", ownership: "agent", recentTabTitles: [...] },
  { taskId: "t2", id: 2, name: "checkout", ownership: "user", recentTabTitles: [...] }
]
*/

```

### Creating and Switching Spaces

Agents create new isolated contexts using `newTaskSpace(name)`, implemented at line 71 of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts). This function calls `ego.createTaskSpace` and immediately selects the new space for the current invocation.

To activate an existing agent-owned space, use `switchTaskSpace(nameOrId)` at line 52, which validates ownership through the `isAgentOwned` helper before invoking `ego.useTaskSpace`.

```javascript
// Create a new agent-owned space and switch to it
const mySpace = await taskSpaces.new("my-analysis");
console.log(`Using space ${mySpace.id}`);

// Switch to an existing space
await taskSpaces.switch("research");

```

For idempotent automation, `useOrCreateTaskSpace(nameOrId)` at line 86 implements a "use-or-create" pattern. It queries existing spaces via `listTaskSpaces` and either selects a match or creates a new one. Notably, if the existing space is user-owned, the helper only selects it without claiming ownership.

```javascript
// Reuse existing space or create if missing
const space = await taskSpaces.useOrCreate("checkout-flow");
// User-owned spaces are selected, not claimed

```

### Claiming User-Owned Spaces

When an agent needs to execute privileged CDP commands on a user-owned space, it must transfer ownership first. The `claimTaskSpace(nameOrId)` function at line 24 (which delegates to `claimResolvedTaskSpace`) transfers ownership from `user` to `agent`.

The ownership policy, encoded in `isAgentOwned` at lines 43-45, governs which operations are permitted. Only spaces marked as `agent` or `agentDelegatedToUser` allow full automation; attempting unauthorized actions on `user`-owned spaces raises errors defined in [`src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ego-errors.ts).

```javascript
// Claim a user-owned space before running privileged actions
await taskSpaces.claim("checkout-flow");
await taskSpaces.switch("checkout-flow"); 
// Now safe to run CDP commands like click, goto, etc.

```

## Managing Control Transitions

### Handing Off to Users

The `handOffTaskSpace(nameOrId?)` function at line 26 returns control to the human user by hiding the agent overlay. This operation skips user-owned spaces because the user already possesses control. After handing off, the agent can no longer execute browser commands until it regains control.

```javascript
// Return control to the user after completing a step
await taskSpaces.handOff("checkout-flow");
// Agent overlay hidden; user can interact directly

```

### Taking Over and Waiting for Control

To resume work after a hand-off, agents invoke `takeOverTaskSpace(nameOrId?)` at line 47. This re-shows the agent overlay and restores the automation context without performing ownership checks.

When an agent needs to wait for control restoration (for example, after requesting user input), `waitForAgentControl(nameOrId, options?)` at line 84 polls the runtime until ownership returns to the agent. This is particularly useful in workflows requiring human verification between automation steps.

```javascript
// Resume automation
await taskSpaces.takeOver();

// Poll until agent regains control (timeout in milliseconds)
await taskSpaces.waitForAgentControl("checkout-flow", { timeout: 300 });

```

### Completing and Closing Spaces

The `completeTaskSpace(nameOrId, {keep})` function at line 74 finalizes a task space. Passing `keep: false` closes the space entirely, while `keep: true` simply dismisses the agent overlay while preserving the browser context. According to the implementation, user-owned spaces are never closed automatically, ensuring user data preservation.

```javascript
// Close space and discard context
await taskSpaces.complete("my-analysis", { keep: false });

// Keep space alive but end agent session
await taskSpaces.complete("research", { keep: true });

```

## Ownership Safety and Error Handling

The runtime enforces strict boundaries through the ownership model defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts). The `isAgentOwned` check (lines 43-45) ensures that agents cannot inadvertently modify user-owned spaces without explicit claiming. When violations occur, error utilities in [`src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ego-errors.ts) surface descriptive messages explaining the control boundary violation.

All task-space helpers are automatically injected into the agent's script context via `helperContext()`, with public signatures documented in [`src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/format.ts) (line 653) for the built-in `help()` system. End-to-end tests in `src/taskspace-e2e.test.mjs` validate the correctness of creation, switching, hand-off, and takeover flows.

## Summary

- **Task spaces** isolate browser state (tabs, snapshots, UI) into independent contexts with tracked ownership.
- **Creation and switching** use `newTaskSpace()` and `switchTaskSpace()` in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts), with `useOrCreateTaskSpace()` providing idempotent access.
- **Ownership boundaries** enforced by `isAgent Owned` prevent unauthorized actions on user-owned spaces; use `claimTaskSpace()` to transfer control.
- **Control transitions** utilize `handOffTaskSpace()` to return control to users and `takeOverTaskSpace()` to resume agent automation.
- **Lifecycle management** completes with `completeTaskSpace()`, which optionally persists or destroys the isolated context based on the `keep` parameter.

## Frequently Asked Questions

### What is the difference between switching and claiming a task space?

Switching (`switchTaskSpace`) activates an existing space only if the agent already owns it (`agent` or `agentDelegatedToUser` status). Claiming (`claimTaskSpace`) transfers ownership from a `user` to the `agent`, enabling privileged CDP operations. Attempting to switch to a user-owned space without claiming it first results in an ownership error from the runtime.

### How do I persist a task space after the agent finishes working?

Use `completeTaskSpace(nameOrId, { keep: true })` to dismiss the agent overlay while maintaining the browser context. This preserves all tabs and state for later user interaction or subsequent agent sessions. The space remains accessible in the task space list and can be reclaimed or switched to later.

### Can multiple agents control the same task space simultaneously?

No, the ownership model enforces single-controller semantics. A task space can only be actively controlled by one party at a time: either the `agent` (automation), `agentDelegatedToUser` (agent lent control), or `user` (original human control). Concurrent access attempts are blocked by the ownership validation logic in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

### What happens to browser tabs when I hand off a task space to a user?

The browser tabs and all page state remain intact and visible to the user. The `handOffTaskSpace()` operation only hides the agent overlay UI; it does not close, refresh, or modify any tab content. The user gains immediate interactive control over the same browsing session the agent was using.