Saltar al contenido principal

Documentation Index

Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

TypeBox es una biblioteca de esquemas orientada a TypeScript. La usamos para definir el protocolo WebSocket del Gateway (handshake, solicitud/respuesta, eventos del servidor). Esos esquemas impulsan la validación en tiempo de ejecución, la exportación a JSON Schema y la generación de código Swift para la app de macOS. Una única fuente de verdad; todo lo demás se genera. Si quieres el contexto de protocolo de más alto nivel, empieza con Arquitectura del Gateway.

Modelo mental (30 segundos)

Cada mensaje WS del Gateway es uno de tres frames:
  • Solicitud: { type: "req", id, method, params }
  • Respuesta: { type: "res", id, ok, payload | error }
  • Evento: { type: "event", event, payload, seq?, stateVersion? }
El primer frame debe ser una solicitud connect. Después de eso, los clientes pueden llamar a métodos (por ejemplo, health, send, chat.send) y suscribirse a eventos (por ejemplo, presence, tick, agent). Flujo de conexión (mínimo):
Client                    Gateway
  |---- req:connect -------->|
  |<---- res:hello-ok --------|
  |<---- event:tick ----------|
  |---- req:health ---------->|
  |<---- res:health ----------|
Métodos y eventos comunes:
CategoríaEjemplosNotas
Núcleoconnect, health, statusconnect debe ir primero
Mensajeríasend, agent, agent.wait, system-event, logs.taillos efectos secundarios necesitan idempotencyKey
Chatchat.history, chat.send, chat.abortWebChat usa estos
Sesionessessions.list, sessions.patch, sessions.deleteadministración de sesiones
Automatizaciónwake, cron.list, cron.run, cron.runscontrol de wake + cron
Nodesnode.list, node.invoke, node.pair.*WS del Gateway + acciones de Node
Eventostick, presence, agent, chat, health, shutdownpush del servidor
El inventario autoritativo de descubrimiento anunciado vive en src/gateway/server-methods-list.ts (listGatewayMethods, GATEWAY_EVENTS).

Dónde viven los esquemas

  • Fuente: src/gateway/protocol/schema.ts
  • Validadores en tiempo de ejecución (AJV): src/gateway/protocol/index.ts
  • Registro de características/descubrimiento anunciados: src/gateway/server-methods-list.ts
  • Handshake del servidor + despacho de métodos: src/gateway/server.impl.ts
  • Cliente de Node: src/gateway/client.ts
  • JSON Schema generado: dist/protocol.schema.json
  • Modelos Swift generados: apps/macos/Sources/OpenClawProtocol/GatewayModels.swift

Pipeline actual

  • pnpm protocol:gen
    • escribe JSON Schema (draft-07) en dist/protocol.schema.json
  • pnpm protocol:gen:swift
    • genera modelos Swift del Gateway
  • pnpm protocol:check
    • ejecuta ambos generadores y verifica que la salida esté confirmada

Cómo se usan los esquemas en tiempo de ejecución

  • Lado del servidor: cada frame entrante se valida con AJV. El handshake solo acepta una solicitud connect cuyos parámetros coincidan con ConnectParams.
  • Lado del cliente: el cliente JS valida los frames de eventos y respuestas antes de usarlos.
  • Descubrimiento de características: el Gateway envía una lista conservadora features.methods y features.events en hello-ok desde listGatewayMethods() y GATEWAY_EVENTS.
  • Esa lista de descubrimiento no es un volcado generado de todos los helpers invocables en coreGatewayHandlers; algunos RPC helpers se implementan en src/gateway/server-methods/*.ts sin enumerarse en la lista de características anunciada.

Frames de ejemplo

Connect (primer mensaje):
{
  "type": "req",
  "id": "c1",
  "method": "connect",
  "params": {
    "minProtocol": 3,
    "maxProtocol": 4,
    "client": {
      "id": "openclaw-macos",
      "displayName": "macos",
      "version": "1.0.0",
      "platform": "macos 15.1",
      "mode": "ui",
      "instanceId": "A1B2"
    }
  }
}
Respuesta Hello-ok:
{
  "type": "res",
  "id": "c1",
  "ok": true,
  "payload": {
    "type": "hello-ok",
    "protocol": 4,
    "server": { "version": "dev", "connId": "ws-1" },
    "features": { "methods": ["health"], "events": ["tick"] },
    "snapshot": {
      "presence": [],
      "health": {},
      "stateVersion": { "presence": 0, "health": 0 },
      "uptimeMs": 0
    },
    "policy": { "maxPayload": 1048576, "maxBufferedBytes": 1048576, "tickIntervalMs": 30000 }
  }
}
Solicitud + respuesta:
{ "type": "req", "id": "r1", "method": "health" }
{ "type": "res", "id": "r1", "ok": true, "payload": { "ok": true } }
Evento:
{ "type": "event", "event": "tick", "payload": { "ts": 1730000000 }, "seq": 12 }

Cliente mínimo (Node.js)

El flujo útil más pequeño: connect + health.
import { WebSocket } from "ws";

const ws = new WebSocket("ws://127.0.0.1:18789");

ws.on("open", () => {
  ws.send(
    JSON.stringify({
      type: "req",
      id: "c1",
      method: "connect",
      params: {
        minProtocol: 4,
        maxProtocol: 4,
        client: {
          id: "cli",
          displayName: "example",
          version: "dev",
          platform: "node",
          mode: "cli",
        },
      },
    }),
  );
});

ws.on("message", (data) => {
  const msg = JSON.parse(String(data));
  if (msg.type === "res" && msg.id === "c1" && msg.ok) {
    ws.send(JSON.stringify({ type: "req", id: "h1", method: "health" }));
  }
  if (msg.type === "res" && msg.id === "h1") {
    console.log("health:", msg.payload);
    ws.close();
  }
});

Ejemplo completo: añadir un método de extremo a extremo

Ejemplo: añadir una nueva solicitud system.echo que devuelve { ok: true, text }.
  1. Esquema (fuente de verdad)
Añade a src/gateway/protocol/schema.ts:
export const SystemEchoParamsSchema = Type.Object(
  { text: NonEmptyString },
  { additionalProperties: false },
);

export const SystemEchoResultSchema = Type.Object(
  { ok: Type.Boolean(), text: NonEmptyString },
  { additionalProperties: false },
);
Añade ambos a ProtocolSchemas y exporta los tipos:
  SystemEchoParams: SystemEchoParamsSchema,
  SystemEchoResult: SystemEchoResultSchema,
export type SystemEchoParams = Static<typeof SystemEchoParamsSchema>;
export type SystemEchoResult = Static<typeof SystemEchoResultSchema>;
  1. Validación
En src/gateway/protocol/index.ts, exporta un validador AJV:
export const validateSystemEchoParams = ajv.compile<SystemEchoParams>(SystemEchoParamsSchema);
  1. Comportamiento del servidor
Añade un handler en src/gateway/server-methods/system.ts:
export const systemHandlers: GatewayRequestHandlers = {
  "system.echo": ({ params, respond }) => {
    const text = String(params.text ?? "");
    respond(true, { ok: true, text });
  },
};
Regístralo en src/gateway/server-methods.ts (ya fusiona systemHandlers), luego añade "system.echo" a la entrada de listGatewayMethods en src/gateway/server-methods-list.ts. Si el método puede ser llamado por clientes operador o Node, clasifícalo también en src/gateway/method-scopes.ts para que la aplicación de alcances y el anuncio de características de hello-ok permanezcan alineados.
  1. Regenerar
pnpm protocol:check
  1. Pruebas + documentación
Añade una prueba de servidor en src/gateway/server.*.test.ts y documenta el método.

Comportamiento de la generación de código Swift

El generador Swift emite:
  • enum GatewayFrame con casos req, res, event y unknown
  • structs/enums de payload fuertemente tipados
  • valores ErrorCode, GATEWAY_PROTOCOL_VERSION y GATEWAY_MIN_PROTOCOL_VERSION
Los tipos de frame desconocidos se conservan como payloads sin procesar para compatibilidad futura.

Versionado + compatibilidad

  • PROTOCOL_VERSION vive en src/gateway/protocol/version.ts.
  • Los clientes envían minProtocol + maxProtocol; el servidor rechaza rangos que no incluyan su protocolo actual.
  • Los modelos Swift conservan los tipos de frame desconocidos para evitar romper clientes antiguos.

Patrones y convenciones de esquemas

  • La mayoría de los objetos usan additionalProperties: false para payloads estrictos.
  • NonEmptyString es el valor predeterminado para IDs y nombres de métodos/eventos.
  • El GatewayFrame de nivel superior usa un discriminador en type.
  • Los métodos con efectos secundarios suelen requerir un idempotencyKey en params (ejemplo: send, poll, agent, chat.send).
  • agent acepta internalEvents opcionales para contexto de orquestación generado en tiempo de ejecución (por ejemplo, traspaso de finalización de subagent/tarea cron); trata esto como superficie de API interna.

JSON de esquema en vivo

El JSON Schema generado está en el repositorio en dist/protocol.schema.json. El archivo sin procesar publicado suele estar disponible en:

Cuando cambias esquemas

  1. Actualiza los esquemas TypeBox.
  2. Registra el método/evento en src/gateway/server-methods-list.ts.
  3. Actualiza src/gateway/method-scopes.ts cuando el nuevo RPC necesite clasificación de alcance de operador o Node.
  4. Ejecuta pnpm protocol:check.
  5. Confirma el esquema regenerado + los modelos Swift.

Relacionado