# Understanding the Ownership Model for Task Spaces in Ego-Lite

> Explore Ego-Lite's strict three-tier ownership model agent, agentDelegatedToUser, and user to prevent unauthorized mutations in isolated browser automation contexts.

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

---

**Ego-Lite enforces a strict three-tier ownership policy—`agent`, `agentDelegatedToUser`, and `user`—to prevent unauthorized mutations across isolated browser automation contexts.**

Ego-Lite is a browser automation SDK that runs each script inside a **task space**, a short-lived, isolated browsing context with its own tabs, snapshots, and Chrome DevTools Protocol (CDP) session. The **ownership model for task spaces in ego-lite** governs which entities can create, modify, or transfer these contexts, ensuring that agent-controlled automation never accidentally interferes with user-owned browsing sessions.

## What Are Task Spaces in Ego-Lite?

A **task space** is the fundamental isolation primitive in ego-lite. Each space maintains:

- An independent set of browser tabs
- Dedicated CDP sessions
- Scoped snapshots and state

The isolation is enforced by the native bridge (the closed-source ego-lite app), while the JavaScript SDK exposes a *task-space façade* under the global `taskSpaces` object. This façade allows agents to create, select, and manage spaces while respecting the ownership policy defined in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts).

## The Three-Tier Ownership Policy

The SDK defines three distinct ownership values, documented in the ownership policy comment at lines [18-30](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L18-L30) of [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts):

### `"agent"`

Created by the automation agent and fully owned by it. The agent can mutate, switch, and close these spaces without restrictions.

### `"agentDelegatedToUser"`

Created by the agent but temporarily handed over to the user, typically after a hand-off operation. The agent retains creation rights but defers control to the user until reclaimed.

### `"user"`

Created by the end-user and wholly owned by them. Agents cannot mutate these spaces without explicitly claiming ownership first.

## Ownership Enforcement in src/helpers.ts

The core enforcement logic resides in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts). The helper `isAgentOwned` (lines [43-45](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L43-L45)) checks ownership before mutating operations:

```typescript
// Pseudomorphic representation of the ownership guard
function isAgentOwned(space): boolean {
  return space.ownership === 'agent' || space.ownership === 'agentDelegatedToUser';
}

```

Mutating functions like `switchTaskSpace` implement strict guards. At lines [57-62](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L57-L62), the function throws an error if the target space is not agent-owned, preventing accidental context switches into user-controlled environments.

Conversely, read-only functions such as `waitForAgentControl` and `takeOverTaskSpace` ignore ownership checks because they do not alter state.

## Task Space Lifecycle and Ownership Transfers

The SDK provides specific methods for navigating the ownership model programmatically. These are exposed through the `taskSpaces` façade registered in [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts) (lines [119-133](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/index.ts#L119-L133) within the `LEGACY_GLOBAL_HELPERS` list).

### Creating Agent-Owned Spaces

Use `new()` to create a space with `"agent"` ownership and immediately select it:

```typescript
// Creates and switches to an agent-owned task space
await taskSpaces.new('myAgentSpace');

```

### Claiming User-Owned Spaces

When an agent needs to take control of a user-created space, it must explicitly claim ownership. The `claimTaskSpace` implementation (lines [24-27](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L24-L27)) transfers ownership from `"user"` to `"agent"` before selection:

```typescript
// Attempting to use a potentially user-owned space
await taskSpaces.useOrCreate('maybeUserSpace');

// If ownership is "user", claim it before mutating
await taskSpaces.claim('maybeUserSpace');

```

The `useOrCreateTaskSpace` helper (lines [94-110](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L94-L110)) handles this gracefully: if the space exists but is user-owned, it returns a user-control error rather than crashing, prompting the developer to call `claim`.

### Handing Off Control

To return control to the user without closing the session, use `handOff()`. This transitions ownership to `"agentDelegatedToUser"` or `"user"`, skipping user-owned spaces automatically:

```typescript
// Release control back to the user
await taskSpaces.handOff();

```

### Completing and Cleaning Up

Always close task spaces after automation completes to free CDP resources:

```typescript
// Close the task space and remove it from the registry
await taskSpaces.complete('myAgentSpace', { keep: false });

```

## Summary

- **Task spaces** in ego-lite provide isolated browsing contexts with unique CDP sessions and tab sets.
- **Three ownership tiers**—`agent`, `agentDelegatedToUser`, and `user`—determine mutation rights.
- **Enforcement** occurs in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) via `isAgentOwned` checks and explicit guards in methods like `switchTaskSpace`.
- **Ownership transfers** require explicit API calls (`claimTaskSpace`) to prevent accidental interference with user sessions.
- The `taskSpaces` façade in [`src/index.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/index.ts) exposes these controls to the automation runtime.

## Frequently Asked Questions

### What happens if an agent tries to switch to a user-owned task space without claiming it?

The `switchTaskSpace` function throws a ownership violation error. According to the implementation in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts) (lines [57-62](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L57-L62)), the SDK explicitly checks `isAgentOwned` before switching contexts, preventing agents from accidentally modifying user-controlled browsing sessions.

### How does task space isolation work in ego-lite?

Isolation is enforced at the native bridge level (the closed-source ego-lite application), while the JavaScript SDK manages logical separation. Each task space maintains its own CDP session, tab registry, and snapshot state. Switching spaces via `ego.useTaskSpace` selects the correct native context, ensuring that cookies, local storage, and DOM state remain segregated between spaces.

### What is the difference between `agentDelegatedToUser` and `user` ownership?

`"agentDelegatedToUser"` indicates the agent created the space but explicitly handed it to the user (e.g., after a `handOff()` call), whereas `"user"` means the user created the space independently. The key distinction lies in creation provenance: delegated spaces can typically be reclaimed more easily by the original agent, while fully user-owned spaces require explicit `claimTaskSpace` calls.

### How do I safely transfer ownership from user to agent in ego-lite?

Call `taskSpaces.claim('spaceName')` before performing mutations. This invokes `claimTaskSpace` (lines [24-27](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L24-L27) in [`src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/helpers.ts)), which transfers the ownership value from `"user"` to `"agent"`. After claiming, the agent can execute `switch`, `complete`, or other mutating operations without triggering ownership guards.