# How Task Space Functions Interact in Ego Lite: `useOrCreateTaskSpace`, `claimTaskSpace`, and `completeTaskSpace`

> Explore how useOrCreateTaskSpace, claimTaskSpace, and completeTaskSpace work together in Ego Lite to manage isolated browsing contexts through their coordinated lifecycle.

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

---

**The three task space functions form a coordinated lifecycle that handles creation, ownership transfer, and cleanup of isolated browsing contexts in Ego Lite.**

Ego Lite's browser harness provides **task spaces** as isolated browsing contexts that switch between **agent-owned** and **user-owned** states. The helper functions `useOrCreateTaskSpace`, `claimTaskSpace`, and `completeTaskSpace` manage this lifecycle from TypeScript agent scripts. This article explains how these functions interact based on the source code in `citrolabs/ego-lite`.

## Individual Function Responsibilities

### `useOrCreateTaskSpace(nameOrId)` — Entry Point

This function serves as the primary gateway for obtaining a task space. Located in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) at lines 193–213, it:

- Accepts either a string name or numeric ID
- Returns an existing **agent-owned** space immediately
- Creates a **new agent-owned space** if none exists
- **Throws an error** if the space exists but is **user-owned**, forcing explicit claiming

```typescript
// From helpers.ts L193-L213
const space = await useOrCreateTaskSpace('checkout-flow');
// Returns: { id: 7, name: 'checkout-flow', ownership: 'agent' }

```

### `claimTaskSpace(nameOrId)` — Ownership Transfer

When you need to take control of a user-created space, this function executes the handoff. Found at [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) lines 224–236:

- Calls the native `ego.claimTaskSpace` API
- Promotes **user-owned** spaces to **agent-owned**
- Returns the same resolved space object as `useOrCreateTaskSpace`

```typescript
// From helpers.ts L224-L236
const claimed = await claimTaskSpace('user-opened-tab');
// Space ownership now: 'agent' — ready for automation

```

### `completeTaskSpace(nameOrId, { keep })` — Lifecycle Termination

This function signals completion and triggers resource cleanup. It accepts an options object with a `keep` flag:

- `keep: false` (default) — destroys the space entirely
- `keep: true` — preserves the space for future reuse

```typescript
await completeTaskSpace('checkout-flow', { keep: false });
// Runtime reclaims resources; subsequent calls create fresh space

```

## How the Functions Interact: The State Machine

The three helpers operate as a **coordinated state machine** with clear transition rules:

```

┌─────────────────────────┐
│  useOrCreateTaskSpace   │
│     (entry point)       │
└───────────┬─────────────┘
            │
    ┌───────┴───────┬─────────────────┐
    ▼               ▼                 ▼
┌────────┐    ┌────────────┐    ┌──────────┐
│ Exists │    │   Exists   │    │ Missing  │
│+ Agent │    │  + User    │    │          │
│ Owned  │    │   Owned    │    │          │
└────┬───┘    └─────┬──────┘    └────┬─────┘
     │              │                │
     ▼              ▼                ▼
  [Return]    claimTaskSpace    [Create New]
              then retry        Agent-Owned
              useOrCreateTaskSpace  │
                                    ▼
                                 [Return]

```

### Typical Workflow Patterns

**Pattern 1: Fresh Agent Workspace**

```typescript
// Simple case — agent creates and owns everything
const space = await useOrCreateTaskSpace('automation-session');
// ... perform browser actions ...
await completeTaskSpace('automation-session');

```

**Pattern 2: Claiming User-Initiated Context**

```typescript
// User already opened a tab we need to control
try {
  await useOrCreateTaskSpace('user-dashboard');
} catch (e) {
  // Throws because ownership is 'user'
  await claimTaskSpace('user-dashboard');
}
// Now safe to use — ownership transferred
const space = await useOrCreateTaskSpace('user-dashboard');

```

**Pattern 3: Conditional Cleanup with Persistence**

```typescript
const space = await useOrCreateTaskSpace('persistent-cart');

// Do work...

// Keep for next session (e.g., maintaining login state)
await completeTaskSpace('persistent-cart', { keep: true });

// Later — reattach to existing space
const sameSpace = await useOrCreateTaskSpace('persistent-cart');

```

## Shared Infrastructure: `selectTaskSpace`

All three helpers delegate to `selectTaskSpace` for **input normalization** and **metadata resolution**. This utility:

- Converts string names or numeric IDs into full space descriptors
- Provides consistent error handling across the API surface
- Maintains a single source of truth for task space metadata

The global registry consulted by `selectTaskSpace` resides in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts), with default workspace configuration coming from [`src/env.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/env.ts).

## Export and Registration Points

The helpers reach agent scripts through this chain:

| Location | Purpose |
|----------|---------|
| [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts#L790) | Core implementations exported |
| [`index.ts`](https://github.com/citrolabs/ego-lite/blob/main/index.ts#L128-L329) | Registered in helper context for runtime exposure |

This registration pattern ensures all three functions share the same execution environment and state visibility.

## Common Interaction Pitfalls

| Mistake | Why It Fails | Correct Approach |
|---------|--------------|----------------|
| Calling `claimTaskSpace` on agent-owned space | Already owned—may error or no-op | Use `useOrCreateTaskSpace` directly |
| Skipping error handling on `useOrCreateTaskSpace` | User-owned spaces block silently | Wrap in try/catch to detect ownership conflicts |
| Calling `completeTaskSpace` with wrong name | Leaves orphaned resources | Always match the name/ID used at creation |

## Summary

- **`useOrCreateTaskSpace`** — Retrieves or creates agent-owned spaces; blocks on user-owned spaces
- **`claimTaskSpace`** — Transfers ownership from user to agent, enabling full control
- **`completeTaskSpace`** — Terminates lifecycle with optional persistence via `keep` flag

These functions share `selectTaskSpace` for resolution and operate within the registry defined in [`src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/src/state.ts). The ownership-enforcing design prevents accidental interference with user-controlled browsing contexts while providing clear escalation paths when needed.

## Frequently Asked Questions

### What happens if I call `useOrCreateTaskSpace` on a user-owned task space?

The function throws an error with a message indicating the ownership conflict. This intentional design forces you to explicitly invoke `claimTaskSpace` first, ensuring no accidental takeover of user-controlled contexts occurs. After successful claiming, `useOrCreateTaskSpace` will return the space normally.

### Can I use `claimTaskSpace` on a space that doesn't exist?

No. `claimTaskSpace` requires an existing user-owned space to promote. If the space doesn't exist or is already agent-owned, the native `ego.claimTaskSpace` API call will fail. Use `useOrCreateTaskSpace` first to verify existence and ownership status.

### What's the difference between `keep: true` and `keep: false` in `completeTaskSpace`?

With `keep: false` (the default), the runtime fully destroys the task space and reclaims all associated resources—subsequent `useOrCreateTaskSpace` calls create an entirely fresh space. With `keep: true`, the space persists in its current state, allowing later reattachment with preserved cookies, localStorage, and navigation history.

### Do these functions work with numeric IDs instead of string names?

Yes. All three helpers accept either format through `selectTaskSpace`, which normalizes the input before resolution. You can pass `await useOrCreateTaskSpace(42)` or `await claimTaskSpace('my-space')` with equal reliability.