Zalo Personal (no oficial)

Estado: experimental. Esta integración automatiza una cuenta personal de Zalo vía zca-js nativo dentro de OpenClaw.

Advertencia: Esta es una integración no oficial y puede resultar en suspensión/bloqueo de la cuenta. Úsala bajo tu propio riesgo.

Plugin requerido

Zalo Personal se distribuye como plugin y no viene incluido en la instalación base.

  • Instalar vía CLI: openclaw plugins install @openclaw/zalouser
  • O desde un checkout de código fuente: openclaw plugins install ./extensions/zalouser
  • Detalles: Plugins

No se requiere ningún binario CLI externo zca/openzca.

Configuración rápida (principiante)

  1. Instala el plugin (ver arriba).
  2. Inicia sesión (QR, en la máquina del Gateway):
    • openclaw channels login --channel zalouser
    • Escanea el código QR con la app móvil de Zalo.
  3. Habilita el canal:
{
  channels: {
    zalouser: {
      enabled: true,
      dmPolicy: "pairing",
    },
  },
}
  1. Reinicia el Gateway (o termina el onboarding).
  2. El acceso a DMs usa emparejamiento de forma predeterminada; aprueba el código de emparejamiento en el primer contacto.

Qué es

  • Se ejecuta completamente en proceso vía zca-js.
  • Usa listeners de eventos nativos para recibir mensajes entrantes.
  • Envía respuestas directamente a través de la API JS (texto/multimedia/enlace).
  • Diseñado para casos de uso de “cuenta personal” donde la API de Bot de Zalo no está disponible.

Nomenclatura

El ID del canal es zalouser para dejar explícito que automatiza una cuenta de usuario personal de Zalo (no oficial). Reservamos zalo para una posible integración futura con la API oficial de Zalo.

Encontrar IDs (directorio)

Usa el CLI de directorio para descubrir peers/grupos y sus IDs:

openclaw directory self --channel zalouser
openclaw directory peers list --channel zalouser --query "nombre"
openclaw directory groups list --channel zalouser --query "trabajo"

Límites

  • El texto saliente se fragmenta a ~2000 caracteres (límites del cliente Zalo).
  • El streaming está bloqueado de forma predeterminada.

Control de acceso (DMs)

channels.zalouser.dmPolicy soporta: pairing | allowlist | open | disabled (predeterminado: pairing).

channels.zalouser.allowFrom acepta IDs de usuario o nombres. Durante el onboarding, los nombres se resuelven a IDs usando la búsqueda de contactos en proceso del plugin.

Aprobar vía:

  • openclaw pairing list zalouser
  • openclaw pairing approve zalouser <code>

Acceso a grupos (opcional)

  • Predeterminado: channels.zalouser.groupPolicy = "open" (grupos permitidos). Usa channels.defaults.groupPolicy para anular el predeterminado cuando no está configurado.
  • Restringir a una lista de acceso con:
    • channels.zalouser.groupPolicy = "allowlist"
    • channels.zalouser.groups (las claves deben ser IDs estables de grupo; los nombres se resuelven a IDs al inicio cuando es posible)
    • channels.zalouser.groupAllowFrom (controla qué remitentes en grupos permitidos pueden activar el bot)
  • Bloquear todos los grupos: channels.zalouser.groupPolicy = "disabled".
  • El asistente de configuración puede solicitar listas de acceso de grupos.
  • Al inicio, OpenClaw resuelve nombres de grupo/usuario en las listas de acceso a IDs y registra el mapeo.
  • La coincidencia de la lista de acceso de grupo es solo por ID de forma predeterminada. Los nombres no resueltos se ignoran para autenticación a menos que channels.zalouser.dangerouslyAllowNameMatching: true esté habilitado.
  • channels.zalouser.dangerouslyAllowNameMatching: true es un modo de compatibilidad de emergencia que rehabilita la coincidencia mutable por nombre de grupo.
  • Si groupAllowFrom no está configurado, el runtime recurre a allowFrom para verificaciones de remitente de grupo.
  • Las verificaciones de remitente aplican tanto a mensajes normales de grupo como a comandos de control (por ejemplo /new, /reset).

Ejemplo:

{
  channels: {
    zalouser: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["1471383327500481391"],
      groups: {
        "123456789": { allow: true },
        "Chat de Trabajo": { allow: true },
      },
    },
  },
}

Restricción por mención en grupos

  • channels.zalouser.groups.<group>.requireMention controla si las respuestas de grupo requieren una mención.
  • Orden de resolución: ID exacto de grupo/nombre -> slug normalizado de grupo -> * -> predeterminado (true).
  • Esto aplica tanto a grupos en la lista de acceso como en modo abierto.
  • Los comandos de control autorizados (por ejemplo /new) pueden omitir la restricción por mención.
  • Cuando un mensaje de grupo se omite porque se requiere mención, OpenClaw lo almacena como historial de grupo pendiente y lo incluye en el siguiente mensaje de grupo procesado.
  • El límite de historial de grupo usa por defecto messages.groupChat.historyLimit (respaldo 50). Puedes anularlo por cuenta con channels.zalouser.historyLimit.

Ejemplo:

{
  channels: {
    zalouser: {
      groupPolicy: "allowlist",
      groups: {
        "*": { allow: true, requireMention: true },
        "Chat de Trabajo": { allow: true, requireMention: false },
      },
    },
  },
}

Multi-cuenta

Las cuentas se mapean a perfiles de zalouser en el estado de OpenClaw. Ejemplo:

{
  channels: {
    zalouser: {
      enabled: true,
      defaultAccount: "default",
      accounts: {
        work: { enabled: true, profile: "work" },
      },
    },
  },
}

Escritura, reacciones y confirmaciones de entrega

  • OpenClaw envía un evento de escritura antes de despachar una respuesta (mejor esfuerzo).
  • La acción de reacción de mensaje react es compatible para zalouser en acciones de canal.
    • Usa remove: true para eliminar un emoji de reacción específico de un mensaje.
    • Semántica de reacciones: Reacciones
  • Para mensajes entrantes que incluyen metadatos de evento, OpenClaw envía confirmaciones de entregado + visto (mejor esfuerzo).

Resolución de problemas

El inicio de sesión no persiste:

  • openclaw channels status --probe
  • Vuelve a iniciar sesión: openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser

Nombre de lista de acceso/grupo no se resolvió:

  • Usa IDs numéricos en allowFrom/groupAllowFrom/groups, o nombres exactos de amigos/grupos.

Actualización desde una configuración antigua basada en CLI:

  • Elimina cualquier suposición sobre procesos externos zca antiguos.
  • El canal ahora se ejecuta completamente dentro de OpenClaw sin binarios CLI externos.