# Ego-Lite Task Space Ownership Model and Agent-User Handoff Explained

> Explore the ego-lite task space ownership model agent agentDelegatedToUser and user states and discover how agent user handoff works with citrolabs ego-lite helpers.

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

---

**Ego-lite implements a three-state task space ownership model—`"agent"`, `"agentDelegatedToUser"`, and `"user"`—that governs whether the AI agent or human user controls browser operations, with handoff managed through specific helpers in the citrolabs/ego-lite repository.**

The citrolabs/ego-lite repository provides a browser harness that isolates work into independent task spaces, each governed by an ownership model determining control rights. This system enables seamless collaboration between automated agents and human users, allowing the agent to delegate control when human judgment is required and reclaim it when tasks resume.

## The Three Task Space Ownership States

Ego-lite tracks ownership through the `ownership` field on task space objects, which can hold one of three string values that determine who may execute browser commands.

### Agent Ownership States (`"agent"` and `"agentDelegatedToUser"`)

When a task space has `"agent"` ownership, the AI agent maintains full control and can execute arbitrary browser commands. The `"agentDelegatedToUser"` state indicates the space was created by the agent but control has been temporarily handed to the user—real agent interactions are paused, though the agent retains ownership claims. In [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts), the `isAgentOwned` helper treats both `"agent"` and `"agentDelegatedToUser"` as agent-owned (lines 43-45), allowing the agent to reclaim these spaces without claiming ownership first.

### User Ownership (`"user"`)

A `"user"` owned space originates from the human user rather than the agent, granting the user exclusive control. The native ego bindings enforce a hard boundary here: agent commands targeting user-owned spaces receive the `EGO_TASK_SPACE_USER_IN_CONTROL` error code defined in [`package/ego-browser/src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts) (lines 13-16), which the system treats as a non-retryable hard stop.

## How Agent-User Handoff Works

The handoff mechanism enables safe transitions between automated and manual browsing, ensuring the agent releases control cleanly and can resume work when appropriate.

### Delegating Control to the User

When the agent determines human intervention is necessary, it calls `handOffTaskSpace([id|name])` from [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts). If the target space is agent-owned, the helper invokes the native `ego.handOffTaskSpace()` binding (lines 27-38) and resolves `{ done: true }`, transitioning the ownership to `"agentDelegatedToUser"`. If the space is already user-owned, the helper returns early with `{ done: false, skipped: "user-owned" }` (lines 31-35), avoiding redundant operations.

### Reclaiming Control from the User

To resume automated operations, the agent executes `takeOverTaskSpace([id|name])`, which re-applies the agent overlay and restores execution capabilities without checking ownership boundaries (lines 44-54). For workflows that must pause until the user finishes, the agent can call `waitForAgentControl()`, which polls the native bridge until the agent regains control, effectively blocking execution during the handoff period.

## Task Space Helper Behaviors by Ownership

The behavior of task space helpers varies based on the current ownership state, as documented in the source comments of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) (lines 24-33):

- **`switchTaskSpace`**: Throws an error when targeting user-owned spaces, as it only operates on agent-owned contexts.
- **`claimTaskSpace`**: Claims user-owned spaces (changing ownership to `"agent"`) before selecting them.
- **`handOffTaskSpace`**: Skips execution on user-owned spaces, returning `{ done: false, skipped: "user-owned" }`.
- **`completeTaskSpace({keep:true})`**: Skips user-owned spaces without action.
- **`completeTaskSpace({keep:false})`**: Claims user-owned spaces first, then closes them.
- **`takeOverTaskSpace`**: Bypasses ownership checks entirely, restoring the agent overlay immediately.
- **`waitForAgentControl`**: Polls until agent control is restored, handling the transition from `"agentDelegatedToUser"` back to `"agent"`.

## Practical Implementation Examples

The following patterns demonstrate proper handoff implementation using the ego-browser API:

```javascript
// Hand off the current task space to the user for manual intervention
import * as taskSpaces from "ego-browser";

await taskSpaces.handOffTaskSpace(); // returns { done: true }
// If already user-owned, returns { done: false, skipped: "user-owned" }

```

```javascript
// Claim a user-owned space before closing it
import * as taskSpaces from "ego-browser";

await taskSpaces.completeTaskSpace("my-user-space", { keep: false });
// Claims ownership, then closes the space. Returns { done: true }.

```

```javascript
// Wait for user to finish, then resume agent operations
import * as taskSpaces from "ego-browser";

await taskSpaces.waitForAgentControl("my-space"); // polls until control returns
// Safe to execute browser commands after this resolves

```

## Error Handling During User Control

When the agent attempts unauthorized operations on a user-controlled space, the system returns `EGO_TASK_SPACE_USER_IN_CONTROL`. This error code, recognized in [`package/ego-browser/src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts), signals that the agent must not retry the operation and should instead wait for the user to release control via `waitForAgentControl()` or explicitly reclaim the space using `takeOverTaskSpace()`.

## Summary

- **Ego-lite uses three ownership states**: `"agent"` (full control), `"agentDelegatedToUser"` (paused agent, user active), and `"user"` (user control, agent blocked).
- **Handoff requires explicit delegation**: The `handOffTaskSpace()` helper transitions agent-owned spaces to delegated states, while `takeOverTaskSpace()` restores agent control without ownership validation.
- **User-owned spaces are protected**: Native bindings enforce boundaries that trigger `EGO_TASK_SPACE_USER_IN_CONTROL` errors when agents attempt unauthorized access.
- **Claiming converts ownership**: The `claimTaskSpace()` and `completeTaskSpace({keep:false})` helpers can convert user-owned spaces to agent ownership when necessary.
- **Polling enables synchronization**: `waitForAgentControl()` provides a blocking mechanism for agents to pause execution until users finish manual operations.

## Frequently Asked Questions

### What happens when an agent tries to control a user-owned task space?

The native ego bindings return the error code `EGO_TASK_SPACE_USER_IN_CONTROL`, which the system treats as a hard stop that prevents retry. According to [`package/ego-browser/src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts), this error indicates the agent must wait for the user to release control or explicitly claim the space first.

### How does the agent know when the user has finished their session?

The agent calls `waitForAgentControl()` from [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts), which continuously polls the native bridge until the task space returns to agent control. This function blocks execution until the user hands back control or the agent forcibly reclaims the space using `takeOverTaskSpace()`.

### Can a user-owned task space be converted to agent ownership?

Yes, through the `claimTaskSpace()` helper, which changes the ownership field from `"user"` to `"agent"`. Additionally, calling `completeTaskSpace({keep:false})` on a user-owned space first claims it (converting ownership) and then closes the task space entirely.

### What is the difference between "agent" and "agentDelegatedToUser" ownership?

Both states indicate the agent created the space, but `"agentDelegatedToUser"` signifies the agent has temporarily handed operational control to the user while retaining ownership claims. The `isAgentOwned` helper in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) recognizes both as agent-owned, allowing the agent to reclaim either without claiming, whereas `"user"` owned spaces require explicit claiming before agent operations can resume.