Configuration & CLI Gateway Config

OpenClaw Browser Relay: The Gateway Feature Nobody Talks About

Most OpenClaw builders wire up Telegram or WhatsApp and call it done. The browser relay connects any web frontend directly to your agent network — no custom backend, no polling loop, no CORS nightmare. Here's the full setup.

SR
S. Rivera
AI Infrastructure Lead
Feb 20, 2025 14 min read 6.4k views
Updated Feb 20, 2025
Key Takeaways
  • The browser relay is a WebSocket proxy built into the OpenClaw gateway that lets web browsers connect directly to your agent network
  • Enable it with three lines in gateway.yaml — no separate process, no extra dependency
  • Always set a strict allowed_origins list in production; a wildcard opens your agent network to any website
  • The relay handles session management and message queuing automatically — reconnections don't lose messages
  • Works with any JavaScript framework using the native WebSocket API or any WS-compatible library

Building a web chat interface on top of OpenClaw takes 90% less code when you use the browser relay. Without it, you need a custom backend to proxy messages, handle WebSocket connections, manage sessions, and bridge the auth gap between the browser and your gateway. With it, your frontend speaks directly to agents. Here's how to set that up correctly.

What the Browser Relay Actually Does

The browser relay is a WebSocket endpoint built into the OpenClaw gateway. It sits at /relay on your gateway URL and accepts connections from browser-based clients. When a browser sends a message through the relay, the gateway routes it to the appropriate agent channel — exactly as if it had arrived via Telegram or any other registered channel.

This matters because browsers can't authenticate with the gateway the same way a server-side agent client can. The relay bridges that gap by handling authentication at the gateway level. The browser sends a short-lived session token, the gateway validates it against its token store, and then proxies all subsequent messages to the correct agent.

The relay also handles reconnection. WebSocket connections drop. Mobile browsers kill background connections. The relay queues messages that arrive during a disconnection and delivers them when the client reconnects — provided the queue TTL hasn't expired. You configure that TTL. Most setups use 60–300 seconds depending on the expected session length.

As of early 2025, the browser relay is enabled by default in new OpenClaw installations but requires explicit configuration before it becomes functional. A gateway with no browser_relay block in gateway.yaml will refuse all relay connections with a 404.

Enabling the Browser Relay in gateway.yaml

The configuration lives in your gateway.yaml file under the browser_relay key. Here's the minimal production-ready configuration.

# gateway.yaml
gateway:
  token: "your-gateway-token"
  port: 8080

browser_relay:
  enabled: true
  allowed_origins:
    - "https://yourdomain.com"
    - "https://app.yourdomain.com"
  session_ttl: 3600          # seconds before session expires
  queue_ttl: 120             # seconds to queue messages during disconnect
  max_connections: 500       # per-gateway connection limit
  auth:
    mode: "token"            # options: token, jwt, none
    token_header: "X-Relay-Token"

The allowed_origins list is your first security layer. The gateway checks the Origin header on every incoming WebSocket handshake against this list. Requests from unlisted origins are rejected with a 403 before any authentication happens.

⚠️
Never Use a Wildcard Origin in Production

Setting allowed_origins: ["*"] means any website — including malicious ones — can initiate relay connections from a visitor's browser. This exposes your agent network to cross-site request abuse. Always list exact origins, including the protocol and subdomain.

After saving the file, restart the gateway process. The relay endpoint becomes active immediately — no additional service to start, no port to open separately. The relay runs on the same port as the rest of the gateway, multiplexed over the same connection.

Connecting From a Web Frontend

The browser side uses standard WebSocket protocol. No special SDK required — the native WebSocket API in every modern browser works fine.

// Connect to the OpenClaw browser relay
const relay = new WebSocket('wss://your-gateway.example.com/relay');

// Send authentication immediately after connection opens
relay.addEventListener('open', () => {
  relay.send(JSON.stringify({
    type: 'auth',
    token: 'your-session-token',
    channel: 'support-agent-001'
  }));
});

// Handle incoming agent messages
relay.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  if (data.type === 'message') {
    displayAgentResponse(data.content);
  }
});

// Send a user message to the agent
function sendMessage(text) {
  relay.send(JSON.stringify({
    type: 'message',
    content: text
  }));
}

// Handle disconnection with automatic reconnect
relay.addEventListener('close', () => {
  setTimeout(() => reconnect(), 2000);
});

The authentication message must be the first thing sent after the connection opens. The gateway enforces a short auth timeout — typically 5 seconds — and will close unauthenticated connections automatically. Send the auth payload in the open event handler, not in a setTimeout.

Sound familiar? This pattern is identical to how Slack, Discord, and Linear handle their real-time connections. The relay follows the same conventions those teams have proven at scale.

Generating Session Tokens

Your backend generates session tokens and passes them to the browser. The browser never holds your gateway token — it holds a short-lived session token that the gateway can validate and revoke independently. This separation is the correct architecture.

# Backend: Generate a relay session token (Python example)
import httpx

response = httpx.post(
    'https://your-gateway.example.com/api/v1/relay/sessions',
    headers={'Authorization': 'Bearer your-gateway-token'},
    json={'channel': 'support-agent-001', 'ttl': 3600}
)
session_token = response.json()['token']
# Return session_token to the browser client

Security Configuration for Production

The allowed_origins check and session token architecture cover most attack surface. There are three additional settings worth configuring before you go live.

Rate limiting per session. Without rate limits, a single browser tab can flood the relay with messages and overwhelm your LLM API quota. Add a rate_limit block under browser_relay to cap messages per session per minute.

browser_relay:
  enabled: true
  allowed_origins:
    - "https://yourdomain.com"
  rate_limit:
    messages_per_minute: 30
    burst: 10
  tls:
    enforce: true   # reject plaintext ws:// connections

TLS enforcement. Set tls.enforce: true to reject plaintext ws:// connections. Browsers on HTTPS pages will refuse ws:// connections anyway due to mixed content rules — but this setting also protects API clients hitting the relay from non-browser contexts.

Connection limits. The max_connections setting caps total concurrent relay connections across all sessions. Set it based on your gateway's available memory — each connection uses roughly 50–100KB depending on queue depth. A 2GB gateway can handle 8,000–10,000 concurrent relay connections before memory becomes a constraint.

💡
Use a Separate Gateway for Browser Traffic

If you're running both internal agent-to-agent communication and browser-facing relay connections through one gateway, consider splitting them. Browser traffic patterns — bursty, high connection count, variable session length — are different from internal agent traffic. A dedicated relay gateway lets you scale them independently.

Common Mistakes That Break the Browser Relay

  • Sending auth after a delay — wrapping the auth message in a setTimeout instead of sending it immediately in the open handler causes the gateway to close the connection before auth completes. Always send auth synchronously in the open handler.
  • Forgetting the protocol prefix — browser relay connections use wss:// (WebSocket Secure) for HTTPS gateways, not https://. Using the wrong protocol gives a cryptic connection error that looks like a CORS issue.
  • Mismatched channel IDs — the channel specified in the auth payload must exactly match a registered agent channel. Typos and case mismatches result in a silent 404 response from the relay, which looks like an auth failure in browser dev tools.
  • Not handling the close event — browser relay connections drop. Mobile networks drop them constantly. An app without a reconnect handler leaves users staring at a broken chat UI with no error message.
  • Hardcoding the gateway token in frontend code — the gateway token must never appear in browser JavaScript. Generate short-lived session tokens server-side and pass only those to the browser. The gateway token gives full control of your agent network.

Frequently Asked Questions

What is the OpenClaw browser relay?

The browser relay is a WebSocket proxy built into the OpenClaw gateway that lets browser-based clients connect directly to agent channels. It handles CORS, authentication bridging, session management, and message queuing — eliminating the need for a custom backend layer between your web frontend and your agents.

How do I enable the browser relay in gateway.yaml?

Add a browser_relay block with enabled: true and an allowed_origins list containing your frontend domain. Restart the gateway after saving. The relay endpoint becomes available immediately at /relay on your gateway URL.

Is the browser relay secure for production use?

Yes, when configured correctly. Set a strict allowed_origins list, enable token-based session authentication, enforce TLS, and configure rate limiting. Never use a wildcard origin — it allows any website to connect to your agent network from a visitor's browser.

Can I use the browser relay with any JavaScript framework?

Yes. The relay uses standard WebSocket protocol. React, Vue, Svelte, Angular, and vanilla JavaScript all work with the native WebSocket API. No special SDK is required. Any WebSocket-compatible library also works — the relay doesn't use proprietary extensions.

What happens if the browser relay drops a connection?

The relay queues messages sent during a disconnection and delivers them when the client reconnects, provided the queue_ttl hasn't expired. Configure queue_ttl in gateway.yaml to match your expected session length — 60 to 300 seconds covers most use cases.

Does the browser relay work with multiple agents simultaneously?

Yes. Each browser session can be routed to different agent channels by specifying the target channel in each message payload. One browser tab can orchestrate multiple agents. The relay multiplexes connections, so you don't need separate WebSocket connections per agent.

SR
S. Rivera
AI Infrastructure Lead

S. Rivera has deployed OpenClaw gateway configurations across cloud and on-premise environments, including browser relay setups serving tens of thousands of concurrent users. Focuses on the intersection of agent infrastructure and web application architecture.

Gateway Configuration Guides

Weekly OpenClaw config tips and infrastructure patterns, free.