How Task Spaces Work With the Agent vs User Ownership Model in ego-lite

Task spaces in ego-lite use a three-state ownership system (agent, agentDelegatedToUser, user) that determines whether an AI agent can directly manipulate a browser context or must first claim it from the user.

The citrolabs/ego-lite browser automation framework isolates each workflow in a dedicated task space with strict access controls. Understanding how the agent vs user ownership model governs these spaces is essential for building reliable agents that handle collaborative hand-offs without permission errors.


The Three Ownership States

Every task space carries an ownership flag that the runtime checks before allowing operations. The possible values are:

  • agent — The agent created the space and has full control.
  • agentDelegatedToUser — The agent created the space but voluntarily handed control to the user; the agent may still act without re-claiming.
  • user — The user created the space. The agent must claim it first before switching to or manipulating it.

The core ownership check is implemented in package/ego-browser/src/helpers.ts at lines 143–144:

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

This predicate guards all agent-side operations, ensuring the runtime throws a clear error when an agent attempts to access a user-owned space.


Creating and Retrieving Task Spaces

The taskSpaces API provides two paths for obtaining a space, with different ownership guarantees.

taskSpaces.useOrCreate(nameOrId)

Behavior: Returns an existing agent-owned space or creates a new one. Fails if a matching space exists but is user-owned.

// Returns existing agent-owned space or creates new one
const task = await taskSpaces.useOrCreate('research-topic');

If the named space has ownership: 'user', the call throws:


useOrCreateTaskSpace cannot use task space … with ownership …

(source line 213)

taskSpaces.new(name)

Behavior: Always creates a brand-new space with ownership: 'agent'. Use this when you explicitly need a fresh isolated context.


Claiming User-Owned Spaces

When a space carries user ownership, the agent must invoke taskSpaces.claim(nameOrId). This operation:

  1. Transfers ownership to the agent
  2. Automatically selects the space as active
// Claim a user-owned task space (ownership transfers to the agent) and select it
await taskSpaces.claim(task.id);

(source line 218)

After claiming, the space behaves like any agent-owned space for the remainder of its lifecycle (or until the agent hands it off).


Switching Between Spaces

taskSpaces.switch(nameOrId) requires the target space to be agent-owned:

await taskSpaces.switch(task.id);

Attempting to switch to a user-owned space produces:


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

(source line 160)

Always verify or claim ownership before switching, especially in multi-step workflows where user intervention may have changed the state.


Hand-off and Take-over Operations

The ownership model supports collaborative workflows through two special methods that bypass normal ownership checks:

taskSpaces.handOff(nameOrId?)

The agent voluntarily returns control to the user, setting ownership: 'user'. The space remains open for user interaction.

taskSpaces.takeOver(nameOrId?)

The agent reclaims a user-owned space without an explicit claim step—useful when the agent knows it previously handed off the space and wants to resume work.

These are "no-ownership-check" shortcuts designed for predictable hand-off patterns where the agent and user alternate control.


Completing Tasks and Cleanup

When finished, call taskSpaces.complete(nameOrId, { keep }):

  • keep: false (default) — Closes the space entirely
  • keep: true — Preserves the space for live-page scenarios documented in the skill reference

(source line 207)

Always complete spaces to release browser resources, especially in long-running agent sessions.


Waiting for Agent Control

After a hand-off, agents can pause until control is regained:

await taskSpaces.waitForAgentControl(task.id);

(source lines 764–766)

This is particularly useful when coordinating with user actions that must complete before the agent resumes automation.


Complete Workflow Example

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

// 2️⃣ Defensive: claim if user somehow owns the space
if (task.ownership === 'user') {
  await taskSpaces.claim(task.id);
}

// 3️⃣ Activate the space
await taskSpaces.switch(task.id);

// ... perform browser automation ...

// 4️⃣ Hand off to user for review
await taskSpaces.handOff(task.id);

// 5️⃣ Later: resume without re-claiming
await taskSpaces.takeOver(task.id);
await taskSpaces.waitForAgentControl(task.id);

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

Summary

  • Three ownership states (agent, agentDelegatedToUser, user) govern all task space operations in ego-lite.
  • Agent-owned spaces allow immediate switching and manipulation; user-owned spaces require claiming first.
  • Use useOrCreate for automatic reuse or creation, but handle the potential failure when a user-owned space exists.
  • Hand-off patterns use handOff/takeOver for clean collaboration without repeated claim cycles.
  • Always call complete to release resources, choosing keep: true only when the live-page pattern requires persistence.

Frequently Asked Questions

What happens if I try to switch to a user-owned task space without claiming it?

The runtime throws an explicit error: switchTaskSpace requires an agent-owned task space, got ownership …. You must call taskSpaces.claim() first to transfer ownership from the user to the agent.

Can an agent act on a space after calling handOff?

Yes, if the agent uses takeOver or claim. The handOff operation sets ownership to user, but the agent can regain control through these methods without needing user permission checks—since the agent previously owned the space.

What's the difference between agentDelegatedToUser and user ownership?

agentDelegatedToUser means the agent created the space and handed it to the user, but retains implicit rights to act without reclaiming. user ownership means the user originated the space, and the agent has no automatic access rights—it must explicitly claim the space.

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

Use keep: true when implementing the live-page pattern where the browser context must persist after task completion—for example, when the final result should remain visible to the user indefinitely. Otherwise, use the default keep: false to close the space and free resources.

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 →