Skip to content

Gateway API Instance Access Configuration

The ClawOS instance UIs (OpenClaw web / noVNC / filebrowser) and the MS Teams callback can be exposed through a single Gateway API entry point. All an administrator has to do is prepare one labeled Gateway in the cluster; ClawOS picks it up automatically when an instance is created and generates the HTTPRoute. If no usable Gateway is found, the instance falls back to direct NodePort access — creation is never blocked.

The minimum configuration is two steps: label the Gateway with agentclaw.io/gateway: "true", then use the agentclaw.io/base-url annotation to tell ClawOS the address users access from outside. Details follow.

Prerequisites

  • The Gateway API CRDs (gateway.networking.k8s.io/v1) and a matching GatewayClass controller (kgateway, Envoy Gateway, Istio, and so on) are installed in the cluster.
  • The controller must pass WebSocket traffic through: both OpenClaw and noVNC use WS. The instance Services generated by ClawOS already carry appProtocol: kubernetes.io/ws on the relevant ports, which some implementations (kgateway) rely on to allow WebSocket.

Requirements the Gateway Must Meet

Every condition below is mandatory. A Gateway that fails any of them is skipped silently (no error is raised; the instance simply falls back to NodePort):

Condition Description
Label agentclaw.io/gateway: "true" The value must be the string "true"
At least one listener with protocol set to HTTP or HTTPS TCP / TLS / UDP listeners cannot carry an HTTPRoute
That listener has allowedRoutes.namespaces.from set to All Must be written explicitly
That listener leaves allowedRoutes.kinds unset, or includes HTTPRoute A listener that declares only GRPCRoute is unusable
An external access address can be determined That is, either a valid agentclaw.io/base-url annotation is set, or status.addresses is non-empty. See the next section

Note

ClawOS does not check the Gateway's Accepted / Programmed conditions. A Gateway can still be selected before its controller has finished programming it — the HTTPRoute is created successfully, but it only becomes reachable once the controller is ready.

Example (HTTPS listener with an explicit external domain):

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: clawos-gateway
  namespace: public
  labels:
    agentclaw.io/gateway: "true"
  annotations:
    agentclaw.io/base-url: https://agentclaw.example.com
spec:
  gatewayClassName: kgateway
  listeners:
    - name: https
      port: 443
      protocol: HTTPS
      tls:
        mode: Terminate
        certificateRefs:
          - name: agentclaw-tls
      allowedRoutes:
        namespaces:
          from: All

External Access Address (agentclaw.io/base-url)

This address is concatenated directly with the /agentclaw/<instanceID>/... prefix to form the access link handed to users, so it must be the address the user's browser actually reaches, not an in-cluster address.

Once the annotation exists it takes precedence and status.addresses is no longer consulted. The format must be scheme://host[:port]. An invalid value makes the entire Gateway unusable (fallback to NodePort).

Option 2: Omit the Annotation and Derive Automatically

The first non-empty value in status.addresses is taken and combined into <lowercase listener protocol>://<value>. The :<port> suffix is appended only when the listener port is not the default port for that protocol (HTTP 80 / HTTPS 443); IPv6 addresses are bracketed automatically.

How a Gateway Is Chosen When There Are Several

  • All labeled Gateways in the cluster are listed and sorted by namespace/name; the first one satisfying the conditions above is used. This ordering exists only to make the result reproducible — it does not mean the first one is "more suitable". Keeping exactly one labeled Gateway per cluster is recommended.
  • When one Gateway has multiple listeners, HTTPS takes priority over HTTP; listeners with the same protocol are ordered by listener name. This ordering only affects the automatically derived scheme and port; it has no effect on the final address when the annotation is set.

Generated Routes

When an instance is created, ClawOS creates an HTTPRoute named agent-route-<instanceID> in the instance's own namespace, with parentRefs pointing at the selected Gateway and ownerReferences set (so it is reclaimed automatically when the instance is deleted). Path prefixes:

Path prefix Backend
/agentclaw/<instanceID>/openclaw OpenClaw UI
/agentclaw/<instanceID>/vnc noVNC
/agentclaw/<instanceID>/files filebrowser
/agentclaw/<callbackID>/msteams MS Teams callback (port 3978)

Each prefix is rewritten to / via ReplacePrefixMatch before being forwarded to the instance Service. If there is another reverse proxy in front of the Gateway, make sure it passes these paths through verbatim and does not strip the prefix again.

When Settings Take Effect, and Troubleshooting

  • The Gateway is evaluated only when an instance is created or updated. Adding a Gateway or changing the annotation afterwards does not rewrite the HTTPRoute or access address of existing instances; the instance must be updated for the selection to run again.
  • A failure at any step (no candidate Gateway, no usable listener, invalid annotation, no address available) never blocks instance creation — it only falls back to direct NodePort access.
  • To troubleshoot, raise the apiserver log level to -v=2 and search for No usable access gateway. The reason field gives the specific cause for each Gateway, for example invalid agentclaw.io/base-url annotation: gateway base URL must not contain a path.

Comments