# How Task Spaces Work in ego-lite: Ownership Model and Control Flow Explained

> Discover how ego-lite task spaces provide isolated browser contexts with clear agent or user ownership. Understand control flow and ownership models for secure cross-party transfers.

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

---

**Task spaces in ego-lite are isolated browser contexts with a strict ownership model where spaces are either `agent`-owned (AI-controlled) or `user`-owned (human-controlled), requiring explicit claims before cross-party control transfers.**

ego-lite divides browsing work into independent units called **task spaces**. Each space operates as its own browser context, complete with cookies, storage, and state. Understanding how these spaces function and who controls them is essential for building reliable automation workflows. This guide examines the ownership model, control methods, and runtime enforcement based on the actual source implementation in `citrolabs/ego-lite`.

## What Are Task Spaces?

A **task space** is a named, isolated browsing environment within ego-lite. Spaces can be created, selected, transferred between parties, and terminated. The `taskSpaces` facade—implemented in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) and documented in [`src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/format.ts)—provides the primary interface for JavaScript code.

Unlike shared browser sessions, task spaces enforce clear boundaries. Each space receives a numeric ID and carries metadata including its name and ownership status.

## The Ownership Model: Agent vs. User

Every task space carries an **`ownership` flag** with two possible values:

| Ownership | Controller | Permissions |
|-----------|-----------|-------------|
| **`agent`** | AI autonomous agent | Full control: `switch`, `claim`, `handOff`, `takeOver`, `complete` |
| **`user`** | Human end user | Blocks agent actions until explicitly claimed |

This binary model prevents accidental conflicts. When the agent creates a space via `newTaskSpace()`, it receives `agent` ownership automatically. Spaces created through other flows may default to `user` ownership, requiring explicit takeover.

## Core Task Space Operations

The `taskSpaces` facade exposes eight primary methods. Each enforces ownership rules through the runtime's task-space manager.

### Creating and Selecting Spaces

**`newTaskSpace(name)`** creates a fresh space with automatic selection:

```javascript
const task = await taskSpaces.new('research-task')
// Returns: { id: 5, name: 'research-task', ownership: 'agent' }
// The new space is immediately active

```

The underlying implementation calls `ego.createTaskSpace`, validates the response through `taskSpaceNumericId`, and sets the new space as current.

**`useOrCreate(nameOrId)`** provides idempotent reuse:

```javascript
const task = await taskSpaces.useOrCreate('research-task')

```

This method only matches **agent-owned** spaces. If a user-owned space exists with that name, it will not be automatically selected—the agent must `claim` it first.

### Claiming User-Owned Spaces

**`claim(nameOrId)`** transfers ownership from user to agent:

```javascript
await taskSpaces.claim('user-checkout')
await taskSpaces.switch('user-checkout')

```

Attempting to `switch` directly to a user-owned space without claiming throws an error with guidance directing the user to take control. The claim operation validates the space's numeric ID and updates the ownership flag before permitting further actions.

### Switching Between Spaces

**`switch(nameOrId)`** activates a specified space:

The method fails under two conditions:
- Unknown space ID
- Unclaimed user-owned space

Ownership verification occurs in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) before `ego.useTaskSpace` is invoked.

### Transferring Control

**`handOff(nameOrId?)`** yields control to the user:

```javascript
await taskSpaces.handOff()  // Current space becomes user-owned

```

**`takeOver(nameOrId?)`** regains agent control after hand-off:

```javascript
await taskSpaces.takeOver()

```

**`waitForAgentControl(nameOrId?, options?)`** pauses execution until ownership returns:

```javascript
await taskSpaces.handOff()
await taskSpaces.waitForAgentControl()  // Blocks until user releases
await taskSpaces.takeOver()

```

### Completing Spaces

**`complete(nameOrId, {keep})`** terminates a space:

```javascript
await taskSpaces.complete(task.id, { keep: false })  // Discard
await taskSpaces.complete(task.id, { keep: true })   // Preserve for later

```

## Runtime Enforcement and Error Handling

The task-space manager in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) validates all operations against ownership state. Key enforcement points include:

- `taskSpaceNumericId()` validates numeric IDs and extracts ownership fields
- `claim` and `switch` verify ownership before calling `ego.useTaskSpace`
- Violations surface clear errors defined in [`src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ego-errors.ts)

Error messages specifically guide developers toward correct ownership operations rather than generic failures.

## Testing the Ownership Flow

The end-to-end test suite in `src/taskspace-e2e.test.mjs` validates the complete model:

- Agent-owned spaces work immediately with `useOrCreate`
- User-owned spaces require `claim` before `switch`
- Direct `switch` attempts on user spaces surface guidance messages
- Unknown IDs and binding misuse throw descriptive errors

These tests confirm that the ownership model prevents automation failures while supporting intentional collaboration patterns.

## Summary

- **Task spaces** are isolated browser contexts with unique IDs and metadata
- **Ownership is binary**: `agent` (full AI control) or `user` (human control, requires claim)
- **`new()`** creates agent-owned spaces; **`useOrCreate()`** only matches agent-owned spaces
- **`claim()`** is mandatory before controlling user-owned spaces
- **Hand-offs** use `handOff()`, `waitForAgentControl()`, and `takeOver()` for safe collaboration
- **Runtime enforcement** in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) prevents accidental control violations
- **Clear errors** in [`src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ego-errors.ts) guide correct usage patterns

## Frequently Asked Questions

### What happens if I try to switch to a user-owned task space without claiming it?

The runtime throws an error with guidance directing the user to take control. According to [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts), `switch()` validates ownership before calling `ego.useTaskSpace`, and unclaimed user spaces fail this check with a specific message from [`src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/ego-errors.ts).

### Can two agents share the same task space?

No. The ownership model only recognizes `agent` and `user` as valid states. While multiple agent processes could theoretically interact with the same space ID, the runtime expects single-party control. Use `handOff` and `takeOver` for sequential control transfers rather than concurrent sharing.

### How do I detect if a space is agent-owned or user-owned before switching?

The `taskSpaces` methods abstract ownership checks—you don't manually inspect the flag. Instead, use `useOrCreate` for agent spaces or wrap `claim` attempts in try-catch blocks. The test suite in `src/taskspace-e2e.test.mjs` demonstrates this pattern: claim first, then proceed on success.

### What's the difference between `complete()` with `keep: true` and `keep: false`?

`keep: true` preserves the space's state for potential future reactivation, while `keep: false` discards it entirely. Both operations end the current active session. The space's ownership history does not affect this—completion works regardless of whether the space was agent or user controlled.