How Task Space Operations Handle Ownership Transfers in ego-lite

In ego-lite, claimTaskSpace transfers a user-owned browsing context to agent control, while completeTaskSpace conditionally claims or skips user-owned spaces based on the keep option before finalizing or closing the task.

The ego-lite framework provides isolated browsing contexts called task spaces that enforce strict ownership boundaries between the agent and the user. Understanding how task space operations work with ownership transfers is essential for building reliable agent skills. This article examines the implementation in citrolabs/ego-lite to explain the mechanics behind claimTaskSpace and completeTaskSpace.

How Task Space Ownership Works

Task spaces in ego-lite carry an ownership field with three possible values:

  • "agent" — The agent has full control
  • "agentDelegatedToUser" — The agent temporarily yielded control
  • "user" — The user owns the browsing context

Ownership changes are mediated through the native ego bridge, which exposes runtime methods for claiming, selecting, completing, and closing task spaces. The helper functions in package/ego-browser/src/helpers.ts enforce these policies and handle all bridge interactions.

Claiming a Task Space with claimTaskSpace

The claimTaskSpace function transfers ownership from user to agent. It resolves the target space by name or ID, then invokes ego.claimTaskSpace(id, name) to perform the transfer.

In helpers.ts (lines 224-236), the implementation follows this pattern:

export async function claimTaskSpace(nameOrId) {
  const space = await findTaskSpace(nameOrId);
  return claimResolvedTaskSpace(space, "claimTaskSpace");
}

async function claimResolvedTaskSpace(space, op = "claimTaskSpace") {
  const ego = globalThis.ego;
  if (!ego || typeof ego.claimTaskSpace !== "function") {
    throw new Error(`${op} requires ego.claimTaskSpace`);
  }
  const id = taskSpaceNumericId(space, op);
  const claimed = normalizeTaskSpace(
    assertNoEgoError(await ego.claimTaskSpace(id, space.name), op),
  );
  // ...select the claimed space...
}

After claiming, the helper automatically selects the space via ego.useTaskSpace(id), making it the active context for subsequent operations.

Completing a Task Space with completeTaskSpace

The completeTaskSpace function handles two scenarios based on the keep option:

  • keep: true — Finalizes agent work but leaves the page open for the user
  • keep: false — Closes the space after finishing

Critically, completeTaskSpace applies ownership-aware logic when encountering user-owned spaces:

Scenario Ownership Behavior
keep: true + user-owned "user" Skips operation, returns { done: false, skipped: "user-owned" }
keep: false + user-owned "user" Claims the space first, then closes it
Agent-owned "agent" or "agentDelegatedToUser" Proceeds directly to complete/close

The implementation in helpers.ts (lines 274-315):

export async function completeTaskSpace(nameOrId, options) {
  // ...validation omitted...
  const match = findMatchingTaskSpace(await listTaskSpaces(), nameOrId);
  if (options.keep) {
    if (match.ownership === "user") {
      return { done: false, skipped: "user-owned" };
    }
    await selectTaskSpace(ego, match, "completeTaskSpace");
    assertNoEgoError(await ego.completeTaskSpace(), "completeTaskSpace");
  } else {
    if (match.ownership === "user") {
      await claimResolvedTaskSpace(match, "completeTaskSpace");
    } else {
      await selectTaskSpace(ego, match, "completeTaskSpace");
    }
    assertNoEgoError(await ego.closeTaskSpace(), "completeTaskSpace");
  }
  return { done: true };
}

Key Implementation Details

Space Resolution and ID Enforcement

Both operations first resolve the target via findTaskSpace(nameOrId), which supports lookup by numeric ID or human-readable name. The internal taskSpaceNumericId helper ensures the space has a valid numeric ID before any native bridge call—this is a hard requirement for the ego runtime.

Native Bridge Method Reference

According to the ego-lite source code, the native bridge exposes these task space methods:

  • ego.claimTaskSpace(id, name) — Transfers ownership to agent
  • ego.useTaskSpace(id) — Selects active task space
  • ego.completeTaskSpace() — Finalizes agent work (keeps page)
  • ego.closeTaskSpace() — Closes the browsing context

These are validated at runtime; missing methods throw explicit errors naming the required capability.

Runtime State Access

Helpers access the native bridge through globalThis.ego, managed by state.ts. This singleton pattern ensures consistent bridge access across all task space operations.

Practical Code Examples

Claim a user-owned task space and begin agent work:

// Transfers ownership → agent, then selects the space
await claimTaskSpace('checkout-flow');

Finish work while preserving the page for user review:

// If user-owned: no-op with skip notice
// If agent-owned: finalizes and keeps open
await completeTaskSpace('checkout-flow', { keep: true });
// Returns: { done: false, skipped: 'user-owned' } or { done: true }

Finish work and close the context:

// Claims first if user-owned, then closes
await completeTaskSpace('checkout-flow', { keep: false });
// Returns: { done: true }

Summary

  • Task spaces carry an ownership field determining agent vs. user control
  • claimTaskSpace resolves by name/ID, calls ego.claimTaskSpace(), then selects the space via ego.useTaskSpace()
  • completeTaskSpace applies conditional logic: skips user-owned spaces when keep: true, claims them first when keep: false
  • Native bridge methods in globalThis.ego perform the actual ownership transfers and lifecycle operations
  • Enforcement resides in helpers.ts (lines 224-236 for claiming, lines 274-315 for completion)

Frequently Asked Questions

What happens if I call claimTaskSpace on an already agent-owned space?

The native ego.claimTaskSpace call still executes; the bridge handles idempotent claims. The helper proceeds with space selection regardless of prior ownership state.

Can an agent complete a user-owned task space without claiming it?

Only when keep: true—and even then, the operation is skipped with { done: false, skipped: "user-owned" }. To actually finish or close a user-owned space, the agent must first claim it.

Where is the ownership policy documented outside the code?

The SKILL.md file in skills/ego-browser/ mirrors the ownership table enforced in helpers.ts, providing agent-facing documentation of these rules.

What validation ensures the native bridge is available?

Each helper checks globalThis.ego and the specific method type before invoking—claimResolvedTaskSpace explicitly validates ego.claimTaskSpace is a function and throws descriptive errors if the bridge is missing or incomplete.

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 →