multi-tenancy.md 3.7 KB

Multi-Tenancy

Overview

Agent PaaS is scoped by workspaces. A workspace is an isolated configuration and deployment environment: it has its own persistence backend (where CR YAML files are stored) and its own deployment target (the Kubernetes cluster or namespace where agents run). All catalog reads/writes and all live resource queries are routed to the active workspace.

Workspace

A workspace has two independent dimensions:

Persistence

Determines where CR YAML files are stored and how mutations are committed.

Type Fields Description
local directory, authorName, authorEmail Local filesystem repo via isomorphic-git
git repoUrl, branch Remote Git repository (GitHub)

Both types accept optional directory overrides in WorkspacePersistence (for example modelsDirectory, toolsDirectory, kbsDirectory, and agentsDirectory). In the current implementation, catalog constructors still use their built-in default directories.

The local type writes commits directly to the filesystem; mutations are auto-committed and the PR lifecycle is skipped. The git type writes via pull request; the PR may be auto-merged based on policy.

Deployment

Determines where live runtime status is read from.

Type Fields Description
k8s namespace, apiUrl?, token?, skipTlsVerify? Kubernetes API server (in-cluster or remote)
local No-op; no live status available

Server Initialization

At startup, Server.init() reads the workspace list and constructs one Catalog and one Resources instance, each internally keyed by workspace ID:

Server.init()
  → Catalog(workspaces)   — one GitClient + WorkspaceCatalog per workspace
  → Resources(workspaces) — one K8sClient + WorkspaceResources per workspace (k8s only)

Both are fully initialized before the first request is served. Workspace configuration is managed by WorkspaceManager (accessed via server.ws); current implementation returns a single local workspace (default).

Workspace Selection

Cookie

The active workspace is stored in the workspaceId cookie (path: '/'). On each request, hooks.server.ts reads this cookie into event.locals.workspaceId.

Default Selection

+layout.server.ts calls server.ws.list() on every page navigation and returns the full list to the frontend. It validates the current workspaceId cookie against both the workspace list and the user's permitted workspaces (user.workspaces). If invalid or absent, it resets the cookie to the first workspace in the list.

Workspace Selector UI

The workspace selector displays all workspaces the current user has access to and indicates the active one. Selecting a workspace writes the workspaceId cookie and reloads the current page.

Request Flow

Browser request
  → hooks.server.ts
      reads session cookie      → locals.user
      reads workspaceId cookie  → locals.workspaceId

  → route handler / load function
    server.catalog.getWorkspaceCatalog(locals.workspace.id)     → catalog ops
    server.resources.getWorkspaceResources(locals.workspace.id) → resource queries

If the workspace is absent or does not match any configured workspace, getWorkspaceCatalog / getWorkspaceResources throw NotFoundError.