Skip to content

Build and Connect the OpenClaw Android Node App

Setting up a mobile node for your agent often feels like a chore. You want to test camera features or chat history on a real device, but network hurdles and pairing codes get in the way. If you are looking to get the OpenClaw Android app running as a companion to your gateway, this guide covers the setup.

Note: The Android app has not been publicly released yet. The source code is available in the OpenClaw repository under apps/android. You can build it yourself using Java 17 and the Android SDK (./gradlew :app:assembleDebug). See apps/android/README.md for build instructions.

The Android app is a companion node. It doesn’t host the Gateway itself, so you’ll need that running on your main machine. Here is the quick breakdown:

System control (launchd/systemd) lives on the Gateway host. See Gateway.

The flow is straightforward: Android node app ⇄ (mDNS/NSD + WebSocket) ⇄ Gateway. Android connects directly to the Gateway WebSocket (default ws://<host>:18789) and uses device pairing (role: node).

  • You can run the Gateway on the “master” machine.
  • Android device/emulator can reach the gateway WebSocket:
    • Same LAN with mDNS/NSD, or
    • Same Tailscale tailnet using Wide-Area Bonjour / unicast DNS-SD (see below), or
    • Manual gateway host/port (fallback)
  • You can run the CLI (openclaw) on the gateway machine (or via SSH).
Terminal window
openclaw gateway --port 18789 --verbose

Confirm in logs you see something like:

  • listening on ws://0.0.0.0:18789

For tailnet-only setups (recommended for Vienna ⇄ London), bind the gateway to the tailnet IP:

  • Set gateway.bind: "tailnet" in ~/.openclaw/openclaw.json on the gateway host.
  • Restart the Gateway / macOS menubar app.

From the gateway machine:

Terminal window
dns-sd -B _openclaw-gw._tcp local.

More debugging notes: Bonjour.

Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD

Section titled “Tailnet (Vienna ⇄ London) discovery via unicast DNS-SD”

Android NSD/mDNS discovery won’t cross networks. If your Android node and the gateway are on different networks but connected via Tailscale, use Wide-Area Bonjour / unicast DNS-SD instead:

  1. Set up a DNS-SD zone (example openclaw.internal.) on the gateway host and publish _openclaw-gw._tcp records.
  2. Configure Tailscale split DNS for your chosen domain pointing at that DNS server.

Details and example CoreDNS config: Bonjour.

In the Android app:

  • The app keeps its gateway connection alive via a foreground service (persistent notification).
  • Open the Connect tab.
  • Use Setup Code or Manual mode.
  • If discovery is blocked, use manual host/port (and TLS/token/password when required) in Advanced controls.

After the first successful pairing, Android auto-reconnects on launch:

  • Manual endpoint (if enabled), otherwise
  • The last discovered gateway (best-effort).

On the gateway machine:

Terminal window
openclaw devices list
openclaw devices approve <requestId>
openclaw devices reject <requestId>

Pairing details: Pairing.

  • Via nodes status:

    Terminal window
    openclaw nodes status
  • Via Gateway:

    Terminal window
    openclaw gateway call node.list --params "{}"

The Android Chat tab supports session selection (default main, plus other existing sessions):

  • History: chat.history
  • Send: chat.send
  • Push updates (best-effort): chat.subscribe → event:"chat"
Section titled “Gateway Canvas Host (recommended for web content)”

If you want the node to show real HTML/CSS/JS that the agent can edit on disk, point the node at the Gateway canvas host.

Note: nodes load canvas from the Gateway HTTP server (same port as gateway.port, default 18789).

  1. Create ~/.openclaw/workspace/canvas/index.html on the gateway host.

  2. Navigate the node to it (LAN):

Terminal window
openclaw nodes invoke --node "<Android Node>" --command canvas.navigate --params '{"url":"http://<gateway-hostname>.local:18789/__openclaw__/canvas/"}'

Tailnet (optional): if both devices are on Tailscale, use a MagicDNS name or tailnet IP instead of .local, e.g. http://<gateway-magicdns>:18789/__openclaw__/canvas/.

This server injects a live-reload client into HTML and reloads on file changes. The A2UI host lives at http://<gateway-host>:18789/__openclaw__/a2ui/.

Canvas commands (foreground only):

  • canvas.eval, canvas.snapshot, canvas.navigate (use {"url":""} or {"url":"/"} to return to the default scaffold). canvas.snapshot returns { format, base64 } (default format="jpeg").
  • A2UI: canvas.a2ui.push, canvas.a2ui.reset (canvas.a2ui.pushJSONL legacy alias)

Camera commands (foreground only; permission-gated):

  • camera.snap (jpg)
  • camera.clip (mp4)

See Camera node for parameters and CLI helpers.

8) Voice + expanded Android command surface

Section titled “8) Voice + expanded Android command surface”
  • Voice: Android uses a single mic on/off flow in the Voice tab with transcript capture and TTS playback (ElevenLabs when configured, system TTS fallback). Voice stops when the app leaves the foreground.
  • Voice wake/talk-mode toggles are currently removed from Android UX/runtime.
  • Additional Android command families (availability depends on device + permissions):
    • device.status, device.info, device.permissions, device.health
    • notifications.list, notifications.actions
    • photos.latest
    • contacts.search, contacts.add
    • calendar.events, calendar.add
    • callLog.search
    • motion.activity, motion.pedometer

Need help with your setup? Check out the AI Setup Assistant.

OpenClaw

OpenClaw Expert

Still stuck?

If this page didn't answer your case, ask OpenClaw Expert for step-by-step guidance.