# How to Hand Off Control of a Task Space to the User in ego-lite

> Easily hand off task space control to the user in ego-lite. Use handOffTaskSpace() for manual intervention like CAPTCHAs, logins, or confirmations.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: how-to-guide
- Published: 2026-08-24

---

**Use the `handOffTaskSpace()` helper in ego-lite to transfer ownership of a browsing context from the AI agent to the user when manual intervention is required for CAPTCHAs, logins, or confirmations.**

In the `citrolabs/ego-lite` framework, **task spaces** isolate browsing contexts for AI agents performing automated workflows. When a workflow encounters a step that requires human intervention—such as solving a CAPTCHA or completing multi-factor authentication—you must hand off control of the task space to the user to prevent automation errors and enable secure manual interaction.

## Why Task Space Handoff Matters

Task spaces in ego-lite enforce strict ownership rules. While the user controls the space, any browser operation initiated by the agent fails with a "user is controlling" error. Properly implementing the handoff protocol, as documented in the "Control handoff" section of [`SKILL.md`](https://github.com/citrolabs/ego-lite/blob/main/SKILL.md), ensures smooth collaboration between automated scripts and human users.

## Implementing Control Handoff with `handOffTaskSpace`

The `handOffTaskSpace` function, implemented in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) (lines 326-338), manages the transfer of ownership from agent to user according to the runtime protocol defined in the ego backend.

### Step 1: Initiate the Handoff

Call `handOffTaskSpace` with an optional task space identifier. Omit the parameter to use the currently selected space.

```javascript
const result = await handOffTaskSpace(task.id);
// Or use the default selected space:
// const result = await handOffTaskSpace();

```

### Step 2: Inspect the Result Object

The function returns a promise that resolves to an object indicating the handoff status:

- **`{ done: true }`** – The transfer succeeded; the space was previously agent-owned.
- **`{ done: false, skipped: "user-owned" }`** – The space was already user-owned; no changes occurred.

Always check `result.done` before proceeding, as shown in `helpers.test.mjs` (lines 849-911):

```javascript
if (!result.done) {
  cliLog('Space already controlled by user');
} else {
  cliLog('Control transferred successfully');
}

```

### Step 3: Communicate with the User

After a successful handoff, explicitly inform the user of required actions. The agent must pause all browser automation until the user signals completion via an "Ask" button or chat message. Do not issue further browser commands during this period.

### Step 4: Reclaim Control with `takeOverTaskSpace`

Once the user confirms completion, reacquire ownership using `takeOverTaskSpace` (or `claimTaskSpace` if reclaiming a previously user-owned space):

```javascript
await takeOverTaskSpace(task.id);
// Resume automation...
await click('button#continue');

```

## Complete Workflow Example

The following pattern demonstrates a full checkout flow with manual login intervention, combining `useOrCreateTaskSpace`, `handOffTaskSpace`, and cleanup:

```javascript
// Create or select task space
const task = await useOrCreateTaskSpace('checkout flow');
cliLog(`Task space id: ${task.id}`);

// Automated steps
await openOrReuseTab('https://example.com/checkout', { wait: true });
await click('button#login');

// Hand off for manual authentication
const handoff = await handOffTaskSpace(task.id);
if (handoff.done) {
  cliLog('Please complete the login and click **Continue**.');
} else {
  cliLog('Control already with user – proceed when ready.');
}

// ... Wait for user signal ...

// Regain control and complete
await takeOverTaskSpace(task.id);
await click('button#confirm');
await captureScreenshot();
cliLog('Checkout completed.');

```

## Cleaning Up Task Spaces

When the workflow completes, close the space using `completeTaskSpace`. The `keep` option controls whether the browser page remains open for the user:

```javascript
await completeTaskSpace(task.id, { keep: true });

```

## Summary

- Call `handOffTaskSpace(nameOrId?)` in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) to transfer control from agent to user.
- Check the returned object's `done` property to confirm successful transfer or detect pre-existing user ownership.
- Pause all automation after handoff; any agent browser actions while the user controls the space will fail with a "user is controlling" error.
- Use `takeOverTaskSpace()` to resume automation after user completion, or `claimTaskSpace()` for spaces created as user-owned.
- Reference the "Control handoff" sections in [`SKILL.md`](https://github.com/citrolabs/ego-lite/blob/main/SKILL.md) and [`AGENTS.md`](https://github.com/citrolabs/ego-lite/blob/main/AGENTS.md) for protocol details and ownership rules.

## Frequently Asked Questions

### What happens if I try to perform browser actions after handing off control?

Any browser operation attempted by the agent while the user controls the task space fails immediately with a "user is controlling" error. The `handOffTaskSpace` implementation in [`helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/helpers.ts) ensures the runtime enforces this ownership boundary to prevent automation conflicts.

### How do I know if the handoff was successful?

Inspect the `done` property of the object returned by `handOffTaskSpace`. A value of `true` confirms the space transitioned from agent to user ownership, while `false` with `skipped: "user-owned"` indicates the space was already under user control, as verified in the unit tests at `helpers.test.mjs` lines 849-911.

### Can I hand off a task space without specifying an ID?

Yes. Call `handOffTaskSpace()` without arguments to target the currently selected task space. The helper defaults to the active context, simplifying workflows where you maintain a single primary space, according to the implementation signature in [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts).

### What is the difference between `takeOverTaskSpace` and `claimTaskSpace`?

Use `takeOverTaskSpace` to reclaim a space you previously handed off to the user during the current session. Use `claimTaskSpace` when taking ownership of a space that was created as user-owned or abandoned by another agent. Both functions restore agent control but target different ownership states, as outlined in [`AGENTS.md`](https://github.com/citrolabs/ego-lite/blob/main/AGENTS.md).