# How ego‑lite Task Space Ownership Models Work: Agent, User, and Delegated Control

> Explore ego-lite task space ownership models: agent, user, and delegated control. Understand how agents manage and claim spaces for efficient task management.

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

---

**TLDR:** ego-lite defines three task space ownership models — `agent`, `agentDelegatedToUser`, and `user` — where the agent has full control over agent-owned spaces, can claim user-owned spaces, and must wait for auxiliary control of spaces delegated to the user.

The [citrolabs/ego-lite](https://github.com/citrolabs/ego-lite) repository implements a browser-based agent orchestration system where **task space ownership** determines which entity — the agent or the user — can execute actions. Understanding these ownership models is essential for building reliable agent workflows, because the helper functions in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) enforce strict boundaries depending on who currently owns the active space. This article breaks down each ownership type, the exact helper behaviors, and the architectural rules that prevent conflicts.

## Task Space Ownership Models in ego‑lite

The ownership policy is defined in the source documentation of [[`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L118-L131). The `ownership` field on a task space object can have one of three values.

### 1. Agent-Owned Spaces (`"agent"`)

An **agent-owned space** is the default type created when the agent starts a new task. The agent has full control: it can switch to, claim, complete, hand off, and take over these spaces without restrictions. Most autonomous workflows operate primarily within agent-owned spaces.

### 2. Agent-Delegated-to-User Spaces (`"agentDelegatedToUser"`)

The **agentDelegatedToUser** model represents a space that is still logically agent-owned but whose real-time control has been temporarily handed to the user. This happens during a handoff or a GUI takeover scenario. The critical nuance, documented in lines 119-121 of [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts), is that both `"agent"` and `"agentDelegatedToUser"` are considered agent-owned by the `isAgentOwned` check — but the user-control boundary is enforced at the native bridge when actual commands run, not in the helper layer. The internal scheduler still considers this space selectable and claimable, but the user is currently at the wheel.

### 3. User-Owned Spaces (`"user"`)

A **user-owned space** is created by the human operator, not the agent. The ego-lite helper functions treat these spaces restrictively: the agent cannot switch to them, cannot hand off from them, and cannot complete them with `keep: true` without first claiming ownership. This prevents the agent from stealthily destroying or scattering the user's work.

## How the Helper Functions Enforce Ownership

Each helper in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) checks the ownership of the target space before acting. The behavior table from the source is straightforward:

| Helper | Behavior on User-Owned Space |
|---|---|
| `switchTaskSpace` | Throws an error (agent-owned only) |
| `claimTaskSpace` | Claims the space, transferring ownership to the agent, then selects it |
| `handOffTaskSpace` | Skips and resolves `{ done: false, skipped: "user-owned" }` |
| `completeTaskSpace` with `keep: true` | Skips, resolving `{ done: false, skipped: "user-owned" }` |
| `completeTaskSpace` with `keep: false` | Claims the space first, then closes it |
| `takeOverTaskSpace` / `waitForAgentControl` | Performs no ownership check — operates directly |

This design means the most common runtime workflows — like claiming a user-created tab for a task and then closing it after — are safely handled without risking unauthorized action on user work.

## Practical Code Examples

The task space helpers are exposed through the [[`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts) module. Below are typical usage patterns taken from the public API.

### Listing Task Spaces and Their Ownership

```javascript
const spaces = await taskSpaces.list();
console.log(spaces);
// Output includes elements like:
// { taskId: "a1b2", id: 3, name: "research-budget", ownership: "user", ... }

```

### Creating and Claiming a Space

```javascript
// Create a new agent-owned space and select it
await taskSpaces.new("scraper-task");

// Use an existing space, creating it if missing.
// If the space is user-owned, it will be selected but not claimed.
const active = await taskSpaces.useOrCreate("scraper-task");

// Claim a user-owned space so the agent gains control
await taskSpaces.claim("research-budget");

```

### Handling User Ownership with Completion

```javascript
// Attempt to complete a user-owned space with keep: true -> resolves { done: false, skipped: "user-owned" }
const result = await taskSpaces.complete("research-budget", { keep: true });

// Complete a user-owned space with keep: false -> claims it first, then closes
await taskSpaces.complete("research-budget", { keep: false });

```

### Handoff and Takeover

```javascript
// Hand off the current space to the user (skipped if not agent-owned)
await taskSpaces.handOff(); // => { done: false, skipped: "user-owned" }

// Take over a space after the user finishes manual work
await taskSpaces.takeOver("my-agent-task");

// Block until the agent regains control of a delegated space
await taskSpaces.waitForAgentControl("my-agent-task");

```

## Key Source Files

| File | Role in Ownership |
|---|---|
| [[`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) | Imple…ments all task-space helpers and defines the ownership policy in its docstring (L118-L131). |
| [[`format.ts`](https://github.com/citrolabs/ego-lite/blob/main/format.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts) | Exposes the public API surface and shows helper signatures used by `help()`. |
| [[`ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/ego-errors.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts) | Contains ownership-specific error messages, including `EGO_TASK_SPACE_USER_IN_CONTROL`. |
| [[`state.ts`](https://github.com/citrolabs/ego-lite/blob/main/state.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/state.ts) | Holds the bucket of mutable runtime state, including the current active task space object. |

## Internal Logic of Ownership Transitions

When the agent wants to move from a user-owned space to full control, the flow is:

1. **Check ownership** — the helper inspects the `ownership` field.
2. **If `"user"` and operation supports claiming** — the `claimTaskSpace` helper updates the ownership to `"agent"` and then selects the space.
3. **If the operation is `completeTaskSpace` with `keep:false`** — the helper first claims it, giving the agent the authority to close it.
4. **If the operation is `switchTaskSpace` or `handOffTaskSpace`** — the helper throws or resolves a skipped status.

This ensures that a user's own task never gets silently closed or switched away without explicit agent ownership.

## Summary

- ego-lite defines **three ownership models**: `agent` (full agent control), `agentDelegatedToUser` (agent owns the space but the user currently controls execution), and `user` (user-created, agent restricted).
- **Agent-owned spaces** (`agent` and `agentDelegatedToUser`) allow the full set of helper actions; user-owned spaces do not.
- `claimTaskSpace` is the only way to transfer a `user` space to the agent, enabling claim-then-close operations.
- `handOffTaskSpace` and `completeTaskSpace` with `keep:true` gracefully skip user-owned spaces rather than erroring.
- The enforcement boundary for actual command execution lives at the native bridge, not in the JS helper layer, as documented in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts).

## Frequently Asked Questions

### What happens when the agent tries to switch to a user-owned task space in ego-lite?

`switchTaskSpace` throws an error if the target space is not owned by the agent. There is no automatic fallback — the caller is expected to call `claimTaskSpace` first to transfer ownership.

### Can a user-owned task space be completed by the agent?

Yes, but only with `completeTaskSpace` using `{ keep: false }`. The helper first claims ownership then closes the space. Using `{ keep: true }` instead skips the operation and resolves with `{ done: false, skipped: "user-owned" }`.

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

Both are considered agent-owned by `isAgentOwned`, meaning the helper layer treats them identically. The difference is that in the `agentDelegatedToUser` case, the user is in control at the native browser level, so real commands will be blocked until the user relinquishes control — enforced by the bridge, not these helpers.

### Which file documents the ownership policy source code?

The policy is documented in the source docstring of [[`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts)](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L118-L131). The helper implementations and error constants live in the same file alongside [`ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/ego-errors.ts).