# How handOffTaskSpace and takeOverTaskSpace Operations Transfer Control in ego-lite

> Understand how handOffTaskSpace and takeOverTaskSpace transfer control in ego-lite. Learn about context lookup, runtime switching, and ego binding delegation.

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

---

**Both `handOffTaskSpace` and `takeOverTaskSpace` are high-level helper functions in `citrolabs/ego-lite` that transfer ownership of a browser task space between the agent and the user by looking up the target context, switching the runtime, and delegating to the underlying ego bindings.**

The `handOffTaskSpace` and `takeOverTaskSpace` operations manage the lifecycle of an isolated browsing context inside the ego-lite framework. When an agent finishes a step, it can hand the task space back to the user; when automation resumes, the agent can take over the same space. These functions live in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) and share a common lookup-and-switch routine before calling the native ego runtime.

## How handOffTaskSpace Returns Control to the User

The `handOffTaskSpace` function follows a strict three-step flow to surrender agent control. According to the `citrolabs/ego-lite` source code, the implementation spans lines 26-40 of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

### Locate the Target Space and Validate Ownership

If a `nameOrId` argument is provided, the helper calls `findTaskSpace`, which internally executes `listTaskSpaces` followed by `findMatchingTaskSpace`. If the resolved space is already **user-owned**, the function short-circuits immediately and returns `{done:false, skipped:"user-owned"}`. This prevents unnecessary runtime calls when the user already holds control.

### Switch the Runtime Context

For agent-owned spaces, the helper invokes `selectTaskSpace`, which calls `ego.useTaskSpace` to switch the runtime to the chosen context. This ensures that the subsequent hand-off operation targets the correct isolated browsing session.

### Invoke the Runtime Hand-Off

After the switch, the function delegates to `ego.handOffTaskSpace()` and wraps the call with `assertNoEgoError`. On success, it returns `{done:true}`, indicating that the agent overlay has been hidden and the user now owns the space.

## How takeOverTaskSpace Restores Agent Control

The `takeOverTaskSpace` function mirrors the lookup logic but omits the user-owned short-circuit. Its flow is implemented in lines 47-54 of [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

### Select the Active or Specified Space

When a `nameOrId` is supplied, `selectTaskSpaceIfProvided` performs the same lookup and runtime switch as the hand-off routine. If no identifier is given, the function operates directly on the currently active task space without switching contexts.

### Call the Runtime Takeover

Once the correct space is active, the helper calls `ego.takeOverTaskSpace()` inside an `assertNoEgoError` wrapper. The function resolves with `void`; the overlay is simply restored, signaling that the agent has resumed work in the browsing context.

## Shared Utilities That Power Both Operations

Both control-transfer functions rely on a set of internal helpers defined in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

### Task Space Lookup and Selection

The helpers share three core utilities:

- **`findTaskSpace`** (lines 40-45) fetches the full list of spaces and selects the matching entry.
- **`selectTaskSpace`** (lines 45-51) switches the runtime using `ego.useTaskSpace`.
- **`selectTaskSpaceIfProvided`** (lines 53-61) is a thin conditional wrapper that runs the lookup only when a `nameOrId` argument is present.

### Error Handling with assertNoEgoError

Every runtime invocation is guarded by `assertNoEgoError`, imported from [`package/ego-browser/src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts). This helper translates low-level ego failures into explicit JavaScript errors, ensuring that hand-off and takeover failures surface immediately rather than silent rejects.

## Practical Code Examples

The following snippets demonstrate typical usage patterns for both operations:

```typescript
// Hand off the current task space (no argument → operates on the active space)
await handOffTaskSpace();   // → { done: true }

// Hand off a specific space, e.g. id 42
const result = await handOffTaskSpace(42);
if (!result.done) {
  console.log('Skipped – space already user-owned');
}

// Take over the current space (agent regains overlay)
await takeOverTaskSpace();

// Take over a named space
await takeOverTaskSpace('order-checkout');

```

End-to-end validation for these flows is available in `package/ego-browser/src/taskspace-e2e.test.mjs`, which exercises real hand-off and takeover sequences against the ego runtime.

## Summary

- **`handOffTaskSpace`** surrenders an agent-owned task space to the user, returning `{done:true}` or short-circuiting with `{done:false, skipped:"user-owned"}` when the user already owns the space.
- **`takeOverTaskSpace`** reclaims a task space for the agent and resolves with `void` after restoring the overlay.
- Both functions delegate to `ego.handOffTaskSpace()` and `ego.takeOverTaskSpace()` after optionally switching contexts via `ego.useTaskSpace`.
- All runtime calls are wrapped with `assertNoEgoError` to catch and translate ego-side failures immediately.
- The implementations are centralized in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts), with integration tests in `taskspace-e2e.test.mjs`.

## Frequently Asked Questions

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

The function detects user ownership during the `findTaskSpace` lookup and returns `{done:false, skipped:"user-owned"}` without invoking the ego runtime. This prevents errors when the agent never held control.

### Does takeOverTaskSpace require a task space name or id?

No. When called without arguments, `takeOverTaskSpace` operates on the currently active task space. If you pass a `nameOrId`, the helper first switches to that space using `selectTaskSpaceIfProvided` before reclaiming control.

### Where is the error handling logic centralized?

The `assertNoEgoError` helper lives in [`package/ego-browser/src/ego-errors.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/ego-errors.ts) and is used by both `handOffTaskSpace` and `takeOverTaskSpace` to validate every ego runtime response. It ensures that low-level failures are surfaced as explicit exceptions in the JavaScript layer.

### How can I verify these operations in a real browser context?

The `citrolabs/ego-lite` repository includes `package/ego-browser/src/taskspace-e2e.test.mjs`, an end-to-end test suite that validates full hand-off and takeover lifecycles against a live ego runtime. You can run these tests to verify correct behavior in an integrated environment.