Task Space Facade in ego-lite: How Lifecycle and Ownership Are Managed

The task space facade in ego-lite provides a set of async helper functions that enforce strict ownership rules and orchestrate a predictable lifecycle: discovery, creation, claiming, switching, completion, and hand-off.

The ego-lite browser package exposes a high-level abstraction over the low-level Ego runtime APIs. Located in package/ego-browser/src/helpers.ts, this facade shields agent code from raw runtime calls while enforcing a clear ownership model that distinguishes between agent-owned and user-owned task spaces.

Understanding the Ownership Model

The facade operates on a binary ownership system inherited from the underlying Ego runtime:

  • Agent-owned spaces: Created by or claimed by the agent; the agent has full control to execute tasks, switch contexts, and close spaces.
  • User-owned spaces: Originated by the user; the agent can view them in listings but cannot manipulate them until ownership is transferred via claimTaskSpace.

This enforcement prevents accidental interference with user-controlled sessions while allowing cooperative hand-off patterns.

Phase-by-Phase Lifecycle Management

Discovery: Listing Available Task Spaces

The listTaskSpaces() helper retrieves all existing task spaces without ownership restrictions. It normalizes the raw runtime payload into a consistent format.

// List all spaces regardless of ownership
const spaces = await listTaskSpaces();
console.log(spaces.map(s => ({ id: s.id, name: s.name, ownership: s.ownership })));

Source: package/ego-browser/src/helpers.ts lines 107–113. This is the only operation that returns user-owned spaces to agent code.

Switching: Selecting Agent-Owned Spaces

The switchTaskSpace(nameOrId) helper selects an existing space for use but strictly validates ownership:

// Throws if space 42 is user-owned
await switchTaskSpace(42);

Internally, it calls findTaskSpace() to resolve the identifier, then asserts ownership === "agent" before invoking ego.useTaskSpace(). This guard ensures agents never accidentally operate in user-controlled contexts.

Source: package/ego-browser/src/helpers.ts lines 152–163.

Creation: Establishing Agent Ownership

The newTaskSpace(name) helper creates a fresh space and immediately establishes agent ownership:

const ts = await newTaskSpace("data-processing");
// ts.ownership === "agent"

The implementation: calls ego.createTaskSpace(name), normalizes the result, validates it via checkTaskSpace(), then selects it via the internal selectTaskSpace() routine.

Source: package/ego-browser/src/helpers.ts lines 171–183.

"Use or Create" Pattern: Convenience with Enforcement

The useOrCreateTaskSpace(nameOrId) helper implements a common workflow: attempt to find an existing space, create if absent. Ownership rules apply:

  • If found and agent-owned: select it.
  • If found and user-owned: reject—caller must explicitly claimTaskSpace first.
  • If not found: create new (automatically agent-owned).
// Safe convenience that won't hijack user spaces
const ts = await useOrCreateTaskSpace("analysis-session");

Source: package/ego-browser/src/helpers.ts lines 193–213.

Claiming: Transferring Ownership

The claimTaskSpace(nameOrId) helper is the only sanctioned path for converting user-owned spaces to agent-owned:

// Transfer ownership from user to agent
await claimTaskSpace("existing-user-space");
// Now safe to switch or manipulate

Implementation calls ego.claimTaskSpace(), normalizes the result, then selects the claimed space. This is the critical bridge for collaborative workflows where users initiate sessions that agents later control.

Source: package/ego-browser/src/helpers.ts lines 224–242.

Completion and Cleanup: Controlled Termination

The completeTaskSpace(nameOrId, { keep }) helper handles graceful shutdown with flexibility:

// Complete and close (default)
await completeTaskSpace(ts.id, { keep: false });

// Complete but leave open for potential reuse
await completeTaskSpace(ts.id, { keep: true });

The implementation selects the target space, checks for native ego.completeTaskSpace support, falls back to claim-then-close if needed, and respects the keep flag to determine whether to call ego.closeTaskSpace().

Source: package/ego-browser/src/helpers.ts lines 274–314.

Hand-Off: Returning Control to Users

The handOffTaskSpace(nameOrId?) helper enables cooperative multitasking:

// Return control to user; returns { done: false, skipped: "user-owned" } if already theirs
const result = await handOffTaskSpace(ts.id);

The helper optionally selects a space, then invokes ego.handOffTaskSpace(). When operating on a user-owned space, the runtime call is skipped and the method resolves with a diagnostic object indicating no action was needed.

Source: package/ego-browser/src/helpers.ts lines 326–338.

Take-Over: Reclaiming Control

The takeOverTaskSpace(nameOrId?) helper allows agents to resume control after a hand-off:

// Re-acquire control of current or specified space
await takeOverTaskSpace(); // uses current space

Unlike claimTaskSpace, no ownership check is performed—this works on the current space as-is, useful for re-entry workflows.

Source: package/ego-browser/src/helpers.ts lines 347–353.

Shared Internal Infrastructure

Normalization and Validation

The normalizeTaskSpace() function (invoked by all public helpers) ensures consistent object shapes regardless of runtime version or API surface variations. The checkTaskSpace() utility validates space integrity before selection.

Unified Selection Routine

The selectTaskSpace(ego, space, op) internal helper is the single point of contact with ego.useTaskSpace(). All public helpers route through it, ensuring consistent logging, error handling, and state synchronization.

Source: package/ego-browser/src/helpers.ts lines 245–253.

Space Resolution

The findTaskSpace(nameOrId) utility resolves string names or numeric IDs to concrete space objects, throwing descriptive errors for unmatched identifiers.

Source: package/ego-browser/src/helpers.ts lines 440–460.

Complete Workflow Example

import {
  listTaskSpaces,
  newTaskSpace,
  claimTaskSpace,
  switchTaskSpace,
  completeTaskSpace,
  handOffTaskSpace,
  takeOverTaskSpace
} from "@citrolabs/ego-browser";

async function collaborativeWorkflow() {
  // 1. Discover existing user context
  const spaces = await listTaskSpaces();
  const userSpace = spaces.find(s => s.name === "shared-analysis");
  
  // 2. Claim user-initiated space
  if (userSpace && userSpace.ownership === "user") {
    await claimTaskSpace(userSpace.id);
  }
  
  // 3. Or create fresh agent space if none exists
  const workspace = userSpace 
    ? await switchTaskSpace(userSpace.id)
    : await newTaskSpace("fresh-analysis");
  
  // 4. Do work...
  
  // 5. Hand back to user for review
  const handoff = await handOffTaskSpace();
  console.log(handoff.skipped ? "Already user-owned" : "Handed off");
  
  // 6. Later, resume control
  await takeOverTaskSpace();
  
  // 7. Complete and cleanup
  await completeTaskSpace(workspace.id, { keep: false });
}

Key Source Files

File Responsibility
package/ego-browser/src/helpers.ts Core facade implementation with all lifecycle helpers
package/ego-browser/src/index.ts Public exports exposing the facade API
package/ego-browser/src/state.ts Runtime state management used by helpers
package/ego-browser/src/taskspace-e2e.test.mjs End-to-end validation of ownership transitions

Summary

  • The task space facade enforces a strict ownership boundary between agent and user contexts.
  • Seven public helpers cover the complete lifecycle: listTaskSpaces, newTaskSpace, claimTaskSpace, switchTaskSpace, useOrCreateTaskSpace, completeTaskSpace, handOffTaskSpace, and takeOverTaskSpace.
  • Claiming is explicit: agents cannot accidentally manipulate user-owned spaces; claimTaskSpace is the required bridge.
  • Internal utilities (selectTaskSpace, findTaskSpace, normalizeTaskSpace) provide consistent, maintainable abstractions over raw runtime calls.
  • All operations are implemented in package/ego-browser/src/helpers.ts according to the citrolabs/ego-lite source code.

Frequently Asked Questions

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

The switchTaskSpace helper throws an error. It validates that ownership === "agent" before calling ego.useTaskSpace(). You must first call claimTaskSpace to transfer ownership from user to agent.

How is useOrCreateTaskSpace different from manually checking then creating?

The helper encodes the ownership-check logic so you don't accidentally claim user spaces. If an existing space is found and user-owned, it rejects rather than proceeding, forcing explicit intent via claimTaskSpace. If no space exists, it creates a fresh agent-owned one.

Can I reuse a task space after calling completeTaskSpace?

Only if you pass { keep: true }. The default { keep: false } calls ego.closeTaskSpace(), terminating the space. The keep flag exists specifically to support reuse patterns in long-running agent workflows.

What's the difference between handOffTaskSpace and claimTaskSpace?

They are complementary opposites. handOffTaskSpace transfers control from agent to user (or no-ops if already user-owned). claimTaskSpace transfers control from user to agent. Together they enable cooperative hand-off patterns where agents and users alternate control of shared sessions.

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 →