Back to blog
Connecting a Rabbit R1 to a Pinata OpenClaw Agent
OpenClaw lets you talk to your AI agent through the apps you already use. Telegram, WhatsApp, Discord, iMessage. Host an agent on Pinata and it's always on, no local server to babysit.
The Rabbit R1 is a Teenage Engineering design. Bright orange, fits in your palm, has a scroll wheel that does nothing useful. It pairs with OpenClaw as a hardware node. Push the button, talk to your agent, get a response through the speaker. AI in your pocket with a fun form factor.
I wanted mine connected to my Pinata hosted agent. The Rabbit's setup script (rabbit.tech/r1-openclaw.sh) works fine for local deployments, you point at the gateway, scan a QR, done. Pinata's agent containers are secured, with HTTP auth required on every request. The R1 doesn't know how to authenticate at that layer, and threw "Invalid Auth Token" every time.
HTTP requests with the same token hit the health endpoint and came back 200. So I tailed the gateway logs while the R1 tried to connect:
[ws] ← connect client=cli ... remoteAddr=127.0.0.1
[ws] ← connect client=cli ... remoteAddr=127.0.0.1
All loopback traffic. Nothing from the R1. The gateway never saw it.
The mismatch
Pinata's platform requires HTTP auth on every request, including WebSocket upgrades. The R1 sends its token inside the WebSocket connect frame, after the HTTP handshake completes. The platform rejects the upgrade before the gateway gets a chance to validate anything.
R1 Device
│
▼
Pinata Ingress ← HTTP auth (rejects upgrade, 401)
│
▼
OpenClaw Gateway ← WS auth (never reached)
Two auth layers. The R1 authenticates at the wrong one.
I tried hacking the QR format. Embedded the token as a query param, and used full URLs in the ips field. The R1 firmware mangles all of it. Appends the port wrong, strips protocols, discards query strings. None of it reached the gateway.
I worked through this with my agent over a few sessions. We broke things along the way, both times by accidentally modifying the gateway config mid-debug. I fed the notes from those failed attempts into a fresh session with strict instructions not to touch its own gateway.
The solution uses Pinata's port forwarding feature. A proxy accepts connections without HTTP auth and forwards to the gateway over localhost. The gateway validates the token from the connect frame like normal. The agent wrote the proxy, started it, registered a custom domain via the Pinata API, generated the QR, and sent me the image over Telegram. I didn't run any commands.
The proxy:
const { createServer } = require('http');
const WebSocket = require('ws');
const server = createServer((req, res) => {
res.writeHead(200);
res.end('OK\\\\n');
});
const wss = new WebSocket.Server({ server });
wss.on('connection', (clientWs) => {
const gatewayWs = new WebSocket('ws://127.0.0.1:18789');
clientWs.on('message', (data, isBinary) => {
if (gatewayWs.readyState === WebSocket.OPEN)
gatewayWs.send(data, { binary: isBinary });
});
gatewayWs.on('message', (data, isBinary) => {
if (clientWs.readyState === WebSocket.OPEN)
clientWs.send(data, { binary: isBinary });
});
clientWs.on('close', () => gatewayWs.close());
gatewayWs.on('close', () => clientWs.close());
});
server.listen(19000, '0.0.0.0');
The custom domain registration:
curl -X POST <https://agents.pinata.cloud/v0/agents/><agent-id>/domains \\\\
-H "Authorization: Bearer $PINATA_JWT" \\\\
-H "Content-Type: application/json" \\\\
-d '{
"subdomain": "swift-fox-347",
"targetPort": 19000,
"protected": false
}'
This can also be done through the UI on https://agents.pinata.cloud/
That gives you swift-fox-347.apps.pinata.cloud. Stable hostname, no HTTP auth required.
The QR payload:
{
"type": "clawdbot-gateway",
"version": 1,
"ips": ["swift-fox-347.apps.pinata.cloud"],
"port": 443,
"token": "<gateway-auth-token>",
"protocol": "wss"
}
Scanned it. Connected. Paired. Finally.
The proxy needs to survive container restarts, so add it to your startup script or use a process manager.
What this gets you
No phone, no laptop, no typing. Hold the button, ask a question, get an answer out loud. The agent has memory, so it pulls context from earlier conversations. It knows my calendar, my notes, what we talked about yesterday.
It wrote the technical sections of this post from its own logs of our troubleshooting session.
OpenClaw is a playground. Pinata makes it always-on. The R1 puts it in your pocket. The sky is the limit with what you can build.