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
- Use password or OIDC sign-in. Native access remains unavailable with Google; see authentication limits.
- Private workspace routing already works for the target Agents. Private routing is enabled by default, but its controllers, GatewayClass, service-key Secret, and matching Installation settings must be ready. Helm rejects an explicit routing opt-out while native admin is enabled.
- A public wildcard DNS name and HTTPS certificate route traffic to the OCC API Service, not to Envoy. Use a previously unused
agentNativeAdmin.domainfor the first pilot rollout; do not reuse a domain from prior native UI experiments because OCC does not evict already registered browser service workers. - The configured Agent domain is separate from the console host and does not include a wildcard, scheme, port, or path.
- In shared-cookie mode, configure HTTPS Console and Agent DNS hosts under a common non-public suffix. OCC derives the shared session cookie domain; for
console.oce.example.comandagents.oce.example.com, it isoce.example.com. Every host that receives this cookie must be a trusted OCE ingress endpoint. The Agent suffix is required even when native access is disabled. - Each pilot Agent uses native trusted-proxy authentication with
occ-workspace-filesgrantedoperator.admin, nativecontrolUi.enabled: true, the derived Agent origin incontrolUi.allowedOrigins, and trusted-proxy device auto-approval. - Users have exact Agent
operatefor chat oradministerfor administration. A runtime must enforce the narrow chat scopes before chat-only access is available.
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:
gatewayRouting: enabled: true agentNativeAdmin: enabled: true domain: agents.oce.example.comFor an installation that already uses guarded OIDC sign-in, select host-only exchange explicitly to keep the Console cookie off Agent hosts:
agentNativeAdmin: enabled: true sessionMode: host-only-exchange domain: agents.oce.example.comKeep 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:
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: 8080The 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:
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: 8080For shared-cookie mode, verify Helm passes these API environment variables:
OCC_AGENT_NATIVE_ADMIN_ENABLED=trueOCC_AGENT_NATIVE_ADMIN_DOMAIN=agents.oce.example.comVerify 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:
https://occ.example.com/namespaces/<namespaceId>/agents/<agentId>/native-adminFor browser devtools, the same check is:
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:
{ "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:
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-nginxEach 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:
sandbox: domain: previews.example.net publicPort: 443The 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.
