Bot de QQ
Lanza tareas a zqagent con el bot oficial de QQ y recibe un aviso por correo (SMTP) al terminar. Admite chat privado, chat de grupo (@bot) y canales, además de la interacción completa: aprobaciones, preguntas e interrupciones.
El bot oficial usa conexiones salientes: no necesita entrada pública y funciona también en servidores propios o de red interna.
Preparación de la plataforma (una vez)
- Regístrate en la plataforma abierta de QQ, crea un bot y obtén
AppID+AppSecret. - Solicita permisos de intents como
GROUP_AND_C2C_EVENT(1<<25) (los eventos de mensajes de chat privado y de grupo son permisos especiales; sin solicitarlos, la autenticación de la pasarela los rechaza). El @ de canal y el DM de canal corresponden aPUBLIC_GUILD_MESSAGES(1<<30) yDIRECT_MESSAGE(1<<12). - En la fase de integración usa el entorno sandbox (solo los miembros del sandbox pueden probar); la publicación oficial requiere revisión.
Configuración
Opción 1: variables de entorno .env (se leen al arrancar)
# .env
QQ_BOT_APP_ID=tuAppID
QQ_BOT_APP_SECRET=tuAppSecret
QQ_BOT_SANDBOX=1 # sandbox=1; entorno oficial=0 o vacíoOpción 2: configuración en caliente (con el servidor ya iniciado, sin reiniciar, reconecta al instante)
# Ver la configuración actual (enmascarada)
curl -s -H "Authorization: Bearer <apiKeyDelInquilino>" http://localhost:8787/api/v1/qq/config
# Configurar / actualizar
curl -s -X POST -H "Authorization: Bearer <apiKeyDelInquilino>" -H "Content-Type: application/json" \
-d '{"appId":"tuAppID","appSecret":"tuAppSecret","sandbox":true}' \
http://localhost:8787/api/v1/qq/config
# Eliminar la configuración (desconectar)
curl -s -X DELETE -H "Authorization: Bearer <apiKeyDelInquilino>" http://localhost:8787/api/v1/qq/configTras configurarlo, el registro muestra QQ 机器人: 已启用. La configuración en caliente se guarda en el servidor y sigue vigente tras reiniciar (prioridad: variables de entorno > configuración guardada).
Vinculación multiinquilino
Opción 1: un solo inquilino sin vinculación (recomendado para uso personal)
Si el sistema tiene un solo inquilino (como el demo predeterminado), no hace falta vincular nada: al enviar un mensaje se vincula automáticamente al único inquilino y la tarea empieza.
Opción 2: vinculación por código de emparejamiento (multiinquilino)
# Generar un código de emparejamiento (administrador, REST API)
curl -X POST http://localhost:8787/api/v1/qq/pairing-code \
-H "Authorization: Bearer <apiKeyDelInquilino>"
# → { "data": { "code": "AB3CD5K7", "expiresIn": 300 } }El usuario vincula desde QQ:
/bind AB3CD5K7
→ Vinculación correcta ✅ Inquilino: demo. Ahora envía un mensaje para empezar.- El código es válido 5 minutos y de un solo uso (evita que la apiKey quede en claro en el historial del chat).
- Cada conversación de QQ corresponde a un inquilino + una conversación de zqagent; la conversación se crea al enviar la primera tarea.
- El mapa de vinculaciones se guarda en
{DATA_DIR}/qq/bindings.json.
Lista de comandos
| Comando | Comportamiento |
|---|---|
| Enviar mensaje directamente | Enviar tarea (si espera pregunta, actúa como respuesta; si está en ejecución, como información adicional) |
/bind <código> | Vincular la conversación de QQ actual a un inquilino |
/unbind | Desvincular |
/new | Crear una conversación nueva y cambiar la vinculación |
/status | Ver el estado de la conversación actual |
/list | Lista de conversaciones |
/stop | Interrumpir la tarea actual |
/approve <once|always_tool|always_command|deny> | Aprobar (también puedes enviar «aceptar/todo aceptar/rechazar») |
/answer <contenido> | Responder a una pregunta |
/help | Ayuda |
Si envías un mensaje durante la ejecución, se inyecta como información adicional (steering) en la tarea actual; para empezar otra tarea, usa
/stopo espera a que termine.
Reenvío de avisos y aprobaciones
Los eventos clave de la ejecución se reenvían a la conversación de QQ correspondiente. La solicitud de aprobación incluye nombre de herramienta + argumentos + motivo:
Se requiere aprobación: write_file
Argumentos:
{
"path": "/tmp/a.txt",
"content": "hello"
}
Motivo: hay que escribir un archivo
Respuesta: aceptar (solo esta vez) / aceptar todo (permitir siempre) / rechazaraceptar/permitir/y→ permitir solo esta vez (once)aceptar todo/permitir siempre→ permitir siempre esta herramienta en esta conversación (always_tool)rechazar/n→ rechazar (deny)
⚠️ El bot oficial de QQ tiene una cuota estricta para mensajes activos; la finalización de la tarea suele superar la «ventana de respuesta pasiva de 5 minutos», por lo que el aviso de finalización usa el correo como canal fiable y el reenvío por QQ es de mejor esfuerzo.
Configurar notificaciones por correo
curl -X POST http://localhost:8787/api/v1/notifications \
-H "Authorization: Bearer <apiKeyDelInquilino>" -H "Content-Type: application/json" \
-d '{
"type": "email",
"enabled": true,
"config": {
"host": "smtp.qq.com",
"port": "465",
"secure": "true",
"user": "you@qq.com",
"pass": "<código de autorización del correo QQ>",
"from": "you@qq.com",
"to": "you@qq.com"
},
"events": { "approval": false, "question": false, "completed": true, "error": true }
}'- Correo QQ:
smtp.qq.com:465(SSL) + código de autorización (no la contraseña de acceso). - 163:
smtp.163.com:465; Gmail:smtp.gmail.com:587(secure:"false"). - Campos sensibles como
passse guardan cifrados con AES usandoSECRET_KEY. eventscontrola cuándo se dispara; el ejemplo solo envía correo al «completar/error».- Las tareas cortas no molestan:
minDurationSeconds(por defecto60); si la tarea termina con éxito y su duración no supera ese umbral, no se envía correo.
