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/wson 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.
Option 1: Set the Annotation Explicitly (Recommended)¶
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,
HTTPStakes priority overHTTP; listeners with the same protocol are ordered by listenername. 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=2and search forNo usable access gateway. Thereasonfield gives the specific cause for each Gateway, for exampleinvalid agentclaw.io/base-url annotation: gateway base URL must not contain a path.