OpenClaw EnterpriseDOCSGitHub

Platform console request flow

Overview

/console/ renders session-authorized resources. The console reference owns user-visible behavior; API and IAM authorize access.

Entry Points

Flow

graph TD
  subgraph Browser["Browser"]
    A["Open console or change page"] --> B["Restore scoped preview or show first-load state"]
    B --> B1["Recheck session and Namespace access"]
    B1 -->|no session| C["Login"]
    C -->|GitHub| C1["Start GitHub sign-in"]
    C1 -->|callback redirect| B1
    B1 -->|authenticated| D["Read readable Namespaces and validate selection"]
    D -->|debug=true| DBG["Read accessible Agents and runtime image metadata"]
    DBG --> F
    D --> E["Request current page resource"]
    E --> E1["Edit starter JSON and select associations"]
    E1 --> S1["Select Secret or open creation modal"]
    S1 -->|select| S3["Stage binding until Apply"]
    S3 -->|apply| E1
    E --> E2["Open new version draft or admitted version by URL"]
    E2 --> E3["Save supported channel draft edit"]
    E2 --> E4["Confirm Agent deletion"]
    E2 --> E5["Confirm Agent stop"]
  end
  subgraph Controller["Controller API"]
    E --> F["Authenticate and authorize exact scope"]
    F -->|Agents or Namespaces| G["OCC reads and filters by IAM"]
    F -->|Backends and Installation admin| H["Project loaded Backend IDs and types"]
    S1 -->|create| S2["POST stores Namespace Secret immediately"]
    S2 --> S3
    E1 -->|draft runtime| M1["POST creates Configuration with staged bindings"]
    E1 -->|supported Dedicated and valid repository selection| M3["POST queues provisioning with inline Configuration"]
    M3 --> M4["Worker creates resources, grants and first deployment"]
    M1 -->|returned Configuration ID| M["POST creates Agent draft only"]
    M --> M2["Console grants Agent use of selected Secrets"]
    E2 --> N["GET draft Configuration or immutable revision"]
    E3 --> O["PATCH Configuration, then grant selected Secret access"]
    E4 --> P["DELETE exact Agent"]
    E5 --> P2["POST exact Agent stop"]
  end
  subgraph Result["Browser result"]
    G --> I["Accept only current navigation response"]
    H --> I
    M2 --> I
    M4 --> I
    N --> I
    O --> I
    P -->|accepted or uncertain| Q["Show status and refresh exact Agent"]
    P2 -->|accepted or uncertain| Q
    P2 -->|denied| K
    P -->|denied| K
    Q -->|Agent not found| R["Return to Agents list"]
    I --> J["Render list, draft, revision, or channel state"]
    F -->|denied or unavailable| K["Clear rows and show recovery"]
    J -->|Logout| L["Hide private state and confirm sign-out"]
  end

Execution Trace

1. Compose discovery metadata and serve public assets

apps/controller/src/composition/production.ts:composeProduction

apps/controller/src/composition/development-postgres.ts:composePostgresDevelopment

Startup passes safe Backend {id,type} summaries to createFastifyApp. Backend-managed delivery owns Driver activation. Requests do not reread configuration or credentials.

apps/controller/src/console-assets.ts:readConsoleAsset serves allowlisted assets and the shared HTML shell with MIME types and same-origin CSP. Unknown console paths return the shell with 404; API routes retain JSON errors.

scripts/build-console-metadata.mjs bakes the publisher's checked OCC_BUILD_REVISION into HTML. With debug=true, shell.mjs:renderShell displays the full commit; invalid or absent metadata remains unknown.

runtime-images.mjs:renderRuntimeImages issues at most three concurrent reads for readable Agents in the selected Namespace. packages/occ/src/index.ts:OpenClawController.getAgentRuntimeImages authorizes exact Agent read, resolves its active revision, then calls its Compute Driver. The Compute contract owns workload inspection and Enterprise/OpenClaw provenance. Navigation preserves debug=true; removing it stops reads. Missing provenance stays explicit.

2. Resolve the session before private reads

apps/controller/src/console/console.mjs:loadPage

loadPage advances the request generation and requests GET /api/auth/session. First loads show loading. Return navigation and Refresh can restore one of at most 16 document-local views keyed by route, Namespace, and session owner while reads run. Password fields and their derived discovery state clear before retention. Controls stay inert until admission succeeds; navigation remains available.

Completed views retain their DOM, handlers, and draft capture callbacks. On return, loadPage rereads their GET dependencies and compares data and user identity. Unchanged views reactivate without rebuilding panels; changed data rebuilds them. Pending reads, read failures, password input, or mutations prevent reuse. Read-only catalog and diagnostic POSTs do not invalidate views. Refresh always rebuilds. Debug runtime disclosures follow the same validation and retain expanded state.

A changed user or session key clears retained views and drafts before further private reads. Missing sessions open login; failed reads offer Retry. showLogin reads GET /api/auth/providers; true github/google flags add their Continue with buttons, and discovery failure keeps password login. Pending login disables all; generations reject late redirects. With sessionBinding, loadPage exchanges the button's stored attemptId once for its key. Tabs then send their pinned x-occ-session-key, so a replaced cookie yields login. authError=<provider> shows a generic, one-time error. The authentication flow owns the server side.

apps/controller/src/auth/index.ts:requireTrustedBrowserOrigin checks Origin before sign-in/out, even for SDK calls bypassing Better Auth middleware; headerless CLI requests remain supported. The browser stores no credentials.

After authentication, loadPage reads GET /namespaces, preserving URL selection or choosing the first ready/readable Namespace. Unreadable IDs stay unavailable; selection never becomes an API query selector.

shell.mjs:namespaceSelector disables and hides choices through session and Namespace checks for loads, Refresh, and admission-starting navigation; retained-view validation can extend this. Empty lists show access guidance. navigation.mjs:navigate returns Agent detail/creation to Agents; global pages remain open; recovered warnings disappear.

3. Authorize the selected page resource

apps/controller/src/index.ts:perform, requireInstallationAdmin

packages/occ/src/index.ts:OpenClawController.listNamespaces, listAgents

Agents use the selected Namespace's route. OCC authorizes Namespace reads and filters Agents by exact read permission; Namespace listing filters its Installation-wide collection. No readable selection means no Agent request. GET /backends ignores selection and requires Installation administer before returning safe startup summaries. Empty configuration returns an empty list; missing wiring or failed dependencies return errors.

apps/controller/src/console/agents/create.mjs:renderCreateAgent composes Provider, Harness, Preset, Configuration, and workspace inputs. Provider/Harness changes reset incompatible credentials and model choices while retaining unrelated JSON. The creation reference owns combinations, Preset constraints, token handling, permissions, and recovery.

agents/plugin-fields.mjs:createPluginFields edits Agent plugins separately from Configuration. Invalid JSON and untouched fields survive; clearing overrides restores inheritance. Submission, uncertain outcomes, or invalid JSON lock editing. capabilities.pluginPolicies gates policy edits; unsupported reviewers remain clearable.

create.mjs:loadPluginCatalog and loadPluginTools implement PAT discovery: the selected or Preset Secret takes precedence over an entered token. OCC reads the Secret server-side. Pagination is upstream; filtering is local. Selecting a plugin loads tools. Credential, provider, and Harness changes clear results and invalidate pending reads.

create.mjs:MODEL_CHOICES supplies unauthenticated static model lists and manual entry.

configurationTemplate enables Control UI with loopback origins on port 18789. Compute supplies gateway authentication; Presets replace the starter unchanged. Native admin access owns HTTPS isolation.

createRepositoryFields loads GET /namespaces/:namespaceId/agents/repository-options, then requests optional descriptions for visible refs. Repository admission resolves the submitted repositoryAccess. Retained drafts keep selections through failed discovery; retries recheck current policy. Only 503 REPOSITORY_OPTIONS_UNAVAILABLE permits creation without bindings, and only without retained selections; other failures block submission.

Supported Dedicated runtimes submit inline Configuration, optional repository access, and Secret references to provisioning, even after that outage. The worker reauthorizes, creates resources and exact Secret grants, and deploys; Console polls, then opens the revision.

Ordinary drafts post {kind: "agent", values, secretBindings} to POST /namespaces/:namespaceId/configurations, then submit its ID, plugins, initialWorkspaceFiles, and workspaceDefaultsId to POST /namespaces/:namespaceId/agents. Success opens revision=draft. OCC stages all four workspace textareas, including unchanged/empty values, outside Agent/Configuration for workspace setup.

create.mjs:grantConfigurationSecretAccess grants exact Secret operate for final same-Namespace env bindings. Failure retains the Agent; Retry credential access rereads grants without duplication. Failed Agent writes retain Configuration ID and lock JSON/Harness for explicit reuse. Writes never retry automatically; drafts admit no revision and start no runtime.

agents/harness-auth.mjs edits bindings and shows Secret identities, never values.

4–6. Edit the Agent and access runtime files

Agent editing traces revision rendering, channels, credentials, workspace files, stopping, and deletion; Agent sharing traces policy writes. Responses follow the ordering checks below.

channels/slack.mjs:supportSlack rejects shapes the editor cannot preserve; updatedSlack preserves untouched policies and reply overrides. The editing flow owns DM policies and channel-only reply defaults. Admission snapshots native values; Kubernetes prepareRevision carries them into openclaw.json without adding defaults.

apps/controller/src/console/agents/detail.mjs:renderAgentDetail registers tab navigation with console.mjs:loadPage. For the same Agent, Namespace, and revision, tab clicks/history replace only tab content; shell, native-admin panel, and revision controls stay mounted. Configuration and revision reads are shared; direct Workspace URLs start neither. Refresh, revision changes, and successful channel/authentication edits reload fully.

Completed tabs retain their DOM and draft capture callbacks within the detail view. Returning restores loaded controls and expanded disclosures. Pending or failed reads, password values, and mutations invalidate tab reuse. Each tab checks it is mounted before applying a response; late reads cannot overwrite another tab. Password values clear while draft captures retain edits. Channel Secret saves update the shared draft snapshot used by other tabs and deployment preflight.

7. Commit only the current response, or clear the view

apps/controller/src/console/console.mjs:loadPage, logout

Navigation, Namespace changes, and logout invalidate reads; generations reject late responses. Refocus coalesces events. Agent detail rechecks access in place, preserving controls, input, and saves; failures clear the view. Other pages revalidate before reuse; forms defer refocus. Drafts keep save baselines and Namespace scopes separate.

Authorization and dependency failures clear affected content and expose recovery; a current protected 401 clears all private state. pagehide clears private DOM, previews, and drafts even for BFCache; persisted pageshow performs a fresh load. Failure views show local reasons and bounded request IDs, never backend error text. Backend authorization denial clears every retained preview, including other Namespace selections, because the permission is Installation-wide.

The detail action flow traces confirmed Stop and Delete requests and permissions. Acceptance is not completed shutdown or deletion. Uncertain outcomes block replay until readback; only confirmed absence returns to Agents. Deployment resumes a stopped Agent through a new revision. The Agent reference owns asynchronous cleanup.

Logout first hides private state, then calls the sign-out endpoint. Confirmed success or session inspection proving absence replaces history with login. An unconfirmed logout stays blocked with Retry. The authentication flow owns server revocation; this client never infers it from a network error.

Deploy the new revision

The Create new version draft exposes Deploy new version. Operator-managed credentials persist { "method": "runtime" } and bypass managed credential setup in Console; OCC does not validate host credentials. Deployment checks the Agent, Configuration association, and generation, then sends bodyless POST /namespaces/:namespaceId/agents/:agentId/deploy. The server authorizes and admits the revision. Its read-only details open while Deployment activity follows the latest visible deployment. Workspace reads check gateway startup and file availability. An uncertain response disables replay until refresh and inspection.

Debugging and Verification

Search documentation