Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Transporte de Socket RPC

El daemon expone una interfaz JSON-RPC 2.0 sobre un flujo IPC local, un socket de dominio Unix en Unix y un named pipe en Windows. Este es el transporte principal para clientes locales como zerocode. El gateway HTTP/WS se mantiene para webhooks, el panel de control web y los consumidores REST remotos.

Resolución de endpoint

Cada directorio de datos obtiene su propio endpoint, por lo que múltiples instancias del daemon en la misma máquina no colisionan. El directorio de datos se deriva del directorio de configuración (--config-dir / ZEROCLAW_CONFIG_DIR, o ZEROCLAW_DATA_DIR).

SOEndpoint predeterminado
Linux<data_dir>/daemon.sock (socket de dominio Unix)
macOS<data_dir>/daemon.sock (socket de dominio Unix)
Windows\\.\pipe\zeroclaw-<hash> donde <hash> se deriva de data_dir

Anula esto con la variable de entorno ZEROCLAW_SOCKET en cualquiera de las plataformas:

sh

export ZEROCLAW_SOCKET=/tmp/my-zeroclaw.sock
zeroclaw daemon

PowerShell

$env:ZEROCLAW_SOCKET = '\\.\pipe\my-zeroclaw'
zeroclaw daemon

Protocolo de cable

NDJSON (JSON delimitado por saltos de línea). Cada línea es un mensaje JSON-RPC 2.0 completo. Sin entramado HTTP, sin prefijo de longitud. El entramado es idéntico en todas las plataformas; las canalizaciones con nombre transportan el mismo flujo de bytes que los sockets de Unix.

{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":1},"id":1}\n
{"jsonrpc":"2.0","result":{"protocolVersion":1,"serverVersion":"0.8.5"},"id":1}\n

Saludo inicial

La primera llamada RPC debe ser initialize. El daemon rechaza todos los demás métodos hasta que initialize se complete correctamente. Una discrepancia en la versión del protocolo produce un error estructurado con el código -32011.

{
  "jsonrpc": "2.0",
  "método": "inicializar",
  "parámetros": {
    "protocolVersion": 1
  },
  "id": 1
}

El endpoint no requiere un token de emparejamiento. El control de acceso lo gestiona el sistema operativo:

  • Unix: el socket es 0o600, el directorio padre es 0o700.
  • Windows: la ACL de la canalización con nombre se establece de forma predeterminada para el usuario creador y SYSTEM.

Métodos

MétodoDirecciónDescripción
initializecliente -> daemonAutenticar y negociar la versión del protocolo
session/newcliente -> daemonCrea una sesión de agente (requiere agentAlias; cwd y sessionId son opcionales; keep_siblings opcional evita la expulsión de sesiones hermanas inactivas del mismo modo para clientes con varias sesiones que gestionan por sí mismos el ciclo de vida de las sesiones hermanas)
session/closecliente -> daemonCerrar y limpiar una sesión
sesión/indicacióncliente -> daemonEjecutar un turno (transmitido mediante notificaciones session/update)
session/cancelcliente -> daemonCancelar un turno en curso
statuscliente -> daemonVersión del servidor, versión del protocolo, lista de sesiones activas
session/updatedaemon -> clientNotificación de streaming durante un turno (fragmentos de texto, llamadas a herramientas, aprobaciones)
elicitation/createdaemon -> clientSolicitar entrada interactiva para los flujos de ask-user y poll

Solicitudes bidireccionales

Cualquiera de las partes puede enviar una solicitud a través del socket establecido. El receptor debe responder con el mismo id y exactamente uno de result o error. Cada par utiliza su propia secuencia zc-out-<number> para las solicitudes salientes; el prefijo no es un espacio de nombres globalmente único. La correlación sigue siendo direccional: cada par compara las respuestas únicamente con su propio mapa de solicitudes pendientes, por lo que el mismo ID textual puede estar en curso de forma independiente en direcciones opuestas.

{"jsonrpc":"2.0","método":"elicitation/create","parámetros":{"mensaje":"¿Continuar?"},"id":zc-out-0}
{"jsonrpc":"2.0","resultado":{acción:aceptar,"contenido":{respuesta:sí}},"id":zc-out-0}

Un "result": null explícito es una respuesta correcta y aun así resuelve al llamador pendiente. Un objeto error lo resuelve como un fallo. Si el par no responde, la operación ask-user o poll que la inició mantiene su comportamiento de tiempo de espera existente.

Cada trama debe ser un objeto JSON con "jsonrpc": "2.0". Las solicitudes requieren un method de tipo cadena; cuando está presente, params debe ser un objeto o una matriz. Las respuestas requieren un id de tipo cadena, numérico o nulo, y exactamente un miembro de respuesta. El JSON no válido produce -32700 (error de análisis). Una envolvente con forma de solicitud malformada produce -32600 (solicitud no válida), utilizando su ID de solicitud válido cuando se pueda recuperar. Una envolvente con forma de respuesta malformada se registra sin el contenido de la trama y se descarta sin responder, porque hacer eco de su ID podría completar una solicitud no relacionada en la dirección opuesta. Las envolventes cuya dirección es ambigua usan id: null. Los ID de respuesta válidos desconocidos también se registran y se ignoran en lugar de responder, lo que evita bucles de respuesta.

Activar streaming

session/prompt devuelve el resultado final cuando el turno se completa. Durante la ejecución, el daemon envía notificaciones session/update con eventos incrementales:

{"jsonrpc":"2.0","método":"session/update","parámetros":{"sessionId":"...","tipo":agent_message_chunk,"texto":"Hola"}}
{"jsonrpc":"2.0","método":"session/update","parámetros":{"sessionId":"...","tipo":"llamada_herramienta",toolCallId:tc_1,"nombre":bash,rawInput:{...}}}
{"jsonrpc":"2.0","método":"session/update","parámetros":{"sessionId":"...","tipo":"resultado_herramienta",toolCallId:tc_1,"nombre":bash,rawOutput:"..."}}

Tipos de evento: agent_message_chunk, agent_thought_chunk, tool_call, tool_result, approval_request.

Modo efímero

zeroclaw daemon --ephemeral rastrea los clientes conectados y se termina automáticamente cuando el último se desconecta (tras un período de gracia de 1 segundo). Una reconexión durante el período de gracia cancela el apagado. El daemon no saldrá hasta que al menos un cliente se haya conectado.

Los daemons iniciados sin --ephemeral ignoran el recuento de clientes y se ejecutan hasta que se detienen explícitamente.

Seguridad

  • Directorio de socket Unix: 0o700 (solo el propietario)
  • Archivo de socket Unix: 0o600 (solo propietario)
  • Canalización con nombre de Windows: la ACL predeterminada concede acceso al usuario creador y a SYSTEM
  • SO_PEERCRED en Linux proporciona el PID y el UID del proceso que se conecta para el registro de auditoría; Windows registra pipe:local como etiqueta del par

Prueba rápida

Inicie el daemon en una terminal:

sh

zeroclaw daemon

En una segunda terminal en Unix, conéctate con socat:

sh

socat READLINE UNIX-CONNECT:~/.zeroclaw/data/daemon.sock

Pegue las líneas una a la vez:

{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":1},"id":1}
{"jsonrpc":"2.0","method":"status","params":{},"id":2}

En Windows, usa cualquier cliente de named-pipe (PowerShell [System.IO.Pipes.NamedPipeClientStream], nc mediante WSL, o simplemente ejecuta zerocode).

Internos

La capa de despacho se encuentra en crates/zeroclaw-runtime/src/rpc/:

ArchivoRol
transport.rsrasgo RpcTransport
turn.rsexecute_turn() ejecutor de turnos compartido
session.rsRpcSession, SessionStore
dispatch.rsEnrutamiento de métodos de RpcDispatcher
local.rsLocalTransport + listener (socket Unix / canalización con nombre de Windows)
wss.rsWSS (WebSocket Secure) transporte + aceptador TLS
attachments.rsProcesamiento de carga de archivos, deduplicación, generación de marcadores

El trait RpcTransport está diseñado para que transportes adicionales (vsock, IPC personalizado) se integren sin tocar la lógica de despacho ni de sesión. El módulo local.rs envuelve las primitivas de Unix y Windows tras una única struct LocalTransport usando tokio::io::split, de modo que el bucle de lectura/escritura se comparte entre ambas plataformas.