Documentation Index
Fetch the complete documentation index at: https://woku.app/docs/llms.txt
Use this file to discover all available pages before exploring further.
Disponible en el plan Corporate. Esta funcionalidad forma parte de las capacidades empresariales de woku. Conversa con nuestro equipo comercial.
- NPS bajo asigna a supervisor: cuando una respuesta de NPS marca menor a 7, asigna al supervisor de la sucursal y le manda un WhatsApp.
- Texto con queja crítica: si la respuesta menciona la palabra “denuncia” o “abogado”, manda un email al equipo legal y abre un webhook a Salesforce.
- SLA vulnerado: si una respuesta lleva más de 60 minutos sin
ser atendida, escala a la jefatura y cambia el estado a
urgent.
Anatomía de una regla
| Campo | Tipo | Descripción |
|---|---|---|
name | string | Nombre visible. |
description | string opcional | Para qué sirve. |
trigger | { type: 'event' | 'cron', events?, cronExpression? } | Cómo se activa. |
conditions | { all: [...] } o { any: [...] } | Grupo top-level de condiciones (compatible con json-rules-engine). |
actions | array | Acciones inmediatas al matchear (orden importa). |
escalations | array | Sub-listas con afterMin para acciones diferidas. |
enabled | booleano | Si está activa. |
priority | número | Prioridad de evaluación (menor = primero). |
metrics | { totalFired, totalEscalated, lastFiredAt } | Contadores en vivo. |
Triggers
event, la regla se evalúa en cadaform-response.created. La evaluación corre en un listener, no en el path del HTTP, así que no agrega latencia al endpoint que crea la respuesta.cron, la regla se evalúa cada 5 minutos (V1) sobre las respuestas no cerradas en las últimas 72 horas. Aquí caen las reglas tipo SLA o detección de volumen bajo.
Condiciones
conditions es exactamente lo que consume json-rules-engine. La
forma mínima es:
equal, notEqual, lessThan, lessThanInclusive, greaterThan,
greaterThanInclusive, in, notIn, contains, doesNotContain.
Operadores custom Woku:
stringContains,factValue.toLowerCase().includes(jsonValue.toLowerCase()).
all representa AND, any representa OR. Para V1 el builder visual
soporta árboles de un solo nivel; la API acepta árboles anidados a
cualquier profundidad, un JSON guardado a mano funciona.
Facts disponibles
El evaluador construye un fact bag por respuesta:| Fact | Origen |
|---|---|
score | Primer valor numérico en answers. Apunta al NPS por convención. |
textConcat | Concatenación lowercased de todos los strings en answers. Útil para stringContains. |
formResponseId, formId, companyId | Ids del contexto. |
createdAt | ISO timestamp. |
sla_elapsed | Solo en cron: minutos transcurridos desde createdAt. |
cualquier key de answers | Cada campo del formulario es un fact independiente. |
Acciones
| Tipo | Parámetros | Efecto |
|---|---|---|
assign_user | userId | FormResponse.assignedTo = userId. |
change_status | status | FormResponse.status = status. Si el status nuevo cae en {closed, resolved, dismissed}, dispara cancelación de escalamientos pendientes. |
send_webhook | url, headers? | POST con { alertRuleId, alertRuleExecutionId, companyId, formResponseId, formId, facts, firedAt, isEscalation }. Timeout 10 s, retry 3x exponencial. |
send_email | to, subject? | V1 logged-only; el módulo de mail engancha esta rama en un follow-up. |
send_whatsapp | to, template?, params? | V1 logged-only; mismo plan que send_email. |
alertActionsQueue, concurrencia
10) y se ejecutan independientemente. El orden de la lista se
preserva en la cola.
Escalamientos
Cada entrada deescalations define un retraso y una sub-lista de
acciones:
delay = afterMin * 60_000. Si después la respuesta entra en un
status terminal (closed/resolved/dismissed), los jobs pendientes
se cancelan y la ejecución se marca como cerrada.
Además, los jobs de escalamiento chequean execution.closedAt antes
de ejecutarse: si el cierre fue muy reciente, el job se vuelve no-op
incluso si el removeJob no llegó a tiempo. Esto cubre la ventana
de carrera entre el cambio de estado y la cancelación.
Builder
El menú Reglas de alerta lleva al listado por empresa. Desde ahí se puede crear, editar, eliminar o probar una regla. El builder tiene cinco pestañas:- General: nombre, descripción, tipo de trigger, prioridad, habilitada.
- Condiciones: lista de condiciones leaf con operador raíz
AND/OR. Cada fila pide
fact,operator,value. La serialización convierte"7"a7,"true"atrue, valores con coma a arrays parain/notIn. - Acciones: lista drag-to-reorder con
@dnd-kit. El tipo de acción determina los campos que pide. - Escalamientos: lista de
{ afterMin, actions, cancelIfClosed }, con la misma UI de acciones anidada. - Vista previa: render del JSON exacto que se envía al servidor.
Simulador
El botón Probar en cada fila del listado abre un modal que ejecuta una simulación (dry-run). Pide un JSON conanswers y
opcionalmente extraFacts, y devuelve:
matched: si la regla habría coincidido.actionsWouldFire: la lista de acciones que se dispararían.facts: el fact bag exacto que vio el motor.
FormResponse, no envía
emails ni webhooks. Es la herramienta para validar una regla antes
de exponerla a producción.
Garantías
- Aislamiento entre reglas: cada regla se evalúa en su propio try/catch. Una regla con un operador inexistente o condiciones malformadas no impide que las demás se evalúen.
- Backpressure: las acciones corren en una cola dedicada con concurrencia 10. Una racha de respuestas no bloquea el path síncrono.
- Idempotencia: cada fire crea un
AlertRuleExecutionconactionJobIds+escalationJobIds. Los jobs de escalamiento vuelven a chequearclosedAtantes de ejecutarse. - Dedup en cron: el evaluador cron-based no dispara dos veces la misma regla contra la misma respuesta dentro de una ventana de 24 horas (la ejecución previa es el token).
- Auditable: cada CRUD de regla queda registrado en el audit
log como
alert-rule.create/update/delete.
Limitaciones conocidas (V1)
send_emailysend_whatsappson stubs que loguean la intención. El módulo de mail y el de WhatsApp engancharán esas ramas en una iteración siguiente sin cambiar el contrato del dispatcher.- Sin builder de árboles anidados: el editor visual cubre un
nivel
alloany. Para reglas con anidamiento dealldentro deany(o viceversa) hay que editar el JSON directamente vía API. - Sin agente IA como acción: el plan original menciona acciones de LangChain, quedan para una iteración futura.
- Statuses terminales hard-coded: V1 considera
{closed, resolved, dismissed}como terminales. Una iteración siguiente permitirá overrides por empresa. - El cron corre cada 5 minutos. Para reglas de SLA con SLAs muy cortos (< 5 min) la latencia perceptible es esa frecuencia.