# How ego-lite Implements Task Space Isolation for Concurrent Agent Tasks

> Discover how ego-lite achieves task space isolation for concurrent agent tasks. Learn about sandboxed contexts preventing state leakage in parallel automation workflows.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: internals
- Published: 2026-07-30

---

**ego-lite isolates concurrent agent tasks using sandboxed "task spaces"—lightweight browsing contexts that encapsulate separate CDP sessions, DOM snapshots, and event queues—enforced through numeric IDs, strict ownership models, and per-space reference maps that prevent state leakage between parallel automation workflows.**

The citrolabs/ego-lite repository provides a browser automation framework designed for concurrent AI agent operations. Task space isolation ensures that multiple agents can execute simultaneously without sharing browser state, cookies, or DOM node references, with each agent receiving its own dedicated CDP session and isolated browsing context maintained in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts).

## Core Isolation Architecture

### The Task Space Registry

In [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts), ego-lite maintains a singleton registry at `state.taskSpaces` that tracks all active spaces. This registry stores ownership metadata, creation timestamps, and the underlying CDP session for each space, guaranteeing that concurrent agents never share the same `BrowserRuntime` instance.

### Numeric ID System

Every task space receives a stable numeric `id` (e.g., `42`) that persists across execution rounds. This ID-based addressing prevents collisions when multiple agents create spaces simultaneously, while optional human-readable names provide convenience without sacrificing uniqueness or isolation boundaries.

## Ownership and Access Control

### Agent-Owned vs User-Owned Spaces

Task spaces implement a strict ownership model distinguishing between **agent** and **user** control. By default, spaces created through automation are agent-owned, but users can claim browser tabs through `claimTaskSpace()`. Only the current owner may switch to or manipulate a space, preventing accidental hijacking of user-controlled tabs by parallel automation scripts.

### Creating and Reusing Spaces

The `useOrCreateTaskSpace(nameOrId)` function in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) implements a safe reuse pattern: it first attempts to locate an existing agent-owned space matching the identifier, and only creates a fresh context if none exists. This function explicitly avoids auto-claiming user-owned spaces, ensuring that manual browser tabs remain protected from automated takeover.

## Lifecycle and Session Management

### Switching Contexts Safely

The `switchTaskSpace(space)` helper validates ownership before changing the active CDP session. This check ensures agents cannot inject commands into spaces they do not own, maintaining isolation even when agents execute interleaved operations.

### Explicit Teardown with completeTaskSpace

When tasks finish, `completeTaskSpace(nameOrId, { keep })` handles cleanup. The mandatory `keep` parameter forces explicit decisions about tab persistence—setting `keep: true` preserves the tab for debugging, while the default destroys the isolated context and releases associated resources from the registry.

## Reference Isolation and Safety

### Per-Space Reference Maps

In [`src/ref-map.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ref-map.ts), ego-lite maintains separate reference maps for each task space. DOM elements are tracked as backend node IDs (e.g., `@21`, `@22`) that are unique within their space but isolated from other contexts. If an agent attempts to use a reference from a different space, the system triggers an automatic re-snapshot that safely fails rather than leaking state across boundaries.

## Coordination Workflows

### Hand-Off Patterns for Human-in-the-Loop

For interactive scenarios, `handOffTaskSpace()` transfers ownership to the user, while `waitForAgentControl()` pauses the agent until `takeOverTaskSpace()` returns control. In [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts), each space maintains its own CDP transport layer, ensuring that temporary human interactions do not expose other agent spaces to the user session.

## Implementation Examples

**Creating or reusing an agent-owned space:**

```javascript
// Grab an existing space named "order-flow" or create a new one.
const space = await useOrCreateTaskSpace('order-flow');
// The helper automatically ensures the space is owned by the agent.

```

*Source:* [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) – `useOrCreateTaskSpace` implementation.

**Claiming a user-owned space:**

```javascript
// The user previously opened a tab "shopping-cart". The agent now claims it.
const space = await claimTaskSpace('shopping-cart');
// After claiming, the agent can switch to it.
await switchTaskSpace(space);

```

*Source:* [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) – `claimTaskSpace`.

**Handing off to a human user:**

```javascript
await handOffTaskSpace(space);    // User now controls the tab.
await waitForAgentControl(space); // Agent pauses until it gets the tab back.

```

*Source:* [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) – `handOffTaskSpace`, `waitForAgentControl`.

**Completing a task with optional persistence:**

```javascript
// Tear down the space after the task, but keep the tab for debugging.
await completeTaskSpace(space.id, { keep: true });

```

*Source:* [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) – `completeTaskSpace`.

**Safe cross-space reference handling:**

```javascript
// In space A we capture a ref.
const buttonRef = await $(`button=Submit`);   // → @23

// Trying to use @23 in space B triggers an automatic re-snapshot.
await switchTaskSpace(spaceB);
await click(@23);   // Re-snapshot occurs; error if element not present.

```

*Source:* [`src/ref-map.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ref-map.ts) – ref-map lifecycle.

## Summary

- **Sandboxed contexts:** Each task space encapsulates its own CDP session, DOM snapshot, and event queue in [`src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/browser-runtime.ts).
- **Collision prevention:** Numeric IDs and the ownership model in `state.taskSpaces` ensure parallel agents never share browser tabs.
- **Explicit lifecycle:** The `completeTaskSpace` function requires intentional decisions about tab persistence via the mandatory `keep` flag.
- **Reference safety:** Per-space ref maps in [`src/ref-map.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ref-map.ts) isolate backend node IDs, with automatic re-snapshotting preventing cross-space DOM access.
- **Coordinated hand-offs:** The hand-off API enables temporary user control without breaking isolation boundaries between concurrent agent tasks.

## Frequently Asked Questions

### How does ego-lite prevent two agents from controlling the same browser tab?

ego-lite enforces an ownership model where only the current owner (agent or user) can manipulate a task space. The `switchTaskSpace()` function validates ownership before changing contexts, and `useOrCreateTaskSpace()` refuses to auto-claim user-owned spaces, ensuring that parallel agents cannot accidentally share tabs or interfere with manual browsing sessions.

### What happens if an agent uses a DOM reference from another task space?

The reference map system in [`src/ref-map.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ref-map.ts) tracks backend node IDs per space. If an agent attempts to use a reference like `@23` in a space where it was not captured, the system triggers an automatic re-snapshot. This operation fails safely rather than accessing the wrong DOM node, preventing state leakage between isolated contexts.

### Can multiple agents reuse the same task space?

Yes, but only sequentially and only when owned by the agent. The `useOrCreateTaskSpace()` function allows agents to reconnect to their existing spaces using stable numeric IDs or names. However, concurrent access is prohibited by the ownership model—two agents cannot simultaneously switch to the same space, ensuring true isolation during parallel execution.

### How does task space isolation handle user-interactive workflows?

The hand-off API (`handOffTaskSpace`, `takeOverTaskSpace`, `waitForAgentControl`) enables temporary transfers of ownership to users. During hand-off, the agent releases control and pauses execution, ensuring that human interactions occur within the same isolated context without exposing other agent spaces to the user session or allowing interference with automated workflows.