Architecture

Gateway Protocol

Constclaw communicates with the OpenClaw gateway using a WebSocket-based JSON protocol.

Connection flow

sendToGateway() — simplifiedjs
"kw">class="c">// 1. Open WebSocket
"kw">const ws = "kw">new WebSocket("ws:">class="c">//127.0.0.1:18789");

"kw">class="c">// 2. Wait for connect.challenge event
ws.onmessage = (event) => {
  "kw">const frame = JSON.parse(event.data);

  "kw">if (frame.event === "connect.challenge") {
    "kw">const nonce = frame.payload.nonce;

    "kw">class="c">// 3. Send connect request
    ws.send(JSON.stringify({
      type: "req",
      id: "constclaw-001",
      method: "connect",
      params: {
        minProtocol: 3,
        maxProtocol: 3,
        client: { id: "constclaw-extension", version: "1.0.0",
                  platform: "browser-extension", mode: "operator" },
        role: "operator",
        scopes: ["operator.read", "operator.write"],
        auth: { token: "" },
        device: { id: "constclaw-extension", nonce },
        locale: "en-US",
      }
    }));
  }

  "kw">class="c">// 4. Receive hello-ok (handshake complete)
  "kw">if (frame.type === "res" && frame.ok) {
    "kw">class="c">// 5. Send message to agent
    ws.send(JSON.stringify({
      type: "req",
      id: "constclaw-002",
      method: "send",
      params: { message: "Explain: quantum entanglement",
                idempotencyKey: "constclaw-002" }
    }));
  }

  "kw">class="c">// 6. Receive agent response
  "kw">if (frame.event === "agent" && frame.payload?.text) {
    console.log(frame.payload.text); "kw">class="c">// ← AI response
  }
};

Wire protocol frames

json
// Request frame
{ "type": "req", "id": "unique-id", "method": "methodName", "params": {} }

// Response frame
{ "type": "res", "id": "unique-id", "ok": true, "payload": {} }

// Event frame (server push)
{ "type": "event", "event": "eventName", "payload": {}, "seq": 1 }