# Agent vs User Task Space Ownership in ego‑lite: Complete Guide to Control Models

> Understand agent vs user task space ownership in ego-lite. Learn the three states agentDelegatedToUser and user and how the agent claims user owned spaces for control.

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

---

**The agent vs user ownership model in ego‑lite determines which party controls isolated browser contexts, with `agent`, `agentDelegatedToUser`, and `user` as the three valid states, and the agent must claim user‑owned spaces before manipulation.**

Task spaces in ego‑lite are isolated browser environments that enable AI agents to perform web-based tasks without interfering with each other or the user's main browsing session. The ownership model governs every interaction with these spaces, from creation through completion. Understanding how `agent` vs `user` ownership works is essential for building reliable agent workflows that handle collaborative hand‑offs correctly.

## Understanding the Three Ownership States

The ego‑lite runtime tracks ownership through a single field with three possible values. The core predicate that checks agent ownership resides in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts):

```ts
function isAgentOwned(ownership) {
  return ownership === "agent" || ownership === "agentDelegatedToUser";
}

```

| Ownership value | Who created it | Control rules |
|---------------|--------------|-------------|
| **`agent`** | Agent | Full agent control; no restrictions on switching or manipulation |
| **`agentDelegatedToUser`** | Agent (delegated) | Agent retains ownership but user has control; agent can still act without reclaiming |
| **`user`** | User | Agent **must claim** before any manipulation; switch operations blocked |

The `agentDelegatedToUser` state enables cooperative scenarios where the agent shares control without fully surrendering the space.

## Creating and Retrieving Task Spaces

### useOrCreate: Reuse Agent Spaces or Fail on User Spaces

The `taskSpaces.useOrCreate(nameOrId)` method in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) attempts to find an existing agent‑owned space matching the identifier, or creates a new one if none exists. Critically, **it cannot reuse user‑owned spaces** — the call throws an explicit error:

```

useOrCreateTaskSpace cannot use task space … with ownership …

```

This safety mechanism prevents accidental agent interference with user‑controlled contexts.

### new: Force Fresh Agent‑Owned Creation

When you need guaranteed isolation, `taskSpaces.new(name)` always creates a brand‑new space with `agent` ownership, regardless of any existing spaces with that name.

## Claiming User‑Owned Spaces

Before an agent can interact with a `user`‑owned space, it must explicitly claim ownership. The `taskSpaces.claim(nameOrId)` method performs this transfer:

```js
// Claim transfers ownership and automatically selects the space
await taskSpaces.claim('user-created-space');

```

After claiming, the space's ownership becomes `agent`, enabling full manipulation. This claim‑then‑act pattern is mandatory for collaborative workflows where users initiate spaces that agents later take over.

## Switching Between Spaces

The `taskSpaces.switch(nameOrId)` method enforces strict ownership validation. It only operates on spaces where `isAgentOwned()` returns true. Attempting to switch to a `user`‑owned space produces a clear runtime error:

```

switchTaskSpace requires an agent-owned task space, got ownership …

```

This error originates from the validation logic at line 160 of [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts), ensuring agents never accidentally operate in unclaimed contexts.

## Hand‑Off and Take‑Over Patterns

ego‑lite provides two special operations for collaborative workflows that bypass standard ownership checks:

- **`taskSpaces.handOff(nameOrId?)`** — Agent voluntarily returns control to the user, setting ownership to `user`. Useful when the agent finishes its portion of a task and awaits user input.

- **`taskSpaces.takeOver(nameOrId?)`** — Agent immediately regains control of a `user`‑owned space without requiring a separate claim operation. This "no‑ownership‑check" shortcut streamlines recovery from hand‑off states.

These methods are implemented as direct ownership transitions in the task‑space façade, enabling fluid agent‑user collaboration without repetitive claim/switch ceremonies.

## Completing Tasks and Preserving Spaces

When work finishes, `taskSpaces.complete(nameOrId, { keep })` handles cleanup:

```js
// Default: close the space entirely
await taskSpaces.complete(task.id); // keep: false

// Preserve for live‑page scenarios
await taskSpaces.complete(task.id, { keep: true });

```

The `keep` parameter, documented in [`skills/ego-browser/SKILL.md`](https://github.com/citrolabs/ego-lite/blob/main/skills/ego-browser/SKILL.md) at line 207, supports use cases where the space should remain available for continued user interaction after agent completion.

## Waiting for Guaranteed Control

In multi‑step workflows involving hand‑offs, agents can ensure they have control before proceeding:

```ts
await taskSpaces.waitForAgentControl(task.id);

```

This utility from [`package/ego-browser/src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts) (lines 764‑766) polls until the space becomes agent‑owned, preventing race conditions in collaborative scenarios.

## Complete Workflow Example

```js
// 1️⃣ Create or reuse an agent‑owned space
const task = await taskSpaces.useOrCreate('research-topic');

// 2️⃣ Handle user‑owned spaces with explicit claim
if (task.ownership === 'user') {
  await taskSpaces.claim(task.id);
}

// 3️⃣ Switch to active work context
await taskSpaces.switch(task.id);

// ... perform agent operations ...

// 4️⃣ Collaborative hand‑off to user
await taskSpaces.handOff(task.id);

// 5️⃣ Later recovery of control
await taskSpaces.takeOver(task.id);
await taskSpaces.waitForAgentControl(task.id);

// 6️⃣ Clean termination
await taskSpaces.complete(task.id, { keep: false });

```

## Source File Reference

| File | Purpose |
|------|---------|
| [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) | Core ownership logic, `isAgentOwned()` predicate, claim/switch implementations |
| [`package/ego-browser/src/format.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts) | Public API surface, `waitForAgentControl()` utility |
| [`skills/ego-browser/SKILL.md`](https://github.com/citrolabs/ego-lite/blob/main/skills/ego-browser/SKILL.md) | Human‑readable API documentation including ownership semantics |
| [`AGENTS.md`](https://github.com/citrolabs/ego-lite/blob/main/AGENTS.md) | High‑level task‑space concepts for agent developers |

## Summary

- **Three ownership states** (`agent`, `agentDelegatedToUser`, `user`) govern all task space interactions in ego‑lite according to the `isAgentOwned()` predicate in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts).

- **User‑owned spaces require explicit claims** via `taskSpaces.claim()` before the agent can switch to or manipulate them.

- **`useOrCreate()` fails on user spaces** by design, preventing accidental interference; use `new()` for guaranteed fresh spaces.

- **Hand‑off patterns** use `handOff()` and `takeOver()` for collaborative workflows without repetitive ownership checks.

- **Completion with `keep: true`** preserves spaces for live‑page scenarios where users continue interacting after agent work finishes.

## Frequently Asked Questions

### What happens if I call switch() on a user‑owned task space?

The runtime throws an error: `"switchTaskSpace requires an agent-owned task space, got ownership …"`. You must first call `taskSpaces.claim()` to transfer ownership, then `switch()` will succeed. This validation occurs at line 160 of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

### What's the difference between claim() and takeOver()?

`claim()` is the standard method for acquiring user‑owned spaces with full ownership validation—it transfers `user` ownership to `agent`. `takeOver()` is a shortcut that bypasses ownership checks entirely, allowing immediate control recovery after a `handOff()`. Both result in agent ownership, but `takeOver()` assumes you already understand the collaboration state.

### Can an agent act on a space after calling handOff()?

Only if it reclaims control. After `handOff()`, ownership becomes `user`, so subsequent agent operations require either `claim()` (standard) or `takeOver()` (shortcut). The `agentDelegatedToUser` state is different—it allows agent action without reclaiming because ownership technically remains with the agent.

### When should I use keep: true in taskSpaces.complete()?

Use `keep: true` when the user needs continued access to the space after agent completion—for example, reviewing results, filling additional forms, or interacting with a finalized page. The default `keep: false` closes the space entirely, which is appropriate for fully automated workflows with no human follow‑up.