Task Space Facade in ego-lite: How Lifecycle and Ownership Are Managed
The task space facade in ego-lite provides a set of async helper functions that enforce strict ownership rules and orchestrate a predictable lifecycle: discovery, creation, claiming, switching, completion, and hand-off.
The ego-lite browser package exposes a high-level abstraction over the low-level Ego runtime APIs. Located in package/ego-browser/src/helpers.ts, this facade shields agent code from raw runtime calls while enforcing a clear ownership model that distinguishes between agent-owned and user-owned task spaces.
Understanding the Ownership Model
The facade operates on a binary ownership system inherited from the underlying Ego runtime:
- Agent-owned spaces: Created by or claimed by the agent; the agent has full control to execute tasks, switch contexts, and close spaces.
- User-owned spaces: Originated by the user; the agent can view them in listings but cannot manipulate them until ownership is transferred via
claimTaskSpace.
This enforcement prevents accidental interference with user-controlled sessions while allowing cooperative hand-off patterns.
Phase-by-Phase Lifecycle Management
Discovery: Listing Available Task Spaces
The listTaskSpaces() helper retrieves all existing task spaces without ownership restrictions. It normalizes the raw runtime payload into a consistent format.
// List all spaces regardless of ownership
const spaces = await listTaskSpaces();
console.log(spaces.map(s => ({ id: s.id, name: s.name, ownership: s.ownership })));
Source: package/ego-browser/src/helpers.ts lines 107–113. This is the only operation that returns user-owned spaces to agent code.
Switching: Selecting Agent-Owned Spaces
The switchTaskSpace(nameOrId) helper selects an existing space for use but strictly validates ownership:
// Throws if space 42 is user-owned
await switchTaskSpace(42);
Internally, it calls findTaskSpace() to resolve the identifier, then asserts ownership === "agent" before invoking ego.useTaskSpace(). This guard ensures agents never accidentally operate in user-controlled contexts.
Source: package/ego-browser/src/helpers.ts lines 152–163.
Creation: Establishing Agent Ownership
The newTaskSpace(name) helper creates a fresh space and immediately establishes agent ownership:
const ts = await newTaskSpace("data-processing");
// ts.ownership === "agent"
The implementation: calls ego.createTaskSpace(name), normalizes the result, validates it via checkTaskSpace(), then selects it via the internal selectTaskSpace() routine.
Source: package/ego-browser/src/helpers.ts lines 171–183.
"Use or Create" Pattern: Convenience with Enforcement
The useOrCreateTaskSpace(nameOrId) helper implements a common workflow: attempt to find an existing space, create if absent. Ownership rules apply:
- If found and agent-owned: select it.
- If found and user-owned: reject—caller must explicitly
claimTaskSpacefirst. - If not found: create new (automatically agent-owned).
// Safe convenience that won't hijack user spaces
const ts = await useOrCreateTaskSpace("analysis-session");
Source: package/ego-browser/src/helpers.ts lines 193–213.
Claiming: Transferring Ownership
The claimTaskSpace(nameOrId) helper is the only sanctioned path for converting user-owned spaces to agent-owned:
// Transfer ownership from user to agent
await claimTaskSpace("existing-user-space");
// Now safe to switch or manipulate
Implementation calls ego.claimTaskSpace(), normalizes the result, then selects the claimed space. This is the critical bridge for collaborative workflows where users initiate sessions that agents later control.
Source: package/ego-browser/src/helpers.ts lines 224–242.
Completion and Cleanup: Controlled Termination
The completeTaskSpace(nameOrId, { keep }) helper handles graceful shutdown with flexibility:
// Complete and close (default)
await completeTaskSpace(ts.id, { keep: false });
// Complete but leave open for potential reuse
await completeTaskSpace(ts.id, { keep: true });
The implementation selects the target space, checks for native ego.completeTaskSpace support, falls back to claim-then-close if needed, and respects the keep flag to determine whether to call ego.closeTaskSpace().
Source: package/ego-browser/src/helpers.ts lines 274–314.
Hand-Off: Returning Control to Users
The handOffTaskSpace(nameOrId?) helper enables cooperative multitasking:
// Return control to user; returns { done: false, skipped: "user-owned" } if already theirs
const result = await handOffTaskSpace(ts.id);
The helper optionally selects a space, then invokes ego.handOffTaskSpace(). When operating on a user-owned space, the runtime call is skipped and the method resolves with a diagnostic object indicating no action was needed.
Source: package/ego-browser/src/helpers.ts lines 326–338.
Take-Over: Reclaiming Control
The takeOverTaskSpace(nameOrId?) helper allows agents to resume control after a hand-off:
// Re-acquire control of current or specified space
await takeOverTaskSpace(); // uses current space
Unlike claimTaskSpace, no ownership check is performed—this works on the current space as-is, useful for re-entry workflows.
Source: package/ego-browser/src/helpers.ts lines 347–353.
Shared Internal Infrastructure
Normalization and Validation
The normalizeTaskSpace() function (invoked by all public helpers) ensures consistent object shapes regardless of runtime version or API surface variations. The checkTaskSpace() utility validates space integrity before selection.
Unified Selection Routine
The selectTaskSpace(ego, space, op) internal helper is the single point of contact with ego.useTaskSpace(). All public helpers route through it, ensuring consistent logging, error handling, and state synchronization.
Source: package/ego-browser/src/helpers.ts lines 245–253.
Space Resolution
The findTaskSpace(nameOrId) utility resolves string names or numeric IDs to concrete space objects, throwing descriptive errors for unmatched identifiers.
Source: package/ego-browser/src/helpers.ts lines 440–460.
Complete Workflow Example
import {
listTaskSpaces,
newTaskSpace,
claimTaskSpace,
switchTaskSpace,
completeTaskSpace,
handOffTaskSpace,
takeOverTaskSpace
} from "@citrolabs/ego-browser";
async function collaborativeWorkflow() {
// 1. Discover existing user context
const spaces = await listTaskSpaces();
const userSpace = spaces.find(s => s.name === "shared-analysis");
// 2. Claim user-initiated space
if (userSpace && userSpace.ownership === "user") {
await claimTaskSpace(userSpace.id);
}
// 3. Or create fresh agent space if none exists
const workspace = userSpace
? await switchTaskSpace(userSpace.id)
: await newTaskSpace("fresh-analysis");
// 4. Do work...
// 5. Hand back to user for review
const handoff = await handOffTaskSpace();
console.log(handoff.skipped ? "Already user-owned" : "Handed off");
// 6. Later, resume control
await takeOverTaskSpace();
// 7. Complete and cleanup
await completeTaskSpace(workspace.id, { keep: false });
}
Key Source Files
| File | Responsibility |
|---|---|
package/ego-browser/src/helpers.ts |
Core facade implementation with all lifecycle helpers |
package/ego-browser/src/index.ts |
Public exports exposing the facade API |
package/ego-browser/src/state.ts |
Runtime state management used by helpers |
package/ego-browser/src/taskspace-e2e.test.mjs |
End-to-end validation of ownership transitions |
Summary
- The task space facade enforces a strict ownership boundary between agent and user contexts.
- Seven public helpers cover the complete lifecycle:
listTaskSpaces,newTaskSpace,claimTaskSpace,switchTaskSpace,useOrCreateTaskSpace,completeTaskSpace,handOffTaskSpace, andtakeOverTaskSpace. - Claiming is explicit: agents cannot accidentally manipulate user-owned spaces;
claimTaskSpaceis the required bridge. - Internal utilities (
selectTaskSpace,findTaskSpace,normalizeTaskSpace) provide consistent, maintainable abstractions over raw runtime calls. - All operations are implemented in
package/ego-browser/src/helpers.tsaccording to the citrolabs/ego-lite source code.
Frequently Asked Questions
What happens if I try to switch to a user-owned task space?
The switchTaskSpace helper throws an error. It validates that ownership === "agent" before calling ego.useTaskSpace(). You must first call claimTaskSpace to transfer ownership from user to agent.
How is useOrCreateTaskSpace different from manually checking then creating?
The helper encodes the ownership-check logic so you don't accidentally claim user spaces. If an existing space is found and user-owned, it rejects rather than proceeding, forcing explicit intent via claimTaskSpace. If no space exists, it creates a fresh agent-owned one.
Can I reuse a task space after calling completeTaskSpace?
Only if you pass { keep: true }. The default { keep: false } calls ego.closeTaskSpace(), terminating the space. The keep flag exists specifically to support reuse patterns in long-running agent workflows.
What's the difference between handOffTaskSpace and claimTaskSpace?
They are complementary opposites. handOffTaskSpace transfers control from agent to user (or no-ops if already user-owned). claimTaskSpace transfers control from user to agent. Together they enable cooperative hand-off patterns where agents and users alternate control of shared sessions.
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 →