Understanding Ego‑Lite's Task Space Ownership Model: Agent vs User Control

The ego‑lite task space ownership model assigns every browser container an ownership flag—either "agent" for autonomous AI control or "user" for human oversight—strictly governing which operations the AI can perform without explicit permission.

The ego‑lite framework isolates browsing work into task spaces, lightweight containers that each own a browser tab and its associated state. According to the citrolabs/ego‑lite source code in src/helpers.ts, every task space carries an ownership property that enforces a clear separation of control between the autonomous agent and the human user. This design prevents the AI from unintentionally disrupting active user sessions while enabling full automation when the agent holds ownership.

What Is a Task Space?

A task space is a logical container that encapsulates a browser tab and its execution context. As implemented in the ego‑browser package, these spaces allow agents to perform multi‑step browsing workflows without interfering with the user's own tabs. Each space maintains its own state, cookies, and session data, but the critical determinant of permissible actions is the ownership flag stored within the space metadata.

Ownership States: Agent vs User

The ownership model recognizes two distinct states that determine control privileges:

  • Agent‑owned spaces grant the autonomous AI complete operational freedom. When ownership is set to "agent", the AI may create, select, claim, complete, close, or hand off the space without human intervention.
  • User‑owned spaces reserve control for the human operator. When ownership is "user", the agent may select the space to inspect its state, but any attempt to claim or modify it automatically raises the EGO_TASK_SPACE_USER_IN_CONTROL error. The user must explicitly transfer ownership before the agent can proceed with destructive actions.

Core Ownership Helper Functions in src/helpers.ts

The implementation in package/ego-browser/src/helpers.ts exposes seven primary functions that enforce these ownership rules through the global ego bindings provided by helperContext():

Creating agent spacesnewTaskSpace(name) invokes ego.createTaskSpace and automatically registers the new container with "agent" ownership, returning a space object containing { id, name, ownership: 'agent', ... }.

Reusing or creating spacesuseOrCreateTaskSpace(nameOrId) queries existing spaces via listTaskSpaces. If no space exists, it delegates to newTaskSpace to create an agent‑owned container. If the space exists and is agent‑owned, it selects that space for the current Node process. However, if the space is user‑owned, the function selects it without claiming, preserving user control and returning a guidance message that explicit claiming is required.

Explicitly claiming user spacesclaimTaskSpace(nameOrId) locates a user‑owned space and transfers ownership to the agent by calling ego.claimTaskSpace. After successful execution, the space behaves as agent‑owned, permitting full automation.

Switching between spacesswitchTaskSpace(nameOrId) validates ownership before switching; it throws an error if the target space is user‑owned, ensuring the agent cannot inadvertently hijack active user sessions.

Handing off controlhandOffTaskSpace([nameOrId]) returns the UI to the user. If the target space is already user‑owned, the operation returns { done: false, skipped: "user-owned" } as a no‑op, acknowledging that the user already possesses control.

Resuming agent controltakeOverTaskSpace([nameOrId]) restores the agent overlay on a previously handed‑off space, allowing the AI to resume work without creating a new container.

Completing workflowscompleteTaskSpace(nameOrId, { keep }) finalizes the task. With keep: true, the tab remains open for the user; with keep: false, it closes. For user‑owned spaces, keep: true skips all actions since the page inherently belongs to the user.

Ownership validation – The private helper isAgentOwned(ownership) (approximately line 143) performs strict equality checks against the string "agent", serving as the gatekeeper for all privileged operations.

Ownership Lifecycle and State Transitions

The typical workflow demonstrates how ownership transitions between states:

  1. Initialization – The agent calls useOrCreateTaskSpace('workflow-name'), creating an agent‑owned space or reconnecting to an existing one.
  2. User intervention – At a decision point, the agent executes handOffTaskSpace(), transferring the browser UI to the user and implicitly marking the space as user‑controlled.
  3. Reclaiming work – When the user requests the agent continue, takeOverTaskSpace() restores the agent overlay, though ownership remains technically with the user until claimTaskSpace() is explicitly invoked.
  4. Explicit claiming – If the agent must modify a user‑owned space (e.g., close the tab), it must first call claimTaskSpace() to transfer the ownership flag to "agent".
  5. Cleanup – The agent finalizes with completeTaskSpace(task.id, { keep: false }), closing the tab only if it possesses agent ownership.

Practical Code Examples

The following patterns from skills/ego-browser/SKILL.md demonstrate safe ownership handling:

// 1️⃣ Start (or reuse) a task space for the agent
const task = await useOrCreateTaskSpace('price‑lookup');
// `task` now contains { id, name, ownership: 'agent', ... }

// 2️⃣ Switch to an existing *agent‑owned* space
await switchTaskSpace(task.id);

// 3️⃣ If you need to work on a *user‑owned* space, first claim it
await claimTaskSpace('checkout‑flow'); // transfers ownership to the agent

// 4️⃣ Hand the space back to the user (e.g., after showing results)
await handOffTaskSpace(task.id);

// 5️⃣ Later the user asks the agent to continue – resume with overlay
await takeOverTaskSpace(task.id);

// 6️⃣ Finish the work and close the tab (or keep it open for the user)
await completeTaskSpace(task.id, { keep: false }); // closes the tab
// or
await completeTaskSpace(task.id, { keep: true });  // leaves page open for user

As noted in CONTRIBUTING.md, every heredoc in agent scripts must begin with useOrCreateTaskSpace to ensure re‑attachment to the correct container across execution rounds.

Summary

  • The ego‑lite task space ownership model bifurcates control between "agent" and "user" states, preventing unauthorized automation.
  • Agent‑owned spaces permit full CRUD operations via newTaskSpace, switchTaskSpace, and completeTaskSpace.
  • User‑owned spaces block automatic claiming; the agent must invoke claimTaskSpace to transfer ownership, or use takeOverTaskSpace to merely overlay the UI.
  • All ownership checks are centralized in src/helpers.ts through the isAgentOwned helper and enforced by the helperContext global bindings.
  • The design ensures that user browsing contexts remain protected while enabling seamless, multi‑round AI workflows when ownership is properly managed.

Frequently Asked Questions

What happens if an agent tries to claim a user‑owned task space?

According to the implementation in src/helpers.ts, any attempt to automatically claim a user‑owned space will raise the EGO_TASK_SPACE_USER_IN_CONTROL error. The agent must explicitly request ownership transfer through the claimTaskSpace function, ensuring the human user maintains control over active browsing sessions.

Can the agent switch to a space that the user currently owns?

No. The switchTaskSpace function validates ownership before switching contexts. If the target space carries "user" ownership, the function throws an error rather than interrupting the human's browsing session. The agent may only select user‑owned spaces for inspection, not for active manipulation.

How does the keep parameter in completeTaskSpace behave with user‑owned spaces?

When completeTaskSpace(nameOrId, { keep: true }) is called on a user‑owned space, the operation skips all actions and returns immediately. Since the user already owns the tab, no state change is necessary. With keep: false, the agent must first possess ownership (via claimTaskSpace) to actually close the browser tab.

Where is the ownership check performed in the source code?

The ownership validation logic resides in the isAgentOwned(ownership) helper function located at approximately line 143 in package/ego-browser/src/helpers.ts. This function strictly checks for the string "agent" and is invoked by switchTaskSpace and other privileged operations to enforce the ownership model. End‑to‑end tests validating these behaviors are available in src/taskspace-e2e.test.mjs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →