How ego-browser Determines If a Task Space Is Agent-Owned

ego-browser treats a task space as agent-owned when its ownership property equals "agent" or "agentDelegatedToUser", enforced through the isAgentOwned() predicate in helpers.ts.

The ownership model in citrolabs/ego-lite controls which task spaces an autonomous agent can manipulate versus those reserved for human users. This article explains the exact logic, source code implementation, and API behaviors that hinge on this classification.

The Ownership Property and Valid Values

Task spaces in ego-browser carry an ownership field with three possible string values. According to the source code in package/ego-browser/src/helpers.ts (lines 118-124), these are:

  • "agent" — fully controlled by the agent
  • "agentDelegatedToUser" — agent retains ultimate ownership but has temporarily delegated control to a user
  • "user" — fully controlled by a human user, agent cannot modify without claiming

This tri-state design allows flexible hand-offs between autonomous and human-driven workflows while maintaining clear boundaries.

The isAgentOwned() Predicate Function

At the heart of ownership determination sits a single helper function defined in package/ego-browser/src/helpers.ts (lines 143-145):

function isAgentOwned(ownership) {
  return ownership === "agent" || ownership === "agentDelegatedToUser";
}

This pure predicate returns true for both direct agent ownership and delegated states, false only for "user". All higher-level helpers import and call this function rather than implementing ad-hoc checks, ensuring consistent policy enforcement.

Runtime Enforcement in Public Helpers

Functions requiring exclusive agent access validate ownership before proceeding. The switchTaskSpace implementation (lines 57-63) demonstrates this pattern:

const space = await findTaskSpace(nameOrId);
if (!isAgentOwned(space.ownership)) {
  throw new Error(
    `switchTaskSpace requires an agent-owned task space, got ownership ${JSON.stringify(space.ownership)}`,
  );
}

The error message explicitly reports the actual ownership value, aiding debugging when automation attempts to operate on user-controlled spaces.

How Ownership Affects Different API Operations

The same predicate drives divergent behaviors across the task-space façade:

Helper Behavior on User-Owned Space Behavior on Agent-Owned Space
switchTaskSpace Throws Error Selects space and continues
useOrCreateTaskSpace Selects without claiming Selects existing or creates new agent-owned
claimTaskSpace Transfers to "agent" then selects No-op, already owned
handOffTaskSpace Returns { done: false, skipped: "user-owned" } Transfers to user
completeTaskSpace Returns { done: false, skipped: "user-owned" } Marks complete and archives

This design lets agents gracefully coexist with human users—the agent never forcefully seizes control without an explicit claimTaskSpace call.

Practical Code Examples

Check ownership manually for debugging

import { listTaskSpaces } from "ego-browser";

async function printAgentOwnedSpaces() {
  const spaces = await listTaskSpaces();
  const agentOwned = spaces.filter(s => 
    s.ownership === "agent" || s.ownership === "agentDelegatedToUser"
  );
  console.log("Agent-owned task spaces:", agentOwned);
}

Switch to a task space with enforced ownership

import { switchTaskSpace } from "ego-browser";

async function goToSpace(idOrName) {
  // Throws if the target space is user-owned
  await switchTaskSpace(idOrName);
  console.log(`Switched to task space ${idOrName}`);
}

Use or create with automatic ownership handling

import { useOrCreateTaskSpace } from "ego-browser";

async function ensureSpace(name) {
  // If agent-owned: select it
  // If user-owned: select without claiming
  // If missing: create as agent-owned
  const space = await useOrCreateTaskSpace(name);
  console.log(`Operating in task space ${space.id}`);
}

Claim control of a user-owned space

import { claimTaskSpace } from "ego-browser";

async function takeControl(nameOrId) {
  const space = await claimTaskSpace(nameOrId);
  console.log(`Claimed task space ${space.id} – now agent-owned`);
}

Key Source Files

Summary

  • Agent ownership requires ownership === "agent" or ownership === "agentDelegatedToUser"
  • Single source of truth: the isAgentOwned() predicate in helpers.ts (lines 143-145)
  • Strict enforcement: functions like switchTaskSpace throw errors for user-owned spaces
  • Graceful degradation: handOffTaskSpace and completeTaskSpace skip rather than crash on user-owned spaces
  • Explicit transfers: claimTaskSpace is the only automatic path from "user" to "agent" ownership

Frequently Asked Questions

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

The function throws an Error with a descriptive message indicating that switchTaskSpace requires an agent-owned task space and reporting the actual ownership value found. This prevents accidental interference with human-controlled workspaces.

Can an agent work in a user-owned space without claiming it?

Yes. The useOrCreateTaskSpace helper selects user-owned spaces without claiming them, allowing the agent to read or observe while leaving control with the user. This supports collaborative workflows where humans and agents share context.

How does agentDelegatedToUser differ from user ownership?

agentDelegatedToUser means the agent retains ultimate ownership but has temporarily handed control to a user—the agent can reclaim without claimTaskSpace. Full "user" ownership requires an explicit claimTaskSpace call to transfer back to agent control.

Where is the ownership policy documented in the source code?

The valid ownership values and their meanings are documented in a comment block at lines 118-124 of package/ego-browser/src/helpers.ts, immediately above the helper function implementations.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →