Control UI (trình duyệt)

Control UI là một ứng dụng single-page nhỏ gọn được xây dựng bằng Vite + Lit, do Gateway phục vụ:

  • mặc định: http://<host>:18789/
  • prefix tùy chọn: đặt gateway.controlUi.basePath (ví dụ: /openclaw)

Nó giao tiếp trực tiếp với Gateway WebSocket trên cùng một port.

Mở nhanh (local)

Nếu Gateway đang chạy trên cùng máy tính, các bạn mở:

Nếu trang không load được, hãy khởi động Gateway trước: openclaw gateway.

Xác thực được cung cấp trong quá trình WebSocket handshake thông qua:

  • connect.params.auth.token
  • connect.params.auth.password

Panel cài đặt dashboard cho phép các bạn lưu token; còn password thì không được lưu lại. Wizard onboarding sẽ tạo gateway token mặc định, nên các bạn paste nó vào đây khi kết nối lần đầu.

Device pairing (kết nối lần đầu)

Khi các bạn kết nối Control UI từ một trình duyệt hoặc thiết bị mới, Gateway yêu cầu phê duyệt pairing một lần — ngay cả khi các bạn đang ở trên cùng Tailnet với gateway.auth.allowTailscale: true. Đây là biện pháp bảo mật để ngăn chặn truy cập trái phép.

Các bạn sẽ thấy: “disconnected (1008): pairing required”

Để phê duyệt thiết bị:

# Liệt kê các yêu cầu đang chờ
openclaw devices list

# Phê duyệt theo request ID
openclaw devices approve <requestId>

Sau khi được phê duyệt, thiết bị sẽ được ghi nhớ và không cần phê duyệt lại trừ khi các bạn thu hồi nó bằng openclaw devices revoke --device <id> --role <role>. Xem Devices CLI để biết thêm về token rotation và revocation.

Lưu ý:

  • Kết nối local (127.0.0.1) được tự động phê duyệt.
  • Kết nối từ xa (LAN, Tailnet, v.v.) yêu cầu phê duyệt rõ ràng.
  • Mỗi browser profile tạo ra một device ID duy nhất, nên việc chuyển trình duyệt hoặc xóa dữ liệu trình duyệt sẽ yêu cầu pairing lại.

Control UI có thể làm gì (hiện tại)

  • Chat với model thông qua Gateway WS (chat.history, chat.send, chat.abort, chat.inject)
  • Stream tool calls + live tool output cards trong Chat (agent events)
  • Channels: WhatsApp/Telegram/Discord/Slack + plugin channels (Mattermost, v.v.) status + QR login + config từng channel (channels.status, web.login.*, config.patch)
  • Instances: danh sách presence + refresh (system-presence)
  • Sessions: list + ghi đè thinking/verbose cho từng session (sessions.list, sessions.patch)
  • Cron jobs: list/add/run/enable/disable + lịch sử chạy (cron.*)
  • Skills: status, enable/disable, install, cập nhật API key (skills.*)
  • Nodes: list + caps (node.list)
  • Exec approvals: chỉnh sửa gateway hoặc node allowlists + ask policy cho exec host=gateway/node (exec.approvals.*)
  • Config: xem/chỉnh sửa ~/.openclaw/openclaw.json (config.get, config.set)
  • Config: apply + restart với validation (config.apply) và đánh thức session hoạt động cuối cùng
  • Config writes bao gồm base-hash guard để tránh ghi đè các chỉnh sửa đồng thời
  • Config schema + form rendering (config.schema, bao gồm plugin + channel schemas); Raw JSON editor vẫn có sẵn
  • Debug: status/health/models snapshots + event log + manual RPC calls (status, health, models.list)
  • Logs: live tail của gateway file logs với filter/export (logs.tail)
  • Update: chạy package/git update + restart (update.run) với restart report

Hành vi Chat

  • chat.sendnon-blocking: nó ack ngay lập tức với { runId, status: "started" } và response được stream qua chat events.
  • Gửi lại với cùng idempotencyKey sẽ trả về { status: "in_flight" } khi đang chạy, và { status: "ok" } sau khi hoàn thành.
  • chat.inject thêm một assistant note vào session transcript và broadcast một chat event cho UI-only updates (không có agent run, không có channel delivery).
  • Dừng:
    • Click Stop (gọi chat.abort)
    • /stop (hoặc stop|esc|abort|wait|exit|interrupt) để abort out-of-band
    • chat.abort hỗ trợ { sessionKey } (không có runId) để abort tất cả các runs đang hoạt động cho session đó

Truy cập Tailnet (khuyên dùng)

Integrated Tailscale Serve (ưu tiên)

Giữ Gateway trên loopback và để Tailscale Serve proxy nó với HTTPS:

openclaw gateway --tailscale serve

Mở:

  • https://<magicdns>/ (hoặc gateway.controlUi.basePath đã cấu hình của các bạn)

Mặc định, các Serve requests có thể xác thực thông qua Tailscale identity headers (tailscale-user-login) khi gateway.auth.allowTailscaletrue. OpenClaw xác minh identity bằng cách resolve địa chỉ x-forwarded-for với tailscale whois và khớp nó với header, và chỉ chấp nhận những cái này khi request đến loopback với Tailscale’s x-forwarded-* headers. Đặt gateway.auth.allowTailscale: false (hoặc force gateway.auth.mode: "password") nếu các bạn muốn yêu cầu token/password ngay cả với Serve traffic.

Bind to tailnet + token

openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"

Sau đó mở:

  • http://<tailscale-ip>:18789/ (hoặc gateway.controlUi.basePath đã cấu hình của các bạn)

Paste token vào UI settings (được gửi dưới dạng connect.params.auth.token).

Insecure HTTP

Nếu các bạn mở dashboard qua plain HTTP (http://<lan-ip> hoặc http://<tailscale-ip>), trình duyệt chạy trong non-secure context và chặn WebCrypto. Mặc định, OpenClaw chặn các kết nối Control UI không có device identity.

Cách khắc phục khuyên dùng: sử dụng HTTPS (Tailscale Serve) hoặc mở UI locally:

  • https://<magicdns>/ (Serve)
  • http://127.0.0.1:18789/ (trên gateway host)

Ví dụ downgrade (token-only qua HTTP):

{
  gateway: {
    controlUi: { allowInsecureAuth: true },
    bind: "tailnet",
    auth: { mode: "token", token: "replace-me" },
  },
}

Điều này vô hiệu hóa device identity + pairing cho Control UI (ngay cả trên HTTPS). Chỉ sử dụng nếu các bạn tin tưởng mạng.

Xem Tailscale để biết hướng dẫn thiết lập HTTPS.

Build UI

Gateway phục vụ các static files từ dist/control-ui. Build chúng bằng:

pnpm ui:build # tự động cài đặt UI deps ở lần chạy đầu tiên

Absolute base tùy chọn (khi các bạn muốn fixed asset URLs):

OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build

Để phát triển local (dev server riêng):

pnpm ui:dev # tự động cài đặt UI deps ở lần chạy đầu tiên

Sau đó trỏ UI đến Gateway WS URL của các bạn (ví dụ: ws://127.0.0.1:18789).

Debugging/testing: dev server + remote Gateway

Control UI là các static files; WebSocket target có thể cấu hình được và có thể khác với HTTP origin. Điều này tiện lợi khi các bạn muốn Vite dev server ở local nhưng Gateway chạy ở nơi khác.

  1. Khởi động UI dev server: pnpm ui:dev
  2. Mở một URL như:
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789

Xác thực một lần tùy chọn (nếu cần):

http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789&token=<gateway-token>

Lưu ý:

  • gatewayUrl được lưu trong localStorage sau khi load và bị xóa khỏi URL.
  • token được lưu trong localStorage; password chỉ được giữ trong memory.
  • Sử dụng wss:// khi Gateway đứng sau TLS (Tailscale Serve, HTTPS proxy, v.v.).

Chi tiết thiết lập truy cập từ xa: Remote access.