> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/ComposioHQ/agent-orchestrator/llms.txt
> Use this file to discover all available pages before exploring further.

# Workspace

> Plugin interface for workspace isolation strategies (git worktree, clone) providing each session with an isolated copy of the repository

## Overview

The `Workspace` interface defines how each agent session gets an isolated copy of the codebase. Workspace plugins manage repository isolation, branch setup, and post-creation hooks.

**Plugin Slot:** `workspace`\
**Default Plugin:** `worktree`

## Interface Definition

```typescript theme={null}
export interface Workspace {
  readonly name: string;
  
  create(config: WorkspaceCreateConfig): Promise<WorkspaceInfo>;
  destroy(workspacePath: string): Promise<void>;
  list(projectId: string): Promise<WorkspaceInfo[]>;
  postCreate?(info: WorkspaceInfo, project: ProjectConfig): Promise<void>;
  exists?(workspacePath: string): Promise<boolean>;
  restore?(config: WorkspaceCreateConfig, workspacePath: string): Promise<WorkspaceInfo>;
}
```

## Methods

<ResponseField name="name" type="string" required>
  Plugin name identifier (e.g. `"worktree"`, `"clone"`).
</ResponseField>

<ResponseField name="create" type="(config: WorkspaceCreateConfig) => Promise<WorkspaceInfo>" required>
  Create an isolated workspace for a session.

  **Parameters:**

  * `config.projectId` - Project identifier
  * `config.project` - Full project configuration
  * `config.sessionId` - Session identifier
  * `config.branch` - Git branch name

  **Returns:** WorkspaceInfo with path and metadata
</ResponseField>

<ResponseField name="destroy" type="(workspacePath: string) => Promise<void>" required>
  Destroy a workspace and clean up resources.

  **Parameters:**

  * `workspacePath` - Absolute path to workspace directory
</ResponseField>

<ResponseField name="list" type="(projectId: string) => Promise<WorkspaceInfo[]>" required>
  List existing workspaces for a project.

  **Parameters:**

  * `projectId` - Project identifier

  **Returns:** Array of WorkspaceInfo
</ResponseField>

<ResponseField name="postCreate" type="(info: WorkspaceInfo, project: ProjectConfig) => Promise<void>">
  Optional: Run hooks after workspace creation (symlinks, installs, etc.).

  **Parameters:**

  * `info` - Created workspace info
  * `project` - Project configuration
</ResponseField>

<ResponseField name="exists" type="(workspacePath: string) => Promise<boolean>">
  Optional: Check if a workspace exists and is a valid git repo.

  **Parameters:**

  * `workspacePath` - Path to check

  **Returns:** true if workspace exists and is valid
</ResponseField>

<ResponseField name="restore" type="(config: WorkspaceCreateConfig, workspacePath: string) => Promise<WorkspaceInfo>">
  Optional: Restore a workspace (e.g. recreate a worktree for an existing branch).

  **Parameters:**

  * `config` - Workspace creation config
  * `workspacePath` - Path where workspace should be restored

  **Returns:** WorkspaceInfo for restored workspace
</ResponseField>

## Related Types

### WorkspaceCreateConfig

```typescript theme={null}
export interface WorkspaceCreateConfig {
  projectId: string;
  project: ProjectConfig;
  sessionId: SessionId;
  branch: string;
}
```

<ParamField path="projectId" type="string" required>
  Project identifier from orchestrator config
</ParamField>

<ParamField path="project" type="ProjectConfig" required>
  Full project configuration with repo, path, symlinks, postCreate commands
</ParamField>

<ParamField path="sessionId" type="SessionId" required>
  Session identifier
</ParamField>

<ParamField path="branch" type="string" required>
  Git branch name for this workspace
</ParamField>

### WorkspaceInfo

```typescript theme={null}
export interface WorkspaceInfo {
  path: string;
  branch: string;
  sessionId: SessionId;
  projectId: string;
}
```

<ParamField path="path" type="string" required>
  Absolute path to workspace directory
</ParamField>

<ParamField path="branch" type="string" required>
  Git branch name
</ParamField>

<ParamField path="sessionId" type="SessionId" required>
  Session identifier
</ParamField>

<ParamField path="projectId" type="string" required>
  Project identifier
</ParamField>

## Usage Examples

### Implementing a Workspace Plugin

```typescript theme={null}
import type { Workspace, WorkspaceCreateConfig, WorkspaceInfo } from "@composio/ao-core";
import { execFile } from "node:child_process";
import { promisify } from "node:util";
import { mkdir, rm } from "node:fs/promises";
import { join } from "node:path";

const execFileAsync = promisify(execFile);

export function create(): Workspace {
  return {
    name: "worktree",
    
    async create(config: WorkspaceCreateConfig): Promise<WorkspaceInfo> {
      const { project, sessionId, branch } = config;
      const workspacePath = join(project.path, "..", sessionId);
      
      // Create worktree
      await execFileAsync("git", [
        "worktree",
        "add",
        "-b", branch,
        workspacePath,
        project.defaultBranch
      ], {
        cwd: project.path,
        timeout: 30_000
      });
      
      return {
        path: workspacePath,
        branch,
        sessionId,
        projectId: config.projectId
      };
    },
    
    async destroy(workspacePath: string): Promise<void> {
      // Remove worktree
      await execFileAsync("git", [
        "worktree",
        "remove",
        "--force",
        workspacePath
      ], { timeout: 30_000 });
    },
    
    async list(projectId: string): Promise<WorkspaceInfo[]> {
      // Get project config to find repo path
      const project = config.projects[projectId];
      if (!project) return [];
      
      const { stdout } = await execFileAsync("git", [
        "worktree",
        "list",
        "--porcelain"
      ], {
        cwd: project.path,
        timeout: 10_000
      });
      
      // Parse worktree list output
      const worktrees: WorkspaceInfo[] = [];
      const lines = stdout.trim().split("\n");
      
      for (let i = 0; i < lines.length; i += 3) {
        const path = lines[i].replace("worktree ", "");
        const branch = lines[i + 2]?.replace("branch refs/heads/", "") || "";
        
        // Extract session ID from path
        const sessionId = path.split("/").pop() || "";
        
        worktrees.push({
          path,
          branch,
          sessionId,
          projectId
        });
      }
      
      return worktrees;
    },
    
    async postCreate(info: WorkspaceInfo, project: ProjectConfig): Promise<void> {
      // Create symlinks
      if (project.symlinks) {
        for (const link of project.symlinks) {
          const source = join(project.path, link);
          const target = join(info.path, link);
          await execFileAsync("ln", ["-sf", source, target], {
            timeout: 5_000
          });
        }
      }
      
      // Run postCreate commands
      if (project.postCreate) {
        for (const cmd of project.postCreate) {
          await execFileAsync("sh", ["-c", cmd], {
            cwd: info.path,
            timeout: 60_000
          });
        }
      }
    },
    
    async exists(workspacePath: string): Promise<boolean> {
      try {
        await execFileAsync("git", ["rev-parse", "--git-dir"], {
          cwd: workspacePath,
          timeout: 5_000
        });
        return true;
      } catch {
        return false;
      }
    },
    
    async restore(config: WorkspaceCreateConfig, workspacePath: string): Promise<WorkspaceInfo> {
      const { project, sessionId, branch } = config;
      
      // Check if worktree already exists
      if (await this.exists!(workspacePath)) {
        return {
          path: workspacePath,
          branch,
          sessionId,
          projectId: config.projectId
        };
      }
      
      // Recreate worktree from existing branch
      await execFileAsync("git", [
        "worktree",
        "add",
        workspacePath,
        branch
      ], {
        cwd: project.path,
        timeout: 30_000
      });
      
      return {
        path: workspacePath,
        branch,
        sessionId,
        projectId: config.projectId
      };
    }
  };
}
```

### Using Workspace in Session Manager

```typescript theme={null}
import type { Workspace, WorkspaceCreateConfig } from "@composio/ao-core";

const workspace: Workspace = registry.get("workspace", "worktree");

const createConfig: WorkspaceCreateConfig = {
  projectId: "my-app",
  project: projectConfig,
  sessionId: "my-app-1",
  branch: "fix-auth-bug"
};

const info = await workspace.create(createConfig);
console.log(`Workspace created at ${info.path}`);

// Run post-creation hooks
if (workspace.postCreate) {
  await workspace.postCreate(info, projectConfig);
}

// Later: destroy workspace
await workspace.destroy(info.path);
```

## Implementation Notes

### Workspace Isolation

The workspace plugin must ensure complete isolation:

* Each session has its own branch and working directory
* No shared state between sessions (except `.git` in worktree mode)
* Symlinks can share large files (node\_modules, build artifacts)

### Post-Creation Hooks

The `postCreate()` method should:

1. Create symlinks specified in project config
2. Run postCreate commands (npm install, copy configs, etc.)
3. Handle errors gracefully (warn but don't fail)

### Restoration

The `restore()` method enables restoring sessions after:

* Machine reboot (worktrees still exist but runtime is gone)
* Manual cleanup (recreate worktree from existing branch)
* Plugin crash recovery

### Built-in Plugins

* **worktree** - Git worktrees (default, lightweight)
* **clone** - Full git clones (isolated but slower)

Future plugins could support Docker volumes, remote filesystems, cloud storage, etc.

## See Also

* [Session](/api/session) - Session interface
* [Agent](/api/agent) - Agent plugin interface
* [Runtime](/api/runtime) - Runtime execution environment interface


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.