OpenClaw EnterpriseDOCSGitHub

Deploy native admin UI access

Enable native browser access for users with exact Agent operate or administer permission. They open chat or administration through OCC on an isolated per-Agent browser host using their ordinary OCE console session. For a local installation, use local development below. For an existing cluster, start with production installation and private Agent workspace routing.

Local development

Local setup prepares private routing and the browser endpoint. When you create an Agent in the console, select Enable browser chat before Create Agent. After deployment, select Open chat with operate permission or Open Agent UI with administer permission on that exact Agent.

The checkbox supports ordinary creation and guided provisioning after Installation native access is enabled; see creation requirements. For an existing Agent, follow Configure each Agent.

The local OpenShell quickstart includes native admin setup, browser onboarding and reopening the same conversation.

Production requirements

Install on an existing cluster

The standard production values enable this feature. Replace their example domains with your reviewed domains and keep these values alongside private gateway routing:

yaml
gatewayRouting:  enabled: true agentNativeAdmin:  enabled: true  domain: agents.oce.example.com

For an installation that already uses guarded OIDC sign-in, select host-only exchange explicitly to keep the Console cookie off Agent hosts:

yaml
agentNativeAdmin:  enabled: true  sessionMode: host-only-exchange  domain: agents.oce.example.com

Keep the existing OIDC sign-in and recovery-user settings. Console and Agent hosts must use HTTPS on the same registrable site. Google sign-in, OIDC and sandbox preview cannot be combined with this mode. The exchange creates no user or grant; the signed-in person needs operate for chat or administer for administration on the exact Agent. See the session boundary.

Expose the API Service through your existing public ingress layer. The chart does not create this route. This example shows the required shape; adapt the Ingress class, certificate, and selectors to your cluster:

yaml
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: occ-agent-native-admin  namespace: openclaw-system  annotations:    cert-manager.io/cluster-issuer: public-wildcardspec:  ingressClassName: public  tls:    - hosts:        - "*.agents.oce.example.com"      secretName: occ-agent-native-admin-wildcard-tls  rules:    - host: "*.agents.oce.example.com"      http:        paths:          - path: /            pathType: Prefix            backend:              service:                name: openclaw-enterprise-api                port:                  number: 8080

The API refuses protected requests carrying X-Forwarded-* or X-Real-IP headers, which ingress-nginx adds, unless the sender is a trusted proxy: set api.trustedProxy to preset ingress-nginx with the ingress-nginx Pod CIDR (profile installs: controlPlane.trustedProxy), or strip those headers at the ingress.

Allow ingress only to the API Pods selected for public browser traffic. Keep the Envoy Service private:

yaml
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: allow-native-admin-browser-ingress-to-api  namespace: openclaw-systemspec:  podSelector:    matchLabels:      app.kubernetes.io/name: openclaw-enterprise      app.kubernetes.io/component: api  policyTypes: ["Ingress"]  ingress:    - from:        - namespaceSelector:            matchLabels:              kubernetes.io/metadata.name: ingress-nginx          podSelector:            matchLabels:              app.kubernetes.io/name: ingress-nginx      ports:        - protocol: TCP          port: 8080

For shared-cookie mode, verify Helm passes these API environment variables:

text
OCC_AGENT_NATIVE_ADMIN_ENABLED=trueOCC_AGENT_NATIVE_ADMIN_DOMAIN=agents.oce.example.com

Verify that the session cookie is emitted once at the derived domain as __Secure-openclaw_occ_shared.session_token, with Secure, HttpOnly, and the configured SameSite behavior. Sign-out revokes the current session and expires this cookie. Clear stale OCE cookies manually if the browser reports a duplicate-cookie refusal. See shared sessions.

For host-only exchange, verify OCC_AGENT_NATIVE_ADMIN_SESSION_MODE=host-only-exchange is present and OCC_AUTH_COOKIE_DOMAIN is absent. The Console session cookie must have no Domain attribute and must not be sent to the Agent host. Open chat or Open Agent UI establishes a separate host-only Agent cookie; see session exchange.

Kubernetes Compute renders baseline gateway trust from Installation settings. Native admin availability still checks the explicit Agent policy below; keep its matching identity fields and opt-in settings in the saved Configuration.

Configure each Agent

For a new Agent, use Enable browser chat on Create Agent. Use the procedure below for existing Agents after the API feature and wildcard route are enabled. Native browser availability requires the Agent's native configuration to trust the exact derived Agent origin. In an existing authenticated console browser session, open the status URL before the final compatible redeploy:

text
https://occ.example.com/namespaces/<namespaceId>/agents/<agentId>/native-admin

For browser devtools, the same check is:

js
await fetch("/namespaces/<namespaceId>/agents/<agentId>/native-admin", {  credentials: "include",}).then((response) => response.json());

A 200 response with data.status: "unsupported" can still include data.host, data.origin, data.activeRevisionId, and data.url. Copy the exact returned data.origin, including any port. Select Open draft → Configuration → Edit Configuration to open the console Configuration editor, then merge the following JSON fields into the selected Agent's existing Configuration:

json
{  "gateway": {    "publicOrigin": "https://agent-<opaque-hash>.agents.oce.example.com",    "auth": {      "mode": "trusted-proxy",      "trustedProxy": {        "userHeader": "x-occ-identity",        "allowUsers": ["occ-workspace-files"],        "requiredHeaders": ["x-openclaw-scopes"],        "deviceAutoApprove": {          "enabled": true,          "scopes": ["operator.read", "operator.write"]        }      },      "identityScopes": {        "occ-workspace-files": ["operator.admin"]      }    },    "controlUi": {      "enabled": true,      "allowedOrigins": ["https://agent-<opaque-hash>.agents.oce.example.com"]    }  }}

Keep existing model, Harness, channel, gateway, Secret reference, and allowed origin settings. Add the exact origin to any existing allowed origins and preserve other requiredHeaders when adding x-openclaw-scopes. Chat availability requires this saved scope-header policy and a runtime that enforces the chat authority ceiling. publicOrigin is optional for native admin access: set it to the same origin so links the Agent returns, such as embedded Diffs viewer links, open through this Agent host instead of the Gateway's private address. Review any other Agents sharing this Configuration before saving; they use its new values on their next deployment. Resolve explicitly disabled UI or device approval and conflicting authentication policy with the Configuration owner instead of silently overwriting them.

The editor preserves Secret bindings. If someone saves a newer Configuration first, OCC refuses your stale save. Choose Reload draft, check your edits against the current values, then save only the changes you still intend. See Configuration update conflicts for the API contract.

Do not set unsupported gateway authentication fields, controlUi.dangerouslyDisableDeviceAuth, or controlUi.dangerouslyAllowHostHeaderOriginFallback. Deploy the updated Agent revision, then call the status route again and expect data.status: "available" with the same data.origin. For stopped or unavailable, follow the troubleshooting checks before changing configuration.

Keep durable configuration changes in OCE. For compatible Kubernetes gateways, native edits affect a Pod-local copy and are discarded when the Pod is replaced or the Agent is redeployed; persistent workspace and gateway data remain. See Kubernetes managed native configuration for the exact opt-in conditions and storage lifecycle.

Enable HTML previews

HTML previews require shared-cookie mode; host-only exchange refuses sandbox preview enablement. Previews use the runtime's separate sandbox listener. Exposing the native admin UI alone does not expose this listener: without sandbox routing, the browser may try the Agent hostname on port 8081 and report a refused connection.

Provision a wildcard HTTPS certificate and DNS for a separate preview domain, for example *.previews.example.net. This domain must be outside the derived shared cookie domain; it must not receive OCE session cookies. Keep it to 214 characters or fewer so each agent-<32 hex>. hostname fits. Store the wildcard certificate in a TLS Secret in the Helm release namespace. Enable a separate Envoy listener with explicit public ingress peers:

yaml
gatewayRouting:  sandbox:    enabled: true    domain: previews.example.net    tlsSecretName: preview-wildcard    listenerPort: 8443    ingressPeers:      - namespaceSelector:          matchLabels:            kubernetes.io/metadata.name: ingress-nginx        podSelector:          matchLabels:            app.kubernetes.io/name: ingress-nginx

Each peer is an ipBlock or namespace and Pod selectors; Helm refuses a peer the Kubernetes API would refuse.

Route the preview wildcard through your ingress to the Envoy Service's sandbox port, preserving the requested hostname and TLS server name. Keep the private administrative listener restricted. listenerPort is also the Envoy Pod port; it must be at least 1024 and differ from the private Envoy HTTPS target port. For local testing, a loopback port-forward to that Service port can provide the same TLS endpoint; normal certificate validation must succeed.

In the Installation's drivers.compute.configuration.gatewayRouting, add:

yaml
sandbox:  domain: previews.example.net  publicPort: 443

The domain must match Helm. publicPort is the browser-facing HTTPS port and may differ from Envoy's listener port; it defaults to 443. Restart the API and worker after changing startup configuration, then deploy the Agent normally. Compute derives each Agent's hostname, renders mcp.apps.sandboxOrigin and sandboxPort, and creates its Service and route. New Agents need no manual hostname mapping. Remove conflicting tenant overrides of those two native fields rather than redirecting the sandbox to the admin origin.

With or without preview routing, OpenClaw binds its MCP Apps sandbox listener on an Agent's mcp.apps.sandboxPort, else the Gateway port plus one. TCP/18791 is the private runtime status port, so Compute refuses a sandboxPort of 18791, and enabled MCP Apps without a sandboxPort when network.gatewayPort is 18790. With that Gateway port, set sandboxPort for canvas and board previews too.

Open a generated HTML file from the native chat. Verify it renders on the preview domain, the request carries no OCE session cookie, and the preview host cannot serve /console/, Gateway RPCs or workspace data. A successful shell request alone does not prove the file rendered. After replacing the Gateway Pod, reopen the same file and verify its contents are retained.

Tests

Open the console, choose a running Agent with a selected version, and verify Open Agent UI is enabled for an administrator. Its description names the version selected for service. Select Open Agent UI and confirm the Agent host loads in a new tab. Shared-cookie mode opens it directly. Host-only exchange first completes the Console-bound launch and sets __Host-occ_agent_access on the Agent host; the Console cookie stays on the Console host.

Full runtime proof still requires a real browser test that loads native assets through OCC, reconnects native WebSocket traffic, verifies the OCE session cookie never reaches the native gateway, and completes an authorized action against a disposable Agent. A native configuration edit requires Gateway managed mode to be off.

For retained overlong domains, follow domain recovery.

Troubleshooting

Match the refused request’s ID to http.completed. HTTP admission refusals carry nativeAdmissionReason; early guards and post-admission failures may omit it.

Symptom Check
Helm render fails Native access requires private gateway routing. All browser sessions require HTTPS and an Agent DNS suffix sharing a non-public suffix with the Console.
An Agent root or chat link opens the console Sign in if prompted, then open chat from the Agent detail page. The link does not reopen the original chat session. A link that cannot be resolved lands on Agents with a notice.
Helm render fails on auth.baseUrl auth.baseUrl must use HTTPS; Console and Agent hosts must share a non-public DNS suffix.
API startup fails with AUTH_BASE_URL_INVALID Check that Console and Agent DNS hosts share a non-public suffix. IP addresses and missing Agent domains are refused.
API startup fails with AUTH_SECRET_INVALID The auth.secretKey value in the auth.secretName Secret has at least 32 characters.
API startup fails with AGENT_NATIVE_ADMIN_INVALID Native access enablement, Agent domain, public origin and private gateway routing.
Console panel is hidden Feature enablement and exact Agent operate or administer permission.
Panel or status API reports stopped A stopped Agent with no selected version returns only data.status: "stopped", without an origin. Deploy the Agent if native admin access is intended.
Panel or status API reports unavailable No version is serving: there is no selected version yet, or a newer dedicated deployment stopped it and is starting or failed. Check Deployment activity, fix a failure, and redeploy.
Panel says browser chat is off The selected version's Configuration does not turn on the browser UI. Add the settings in Configure each Agent, then deploy.
Panel reports unsupported Check the selected version's native configuration requirements and Compute support for getGatewayChatEndpoint in chat mode or getGatewayEndpoint in admin mode.
Native tab cannot load Browser wildcard DNS/TLS to API, the selected session mode, host-to-Agent resolution, native controlUi.allowedOrigins, and private gateway routing.
Browser reports service-worker registration failure Expected for the pilot. OCC blocks native service-worker script requests and adds worker-src 'none' to proxied responses.
Gateway stays unready after a container restart Run diagnostics reports a failed peer-bridge-record check; logs name openclaw.json.oce-peer-bridge.json. Delete the Pod to restore the managed snapshot; native edits are lost.

Repeated sign-in

Check the session lifetime before changing configuration: password-only sessions last seven days; sessions with external sign-in enabled last eight hours. Native Agent activity does not refresh them. An Agent revision change closes native WebSockets without expiring the OCE login.

If a refreshed tab says Agent version changed, choose Return to console, then open the Agent again. The old session cannot cross a deployment.

If an open Gateway tab offers Reconnect in browser, select it. Your sign-in may have expired, or your access may have changed. If OCE asks you to sign in, it checks your access again and returns you to that Agent’s detail page. Select Open Agent UI to continue. With an older runtime, open the Agent root or its console page to start the same recovery.

If the Agent host returns 503 DEPENDENCY_UNAVAILABLE, check the controller and session store and retry after they recover.

If expiry coincides with controller restarts, check persistent session storage and whether the configured auth secret changed. In-memory sessions disappear on restart; production uses PostgreSQL. Distinguish a console 401 from an actual permission denial (403), which signing in cannot repair. That browser document navigation shows a generic 403 page whose only link is the signed-in person's Agents list. API clients and WebSocket upgrades still get the refusal without that page.

Search documentation