https://github.com/cameronapak/zo-openclaw-gateway
OpenClaw-compatible WebSocket gateway that bridges Rabbit r1 (and other OpenClaw clients) to the Zo Computer API.
https://github.com/cameronapak/zo-openclaw-gateway
ai-gateway openclaw rabbit-r1 voice-assistant websocket zo-computer
Last synced: about 18 hours ago
JSON representation
OpenClaw-compatible WebSocket gateway that bridges Rabbit r1 (and other OpenClaw clients) to the Zo Computer API.
- Host: GitHub
- URL: https://github.com/cameronapak/zo-openclaw-gateway
- Owner: cameronapak
- License: mit
- Created: 2026-05-14T21:51:04.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-06-15T13:47:29.000Z (about 1 month ago)
- Last Synced: 2026-07-14T09:39:33.498Z (3 days ago)
- Topics: ai-gateway, openclaw, rabbit-r1, voice-assistant, websocket, zo-computer
- Language: TypeScript
- Homepage:
- Size: 27.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# zo-openclaw-gateway
An OpenClaw-compatible WebSocket gateway that bridges **Rabbit r1** (and other OpenClaw clients) to the [Zo Computer](https://zo.computer) API.
Talk to your Zo from a Rabbit r1. The gateway speaks the OpenClaw operator protocol over WebSocket, so the r1 thinks it's talking to a real OpenClaw gateway, while every `chat.send` is transparently routed to Zo's `/zo/ask` endpoint.
> Built and tested against a real Rabbit r1. Originally a personal project, now open-sourced so anyone can run their own.
---
## How it works
```
Rabbit r1 ──WebSocket──▶ zo-openclaw-gateway ──HTTP──▶ Zo API (/zo/ask)
(OpenClaw protocol) (this repo) (your Zo Computer)
```
The gateway is an **adapter**, not a full OpenClaw clone. It implements just enough of the OpenClaw operator protocol to satisfy the r1's connect, session, and chat flow, then maps each request to the equivalent Zo API call.
### What it implements
| OpenClaw surface | What happens |
|---|---|
| `connect` (challenge + auth) | Bootstrap-token / device-token auth, issues reusable device tokens |
| `chat.send` (and aliases) | Routes to Zo `/zo/ask`, streams the response back as OpenClaw `chat`/`agent` events |
| `sessions.list` / `chat.history` | Backed by a local JSON state file |
| `models.list` / `agents.list` | Pulled live from Zo (`/models/available`, `/personas/available`) |
| `talk.config` / `talk.speak` / `tts.*` | Returns a `talk_unconfigured` fallback so the r1 uses its **local** TTS instead of server-side |
| `health`, `ping`, `heartbeat` | Standard keep-alive |
| QR setup (`/qr`, `/setup-code`) | Generates a scannable setup code for the r1's pairing flow |
Each OpenClaw session maps to its own Zo `conversation_id`, so conversation continuity is preserved across reconnects.
### Voice / TTS
Server-side TTS is intentionally **disabled**. The gateway returns a `talk_unconfigured` fallback signal, which tells the r1 to synthesize speech locally. This keeps your provider keys off the gateway and avoids latency. If you want server-side TTS later, the `talk.speak` and `tts.convert` handlers are the extension points.
---
## Quick start
### Prerequisites
- [Bun](https://bun.sh) runtime (v1.3+)
- A [Zo Computer](https://zo.computer) account
- A Rabbit r1 (or any OpenClaw-compatible client)
### 1. Get your Zo API key
In Zo Computer, go to **Settings → Advanced → Access Tokens** and create a token.
### 2. Configure environment
```bash
cp .env.example .env
```
Fill in:
```bash
ZO_API_KEY=your-zo-access-token
OPENCLAW_ADMIN_TOKEN=choose-a-long-random-secret
GATEWAY_PUBLIC_URL=wss://your-gateway.example.com # see deployment below
```
### 3. Install & run
```bash
bun install
bun start
```
The gateway listens on `:8787` by default.
### 4. Generate a setup code for your r1
```bash
curl -H "Authorization: Bearer $OPENCLAW_ADMIN_TOKEN" \
https://your-gateway.example.com/setup-qr
```
This returns JSON with a `qrDataUrl`. For an HTML page you can scan directly:
```bash
curl -H "Authorization: Bearer $OPENCLAW_ADMIN_TOKEN" \
https://your-gateway.example.com/qr
```
Scan the QR with the Rabbit r1's OpenClaw setup flow. The r1 connects, authenticates via the bootstrap token, receives a reusable device token, and you're talking to Zo.
---
## Deployment
The gateway is a standard Bun HTTP/WebSocket server — deploy it anywhere that exposes a public `wss://` endpoint.
### Option A: Zo Computer User Service
If you have a Zo Computer, run it as a managed HTTP service (this is how the author runs it):
1. Push this repo into your Zo workspace.
2. Register an HTTP user service with entrypoint `bun run src/server.ts`.
3. Set `ZO_API_KEY`, `OPENCLAW_ADMIN_TOKEN`, and `GATEWAY_PUBLIC_URL` as service env vars (the public `wss://.zocomputer.io` URL).
4. The service auto-starts and restarts on crash.
### Option B: Any Node/Bun host
Fly.io, Railway, Render, a VPS — anything with a public address works. Make sure `GATEWAY_PUBLIC_URL` points at the deployed `wss://` address and `PORT` is set to whatever the platform assigns.
---
## Configuration
All config is via environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
| `ZO_API_KEY` | yes | — | Zo access token |
| `OPENCLAW_ADMIN_TOKEN` | yes | — | Protects `/qr`, `/setup-code`, `/setup-qr` |
| `GATEWAY_PUBLIC_URL` | no | `ws://localhost:8787` | Public `wss://` URL for setup codes |
| `STATE_FILE` | no | `./data/state.json` | Where device tokens + session history are persisted |
| `PORT` | no | `8787` | Listen port |
---
## Development
```bash
bun install
bun test # run the test suite
bun run typecheck
bun run observe # tail structured gateway logs
```
Tests use an in-memory `FakeZoClient`, so no real Zo key is needed to run them.
### Project structure
```
src/
├── server.ts # entrypoint — reads env, boots Bun.serve
├── openclaw-gateway.ts # core: WS handler, protocol, auth, chat routing
├── zo-client.ts # HTTP client for Zo API (ask + stream + models + personas)
├── setup-code.ts # QR/setup-code encoding (clawdbot-gateway format)
├── state.ts # JSON-file-backed state store (sessions, tokens)
└── types.ts # shared types
tests/
├── gateway.test.ts # connect, chat, sessions, tool labels, TTS fallback
└── setup-code.test.ts # setup-code encode/decode round-trip
scripts/
└── observe.ts # structured-log tailer for debugging
```
---
## Protocol reference
See [`docs/protocol.md`](docs/protocol.md) for a summary of the OpenClaw operator protocol methods this gateway implements, and [`docs/architecture.md`](docs/architecture.md) for the request/response flow diagrams.
Official OpenClaw docs:
---
## Security notes
- `OPENCLAW_ADMIN_TOKEN` gates all setup-code generation. Keep it secret.
- Device tokens (`oc_dev_*`) are persisted in `STATE_FILE`. Anyone with one can connect and chat with your Zo. Treat the state file as a credential.
- The gateway redacts token/secret/password fields from structured logs, but **never log the raw state file or env in production**.
- After pairing, consider rotating your `OPENCLAW_ADMIN_TOKEN` if it was exposed during setup.
---
## License
[MIT](LICENSE) — Cam Pak
---
Built on [Zo Computer](https://zo.computer). Not affiliated with Rabbit Inc. or OpenClaw.