Task Space Ownership Model in ego-lite: How Agent vs User Control Works
The ego-lite framework implements a three-tier ownership system for task spaces where the agent, agentDelegatedToUser, and user ownership values determine control permissions, with agents requiring explicit claims to access user-owned spaces.
Each task space in the ego-lite runtime functions as an isolated browser context with a strict ownership flag governing who can create, switch, or manipulate it. According to the citrolabs/ego-lite source code, this model prevents unauthorized agent interference while enabling collaborative hand-off patterns between autonomous agents and human users.
The Three Ownership States
Task spaces exist in one of three distinct ownership states defined in helpers.ts:
| Ownership value | Control semantics |
|---|---|
agent |
Full agent ownership; the agent created the space and controls it completely. |
agentDelegatedToUser |
Delegated control; the agent created the space but handed it to the user, yet retains the right to act without re-claiming. |
user |
User-created space; the agent must claim it before any manipulation or switching. |
The ownership predicate is implemented as a simple helper:
function isAgentOwned(ownership) {
return ownership === "agent" || ownership === "agentDelegatedToUser";
}
([source lines 143-144 in package/ego-browser/src/helpers.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts#L143))
This predicate gates all agent-controlled operations on task spaces.
Creating and Retrieving Task Spaces
useOrCreate: Agent-Owned Spaces Only
The taskSpaces.useOrCreate(nameOrId) method returns an existing agent-owned space or creates a new one with agent ownership. Critically, it fails on user-owned spaces:
// Returns agent-owned space or creates new agent-owned space
const task = await taskSpaces.useOrCreate('research-topic');
// Throws if matching space exists with 'user' ownership:
// "useOrCreateTaskSpace cannot use task space … with ownership …"
new: Force Fresh Agent Creation
The taskSpaces.new(name) method always creates a brand-new space with agent ownership, regardless of existing spaces.
Claiming User-Owned Spaces
When a space carries user ownership, the agent must explicitly claim it before any interaction. The taskSpaces.claim(nameOrId) operation:
- Transfers ownership from
usertoagent - Automatically selects the space for immediate use
// Claim transfers ownership and selects the space
await taskSpaces.claim(task.id);
This is the mandatory pathway for agents to access user-created contexts.
Switching Between Spaces
The taskSpaces.switch(nameOrId) method enforces strict ownership verification. It only operates on spaces where isAgentOwned() returns true:
await taskSpaces.switch(task.id); // Works only on agent-owned spaces
Attempting to switch to a non-agent-owned space produces a clear error:
switchTaskSpace requires an agent-owned task space, got ownership …
Hand-Off and Take-Over Patterns
ego-lite provides bypass methods for collaborative workflows that skip ownership checks:
| Method | Ownership transition | Use case |
|---|---|---|
taskSpaces.handOff(nameOrId?) |
agent → user |
Agent voluntarily returns control to user |
taskSpaces.takeOver(nameOrId?) |
user → agent |
Agent regains control without claim overhead |
Both methods are "no-ownership-check" shortcuts optimized for scripted collaboration patterns where explicit claim/verify cycles would add friction.
Waiting for Confirmed Control
After asynchronous hand-off scenarios, agents can ensure control before proceeding:
await taskSpaces.waitForAgentControl(task.id);
([source lines 764-766 in format.ts](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/format.ts#L764))
Completing Task Spaces
Task cleanup uses taskSpaces.complete(nameOrId, { keep }) which must be called when work finishes:
keep: false(default): Closes and destroys the spacekeep: true: Preserves the space for live-page scenarios documented inSKILL.md
Complete Workflow Example
// 1. Create or reuse an agent-owned space
const task = await taskSpaces.useOrCreate('research-topic');
// 2. Handle user-owned spaces with explicit claim
if (task.ownership === 'user') {
await taskSpaces.claim(task.id);
}
// 3. Switch to the target space (verified agent-owned)
await taskSpaces.switch(task.id);
// ... execute agent operations ...
// 4. Collaborative hand-off to user
await taskSpaces.handOff(task.id);
// 5. Later retrieval without claim overhead
await taskSpaces.takeOver(task.id);
await taskSpaces.waitForAgentControl(task.id);
// 6. Cleanup with space closure
await taskSpaces.complete(task.id, { keep: false });
Implementation Files
| File | Purpose |
|---|---|
package/ego-browser/src/helpers.ts |
Core ownership predicates, claim/switch logic, error handling |
package/ego-browser/src/format.ts |
Public API signatures and waitForAgentControl implementation |
skills/ego-browser/SKILL.md |
Human-readable API documentation with ownership semantics |
AGENTS.md |
High-level task space concepts for agent developers |
Summary
- Three ownership states govern all task space operations:
agent,agentDelegatedToUser, anduser - Agent-owned predicate (
isAgentOwned) gatesswitch()and most manipulation methods - Mandatory claim requirement for user-owned spaces prevents unauthorized agent access
- Hand-off/take-over shortcuts enable collaborative workflows without claim overhead
- Explicit completion via
complete()ensures proper resource cleanup
Frequently Asked Questions
What happens if an agent tries to useOrCreate a user-owned task space?
The call fails with a descriptive error: useOrCreateTaskSpace cannot use task space … with ownership …. The agent must instead call claim() to transfer ownership, or use new() to force creation of a fresh agent-owned space.
Can an agent act on a space after calling handOff?
No direct manipulation. After handOff(), ownership becomes user and standard methods like switch() are blocked. The agent must use takeOver() or claim() to regain control, or rely on agentDelegatedToUser status if the space was created in that mode.
What is the difference between claim and takeOver?
claim() performs full ownership verification and transfer from user to agent, suitable for unknown spaces. takeOver() is a no-check shortcut assuming the caller already knows the space should transfer—optimized for scripted recovery after handOff().
When should an agent use keep: true in complete()?
Set keep: true when the task space must persist as a live page for user inspection after agent completion, documented in SKILL.md for scenarios like delivered reports or interactive results. Default keep: false closes the browser context immediately.
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 →