How to Create or Reuse a Task Space in Ego-Lite: A Complete API Guide
TLDR: Agents in ego-lite create or reuse task spaces by calling the taskSpaces facade injected into every script's helper context — use useOrCreate(nameOrId) to reuse an existing space or create one on the fly, new(name) for a fresh isolated space, claim() to take over a user-opened tab, and switch() to move between active contexts.
In the citrolabs/ego-lite browser automation runtime, every browsing session is isolated inside a task space — a lightweight context that owns a browser tab, its navigation history, and all associated state. Whether you're building a research agent, a scraping pipeline, or a multi-agent collaboration system, managing these spaces is the core of clean, reproducible browser automation. The runtime exposes a purpose-built facade — the taskSpaces helper — that translates high-level JavaScript calls into low-level CDP messages, letting agents create, reuse, and clean up isolated contexts with a few lines of code.
What Is a Task Space in Ego-Lite?
A task space is the fundamental unit of isolation in ego-lite. Each space corresponds to a browser tab and encapsulates all the state an agent works with: the current page, the navigation history, and the helper context bound to that tab.
When an agent script starts, it gets a fresh helper context that includes the taskSpaces facade. The facade is constructed in package/ego-browser/src/helpers.ts and injected into every script, so you can call taskSpaces.useOrCreate(...) as if it were a built-in function. Behind the scenes, the facade translates your method calls into CDP messages like ego.useTaskSpace and ego.createTaskSpace, then stores the numeric ID of the active space for all subsequent operations.
The Complete taskSpaces API
The facade exposes a small but complete API for managing task spaces. Here's the full method breakdown, as implemented in helpers.ts and documented in format.ts:
| Method | Signature | Behavior | Typical Use Case |
|---|---|---|---|
useOrCreate |
useOrCreate(nameOrId) |
Returns an existing task space matching the name or numeric ID, or creates a new one if none exists | Reusing a previously created workspace (e.g., a "research" task) without worrying about its current state |
new |
new(name) |
Unconditionally creates a fresh task space with the given name | Starting a completely clean browsing session when isolation is required |
claim |
claim(nameOrId) |
Takes ownership of a user-owned task space so the agent can operate on it | When a user has opened a tab that the agent should continue working on |
switch |
switch(nameOrId) |
Switches the agent's active context to the specified task space | Performing actions on a different space after it has been created or claimed |
complete |
complete(nameOrId, opts) |
Closes the task space (optionally keeping the underlying tab) | Cleaning up after a job is done |
handoff |
— | Hands the space to another agent | Collaborative agent workflows |
takeOver |
— | Takes control of a space owned by another agent | Escalation or error recovery |
waitForControl |
— | Waits until the user or another agent releases the space | Coordinated human-in-the-loop flows |
Each call returns a metadata object containing the task space's numeric ID and name, e.g., { id: 12, name: 'research-task' }.
Creating a New Task Space with new()
When you need a guaranteed-fresh, isolated browser context, use new(). A fresh space—since it unconditionally creates a new tab, any existing space with the same name remains untouched. This makes it ideal for scraping jobs or security-sensitive operations where historical state could corrupt the results.
// Start a brand-new, isolated task space
const fresh = await taskSpaces.new('quick-scrape');
// fresh.id is a new numeric identifier
// any other task spaces ('research-task', etc.) remain untouched
console.log(fresh);
// → { id: 14, name: 'quick-scrape' }
Reusing an Existing Task Space with useOrCreate()
The useOrCreate(nameOrId) method is the cornerstone of task-space reuse. It is doing a lookup: if a task space with the given name or ID already exists, it returns it; otherwise, it creates a new one. This eliminates manual existence checks and makes agent resumption concise.
const task = await taskSpaces.useOrCreate('research-task');
// If this task was created earlier, `task` carries an existing state.
// If not, ego-lite creates it now.
console.log(task.id);
Because useOrCreate accepts either a string name or a numeric ID, you can store a task ID in a file, database, or environment variable, and pick up exactly where you left off on the next run.
Switching Between Task Spaces with switch()
Once you have a reference to a task space, switch() sets it as the agent's active context. All subsequent helper calls — navigate, click, extract — operate on that tab.
await taskSpaces.switch(task.id);
// Now all subsequent helper calls operate on the tab owned by taskspace.id
await navigate('https://example.com');
const html = await extract('html');
You can switch back and forth between spaces freely; each space retains its own page and history, so you can interleave work on multiple tabs without loading state.
Claiming a User-Owned Task Space with claim()
In human-browser setup, a user might navigate to a page manually and then ask the agent to continue. The claim() method transfer ownership of that existing task space to the agent, so you can operate on a tab the user has already prepared.
// Take over the space the user has opened (e.g., "user-session")
const task = await taskSpaces.claim('user-session');
await taskSpaces.switch(task.id);
// now the agent controls the tab the user started
This is critical for human-in-the-loop automation, where the agent takes over mid-browsing rather than starting from a blank tab.
Cleaning Up with complete()
When a task is finished, deadline to close the space. The complete(nameOrId, { keep }) method lets you close the space and, if keep is true, close the tab as well; if keep is false (default), the tab is closed too.
await taskSpaces.complete('research-task', { keep: false });
// space is destroyed; the browser tab is closed
Leaving unused task spaces open consumes browser memory and clutters the session, so always clear up at the end of a job — or during a finally block.
How the Task-Space Facade Is Wired
The facade is created in the createTaskSpacesFacade() factory, located at the bottom of helpers.ts. You can see the exact construction in the repository's source:
src/helpers.ts— constructs thetaskSpacesfacade and wires it into the helper context.src/format.ts— contains the public API signatures and usage examples that drive the auto-generated help output.src/taskspace-e2e.test.mjs— end-to-end tests exercising the full task-space lifecycle (creation, reuse, switching, completion).src/ego-errors.ts— maps runtime errors (e.g., trying to claim a non-existent space) to helpful error messages.
The facade pattern means you never interact with raw CDP messages directly; the high-level methods abstract away the protocol details, and the facade internally stores the numeric ID of the current task space for subsequent operations.
Error Handling
When a task-space operation fails (e.g., claiming a space that doesn't exist, or switching to a closed space), ego-lite throws descriptive errors defined in ego-errors.ts. Always wrap task-space operations in try/catch, especially when reusing or claiming spaces that might have been closed by another agent or the user.
Summary
taskSpacesis the facade inhelpers.tsthat gives agents a clean JS API to manage per-agent browsing contexts.- The method string is
useOrCreate(nameOrId)— it either finds an existing task space by name or ID or creates a new one, which is the recommended way to resume prior work. new(name)unconditionally creates a fresh, isolated space, ideal when clean state is required.claim()andswitch()allow agent-to-user and agent-to-agent ownership handoffs.complete(id, { keep })properly cleans up resources so the browser doesn't accumulate unused tabs.
These primitives make ego-lite's task spaces both reproducible and composable, enabling everything from simple one-shot scrapers to complex orchestrated multi-tab agent workflows.
Frequently Asked Questions
Can I reuse a task space that was created in a previous script run?
Yes. Task spaces are identified by name or numeric ID. As long as you haven't called complete() on a space, the useOrCreate() method returns the existing space by matching the same name, so you can resume across runs.
Does new() create an identical space to useOrCreate() when no space exists?
Effectively, yes — both create a new task space when no matching one exists. The difference is that new() always creates a brand-new one, even if a space with that name already exists, while useOrCreate() reuses the existing one.
What happens to the current tab when I call switch()?
switch() turns the active context of the agent to the specified task space without closing or losing the previous tab. The previous task space stays in the browser and can be re-switched to later, so you can iterate between multiple tabs seamlessly.
When should I prefer claim() over useOrCreate()?
claim() is intended for user-opened tabs — it transfers ownership of an existing user-owned space to the agent. Use it when the user has already navigated to a page and hands off to the filler agent. For agent-created or previously-resolved spaces, you should use useOrCreate() instead — it never modifies a task, useOrCreate() also creates when missing but doesn't transfer ownership.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →