# How `useOrCreateTaskSpace` Differentiates Between User-Owned and Agent-Owned Spaces

> Discover how useOrCreateTaskSpace differentiates user-owned and agent-owned spaces by checking the ownership field. It prioritizes agent spaces and respects user control for user-owned ones.

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

---

**`useOrCreateTaskSpace` distinguishes ownership by inspecting the `ownership` field of the matched task space, automatically reusing agent-owned spaces while deferring to user control for user-owned spaces without explicit claiming.**

In the **citrolabs/ego-lite** repository, task spaces represent isolated browser contexts for automation workflows. The `useOrCreateTaskSpace` helper serves as the primary entry point agents invoke at the start of each heredoc round to obtain a workspace, implementing intelligent ownership resolution to respect user control boundaries.

## How `useOrCreateTaskSpace` Resolves Task Space Ownership

The implementation in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) (lines 193-215) follows a strict resolution protocol to determine whether an agent can immediately use a space or must request permission.

### Retrieving and Matching Existing Spaces

The function first calls **`listTaskSpaces()`** to retrieve the current set of task spaces. It then invokes **`findMatchingTaskSpace`** to resolve the supplied `nameOrId` parameter against this list, handling three identifier types:
- String names
- Numeric-id strings  
- Raw numeric ids

### The Ownership Check Logic

Once a matching space is located, the helper examines the **`ownership`** field to determine control rights:

- **`ownership === "agent"`** (or equivalent agent designation): The helper immediately calls **`selectTaskSpace`** to activate the space and returns it for use.
- **`ownership === "user"`**: The helper selects the space but **does not claim ownership**. This triggers the **`EGO_TASK_SPACE_USER_IN_CONTROL`** error, which the system converts into guidance prompting the agent to respect user control.

When no match is found, the behavior depends on the identifier type:
- **Numeric ids**: Throws *"task space not found"* because numeric identifiers must reference existing spaces.
- **String names**: Creates a new agent-owned space via **`newTaskSpace(nameOrId`**.

## Handling User-Owned vs Agent-Owned Spaces

### Agent-Owned Space Reuse

When the resolved space carries agent ownership, `useOrCreateTaskSpace` provides seamless continuity. The function automatically selects the existing context, allowing agents to resume work across heredoc rounds without manual intervention.

### User-Owned Space Protection

User-owned spaces trigger a protective boundary. Rather than automatically claiming control, the function surfaces the **`EGO_TASK_SPACE_USER_IN_CONTROL`** error as implemented in the source. According to the repository's **SKILL.md** documentation, this behavior ensures that `useOrCreateTaskSpace` "reuses an agent-owned space or creates a new one; it no longer auto-claims user-owned spaces."

To assume control of a user-owned space, agents must explicitly invoke **`claimTaskSpace(nameOrId)`** after receiving the ownership error, ensuring intentional handoff rather than accidental takeover.

## Code Examples

The following patterns demonstrate the ownership-sensitive behavior as documented in **AGENTS.md** and the test suite:

```javascript
// Reuse an existing agent-owned space or create a new one if missing
const task = await useOrCreateTaskSpace('checkout-flow');
// Returns an agent-owned space ready for browser commands

```

```javascript
// Attempting to use a user-owned space without claiming
// The user currently controls the space; this surfaces guidance
const userTask = await useOrCreateTaskSpace('user-demo');

// To take control, explicitly claim first:
await claimTaskSpace('user-demo');

```

```javascript
// Numeric IDs must exist; this throws if space 42 is not found
try {
  await useOrCreateTaskSpace(42);
} catch (e) {
  console.error(e.message); // "task space not found: 42"
}

```

## Summary

- **`useOrCreateTaskSpace`** in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) (lines 193-215) serves as the canonical helper for task space acquisition.
- **Agent-owned spaces** are automatically selected and returned for immediate use.
- **User-owned spaces** trigger `EGO_TASK_SPACE_USER_IN_CONTROL` errors rather than automatic claiming, preserving user control.
- **String identifiers** create new spaces when not found; **numeric identifiers** require pre-existence.
- Explicit **`claimTaskSpace`** calls are required to transfer ownership from users to agents.

## Frequently Asked Questions

### What happens when `useOrCreateTaskSpace` finds a user-owned space?

When the function encounters a space where `ownership === "user"`, it selects the space via `selectTaskSpace` but does not claim it. This action triggers the `EGO_TASK_SPACE_USER_IN_CONTROL` error, which the system converts into guidance informing the agent that the user currently maintains control. The agent must then explicitly call `claimTaskSpace(nameOrId)` to assume ownership.

### Why does `useOrCreateTaskSpace` throw an error for missing numeric IDs but create new spaces for missing string names?

The function treats numeric identifiers as immutable references to existing resources that must already exist in the task space registry. In contrast, string names serve as human-readable labels that can instantiate new agent-owned contexts dynamically. This distinction prevents accidental creation of orphaned spaces via numeric typos while allowing flexible workflow initialization via descriptive names.

### Where is the ownership logic implemented in the ego-lite source code?

The core logic resides in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) between lines 193-215, within the `useOrCreateTaskSpace` function definition. Additional context appears in [`skills/ego-browser/SKILL.md`](https://github.com/citrolabs/ego-lite/blob/main/skills/ego-browser/SKILL.md) (lines 23-36) regarding intended usage patterns, and in [`AGENTS.md`](https://github.com/citrolabs/ego-lite/blob/main/AGENTS.md) (lines 27-28) documenting the public helper API. End-to-end tests confirming the ownership behavior exist in `package/ego-browser/src/taskspace-e2e.test.mjs`.

### Can an agent force control of a task space without using `claimTaskSpace`?

No. According to the implementation in **citrolabs/ego-lite**, agents cannot bypass the explicit claiming mechanism. When `useOrCreateTaskSpace` encounters user-owned spaces, it specifically avoids calling the claim logic internally. Agents must invoke `claimTaskSpace(nameOrId)` separately to transfer ownership, ensuring users retain control until they explicitly release it.