Control UI URL Routes and Session Link Grammar

This page documents the URL structure for Control UI pages and session links, including base path configuration and session key encoding. It is intended for developers and administrators who need to understand or construct these URLs.

Read this when

  • You need to bookmark or share a Control UI session
  • You need to publish or revoke a world-readable session transcript
  • You run the Control UI behind a login proxy and need social previews to unfurl
  • You are adding or changing a Control UI route
  • You need a terminal, desktop, approval, onboarding, or remote Gateway URL

The Control UI exposes human-readable paths for its pages and session links. A configured gateway.controlUi.basePath is prepended to every path listed below. As an example, /chat/main resolves to /openclaw/chat/main when the base path is set to /openclaw.

Session and dashboard URLs

Chat and dashboard views live in parallel route namespaces:

/chat/main/deploy-monitor-6db92d48
/dashboard/main/deploy-monitor-6db92d48
/chat/main/telegram/12345
/chat/main/cron/nightly/run/8821
/chat/main

The path grammar follows this structure:

/<namespace>/<agentId>
/<namespace>/<agentId>/<sessionRef>
/<namespace>/<agentId>/<restSegment>/<restSegment>...

<namespace> accepts either /chat or /dashboard. Choosing the first option opens that agent's primary session. The remaining options encode a single immutable session key through one of two mechanisms.

The short-id mechanism applies when the session key's remainder, the portion after agent:<agentId>:, terminates in a UUID. <sessionRef> combines an optional display-name slug with a short id, for instance deploy-monitor-6db92d48. The short id carries the authority: at least eight lowercase hexadecimal characters drawn from the beginning of the key's trailing UUID, with dashes removed. Longer prefixes extending to all 32 hexadecimal characters are permitted. The row's rotating sessionId does not contribute to the URL identity.

Any other key relies on the literal-key mechanism. Each colon-delimited segment following agent:<agentId>: maps to one URL-encoded path segment. So agent:main:telegram:12345 turns into /chat/main/telegram/12345, and agent:main:cron:nightly:run:8821 becomes /chat/main/cron/nightly/run/8821.

Literal rest segments that exactly equal . or .. use ~dot and ~dotdot so browsers cannot treat them as relative path segments and collapse them. A literal segment beginning with ~ doubles that leading character to preserve reversible encoding. When an otherwise literal one-segment rest could be confused with a short id, the builder prepends ~key, for example agent:main:release-deadbeef becomes /chat/main/~key/release-deadbeef. That marker enforces literal interpretation and appears only when the unescaped form would be ambiguous.

The reserved single-segment literal rest names are main, global, boot, and sessions. The configured session.mainKey adds itself to that set at runtime. A single segment after the agent id is literal when it is reserved or fails to contain a valid short id; otherwise it counts as a short reference. Two or more segments after the agent id are always literal.

Only the configured session.mainKey reduces to the agent-only main-session path. With session.mainKey: "workspace", agent:research:workspace becomes /chat/research, whereas the distinct key agent:research:main stays as the literal path /chat/research/main.

Stability contract

The following pieces form stable URL contracts:

  • The /chat and /dashboard namespace words.
  • The key UUID short id inside short-id URLs.
  • The arity and short-versus-literal parsing rules described above.

In short-id form, the agent segment is ornamental and the slug is nearly ornamental. Neither one identifies the session by itself, and both can change without warning. The single exception is a tie: when the short id matches several sessions and only one of them still carries the slug in the link, that session gets selected, so a generated link remains functional even if two ids happen to share a prefix. A slug that matches none or multiple of the tied sessions is ignored and the disambiguation view appears. After resolution, the Control UI updates the address bar with the current agent id and current display-name slug without inserting a browser-history entry.

In literal-key form, the agent segment is authoritative because it forms part of the reconstructed session key. The remaining literal segments carry authority as well. A slug, when it exists, is always ornamental; literal-key forms never generate one.

As a best-effort convenience, an unescaped one-segment literal that fails to resolve as an exact session key is also checked against display-name slugs. One exact slug match gets swapped in the address bar for its full /<namespace>/<agentId>/<slug>-<shortId> reference. When several sessions share the slug, the UI presents the same disambiguation view used for short-id ties rather than making a guess. Exact short-id and literal-key references always take precedence over slug matching.

If one short id matches more than one session and the slug does not break the tie, the UI refrains from guessing. It displays a compact disambiguation view listing the matching display names, agents, and longer id prefixes. Choose a longer prefix to make the URL unique. Resolution inspects at most five pages of search results; if additional ones remain, the view notes that the search was incomplete instead of guessing.

Canonical links avoid ?session= and ?face=. Released links such as /chat?session=<sessionKey> are accepted only at the application boundary as a migration aid and are immediately rewritten, without adding browser history, to the canonical path. The released ?face=dashboard companion picks the /dashboard namespace during that rewrite. Loaders and page code never read the query-form identity, and new links must not emit it. The Sessions list keeps its own ?session= parameter because that parameter expands a row; it is not a session deep link. The one-shot composer value ?draft= remains supported on chat and dashboard session paths.

Route table

This table enumerates every Control UI application route. A dash indicates the route carries no route-specific URL parameters.

PageCanonical pathAliasesParameters or dynamic forms
Chat/chat-Key-backed session forms above; ?draft=<text>
Dashboard/dashboard-Key-backed session forms above; ?draft=<text>
Dashboards/dashboards--
Ask OpenClaw/custodian-?intent=new-agent, ?onboarding=1
New session/new-?agent=<agentId>, ?catalog=<catalogId>
Activity/activity--
Apps/apps--
Agents/settings/agents/agents/settings/agents/<agentId>[/<panel>]
Channels/settings/channels/channelsShared settings parameters below
Connection/settings/connection-Shared settings parameters below
Legacy General/settings/general/configRedirects to Appearance → Language
Profile/settings/profile/profileShared settings parameters below
Communications/settings/communications/communicationsShared settings parameters below
Appearance/settings/appearance/appearanceShared settings parameters below
Notifications/settings/notifications-Shared settings parameters below
Security/settings/security-Shared settings parameters below
Advanced/settings/advanced-Shared settings parameters below
Approvals/settings/approvals-Shared settings parameters below
Automation settings/settings/automation/automationShared settings parameters below
MCP/settings/mcp/mcpShared settings parameters below
Memory/settings/memory-/settings/memory/memories|dreams|settings
Infrastructure/settings/infrastructure/infrastructureShared settings parameters below
Labs/settings/labs-Shared settings parameters below
About/settings/about-Shared settings parameters below
AI and agents/settings/ai-agents/ai-agentsShared settings parameters below
Model setup/settings/model-setup/model-setup?firstRun=1
Model providers/settings/model-providers/model-providersShared settings parameters below
Import memory/memory-import/settings/memory-import-
Workboard/workboard-/workboard/<boardId>
Worktrees/worktrees/settings/worktrees-
Sessions/sessions/settings/sessions?session=<sessionKey>, ?status=archived|all
Usage/usage--
Debug/debug--
Logs/logs--
Skill Workshop/skills/workshop--
Skills/skills--
Plugins/settings/plugins-/settings/plugins/discover
Automations/cron--
Tasks/tasks--
Devices/settings/devices/nodesShared settings parameters below
Plugin tab host/plugin-?plugin=<pluginId>&id=<tabId>

Deep links backed by schemas for settings routes accept ?section=<section>, ?advanced=1, and #<setting-id>. While these values pick out content on the page, they leave the route identity untouched.

The deprecated General route, together with its /config alias, gets swapped out once for /settings/appearance?section=__appearance__#settings-language. A link pointing to the old #settings-general-model target now lands on the Models behavior section.

Memory tabs rely on the table's paths rather than ?tab=. Older Memory links carrying ?tab=memories|dreams|settings, ?tab=dreaming, ?tab=search, or ?section=memory are replaced once with the matching path, with any setting anchor preserved.

Plugin catalog tabs likewise use paths in place of ?tab=. Links that previously used ?tab=discover|installed are replaced once with the corresponding path, while other query parameters and the fragment remain intact.

Agent selection and its overview|files|tools|skills|channels|cron|memory panels follow paths. Older links with ?agent=<agentId> are replaced once with the agent path, keeping other query parameters and the fragment.

Special documents and startup modes

These documents, served by the Gateway, fall outside the application's route table:

  • /?onboarding=1 brings up the first-run onboarding presentation.
  • /?view=terminal shows the full-screen terminal-only document intended for the mobile apps. It remains available only when gateway.terminal.enabled and operator.admin are present.
  • /approve/<approvalId> opens a standalone approval document. When a base path is set, use <basePath>/approve/<approvalId>. The id points to an approval but never grants authorization; standard Gateway authentication still applies.

The approval namespace is reserved ahead of plugin HTTP routes across all HTTP methods. If Control UI serving is turned off, it responds with 404 rather than letting the request fall through to a plugin route.

Remote Gateway handoff

The Vite development UI can point at a different Gateway:

http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>

Encode a full ws:// or wss:// value with URL encoding. gatewayUrl works only in a top-level window, is stored after load, and gets stripped from the address bar. Prefer #token= since fragments avoid HTTP request logs and Referer headers. The older ?token= handoff remains a bootstrap-only credential fallback and is removed right away. Passwords persist solely in memory.

When gatewayUrl picks another Gateway, the UI does not fall back to local configuration or environment credentials. Supply the remote Gateway's token or password explicitly, and use wss:// behind TLS.

1,653 words · updated Aug 6, 2026