Referencias Open Source

Visión General

Este sección analiza los proyectos open source de referencia para la construcción de nuestra plataforma. Cada proyecto es evaluado por su arquitectura, funcionalidades, licencia, y utilidad como referencia.


Chatwoot

AspectoDetalle
Repositoriogithub.com/chatwoot/chatwoot
StackRuby on Rails 7.2, Vue 3, PostgreSQL, Redis, Sidekiq
LicenciaMIT (core), AGPL (enterprise features)
Estrellas21k+
EnfoqueGestión de conversaciones omnicanal

Arquitectura

Chatwoot sigue una arquitectura de monolito Rails con separación clara entre backend (Rails) y frontend (Vue 3).

Componentes principales:

  • Rails API: Backend REST con serializers JSON:API
  • Vue 3 Frontend: SPA con Vuex, composables
  • PostgreSQL: Base de datos principal
  • Redis: Cache, colas, pub/sub
  • Sidekiq: Procesamiento asíncrono de jobs

Channel Adapter Pattern

El patrón de adaptadores de canales es el aspecto más reutilizable de Chatwoot:

Inbox (polimórfico)
├── Channel::WebWidget
├── Channel::Facebook
├── Channel::Twitter
├── Channel::WhatsApp
├── Channel::Email
├── Channel::Telegram
├── Channel::Line
├── Channel::Sms
├── Channel::Api
├── Channel::WhatsApp (Twilio)
├── Channel::Instagram
└── Channel::Signal

Conceptos clave:

  • Inbox: Representa un canal de entrada (polimórfico)
  • Channel: Implementación específica del canal
  • Conversation: Hilo de mensajes con un contacto
  • Message: Un mensaje individual (texto, archivo, etc.)

Event Dispatching

Chatwoot implementa un sistema de eventos basado en callbacks de ActiveJob:

  • Eventos de conversación (creada, actualizada, resuelta)
  • Eventos de mensaje (recibido, enviado, leído)
  • Eventos de agente (asignado, removido)
  • Webhooks configurables por tenant

License

MIT (core): Licencia permisiva que permite:

  • Uso comercial
  • Modificación sin开源
  • Distribución sin开源
  • Uso en productos proprietarios

Enterprise features (AGPL): Algunas funcionalidades avanzadas como SSO, macros, y reportes están bajo AGPL.

¿Qué Reutilizar?

Aspecto¿Reutilizar?Notas
Patrón de canales polimórficosSí (como referencia)Modelo conceptual, no código
Event dispatchingSí (como referencia)Patrón de diseño
Conversation lifecycleSí (como referencia)Estados y transiciones
Código fuenteNoLicencia MIT lo permite, pero es Ruby

Zammad

AspectoDetalle
Repositoriogithub.com/zammad/zammad
StackRuby on Rails 8.0, Vue 3, PostgreSQL, GraphQL
LicenciaAGPL-3.0
Estrellas6k+
EnfoqueHelpdesk y ticketing

Arquitectura

Zammad es un sistema de helpdesk/ticketing con arquitectura moderna:

  • Rails 8.0: Backend con Hotwire/Turbo
  • Vue 3: Frontend SPA
  • PostgreSQL: Base de datos
  • GraphQL API: API moderna para el frontend
  • Elasticsearch: Búsqueda full-text (opcional)

Fortalezas

  1. RBAC (Role-Based Access Control): 53 políticas de permisos granulares
  2. SLA y Escalación: Sistema completo de SLA con reglas de escalamiento automático
  3. Knowledge Base: Sistema de artículos de ayuda integrado
  4. Ticket States: Estados personalizables con transiciones
  5. Triggers: Sistema de automatización basado en reglas
  6. Reporting: Dashboards y reportes personalizables

Debilidades

  1. Enfoque en ticketing: No es un contact center completo (sin discador, IVR)
  2. Sin telefónica nativa: Integra con sistemas externos pero no tiene su propia pila telefónica

License

AGPL-3.0: Licencia fuertemente copyleft:

Escenario¿Permitido?
Usar como referencia conceptual
Copiar fragmentos de códigoNo
Modificar internamente y usarNo (obliga a开源 todo)
Distribuir como servicio SaaSNo (obliga a开源)
Estudiar patrones de diseño

Decisión

No reutilizar código. Estudiar únicamente los patrones de diseño y funcionalidades.


VICIdial

AspectoDetalle
Repositoriosourceforge.net/projects/vicidial
StackPerl, PHP, MySQL, Apache (LAMP)
LicenciaAGPLv2
EnfoqueDialer y campañas outbound
Producción15+ años en producción activa

Arquitectura

VICIdial es un sistema de discador maduro con arquitectura LAMP legacy:

  • Perl: Core del discador y servicios
  • PHP: Interfaz web
  • MySQL: Base de datos
  • Asterisk: Sustrato telefónica

Modos de Discador

VICIdial implementa 6 modos de discador:

ModoDescripción
ManualAgente marca uno a uno
AdaptiveAjusta ratio basado en respuestas
PredictivePredice disponibilidad de agentes
PowerRatio fijo de llamadas paralelas
ProgressiveUna llamada por agente disponible
AgentEl agente controla la marcación

Algoritmo de Pacing

El algoritmo de pacing adaptativo es el activo más valioso de VICIdial:

Parámetros clave:

  • ratio: Número de llamadas por agente disponible
  • drop_percentage: Porcentaje máximo de llamadas abandonadas
  • avg_hold_time: Tiempo promedio de espera
  • calls_per_minute: Llamadas por minuto

Lógica adaptativa:

  1. Calcula ratio basado en agentes disponibles y métricas históricas
  2. Ajusta ratio en tiempo real basado en:
    • Tasa de respuesta
    • Tiempo promedio de llamada
    • Abandon rate
    • Disponibilidad de agentes
  3. Limita por drop_percentage máximo (típicamente 3%)

License

AGPLv2: Similar a AGPL-3.0 pero versión 2. Restricciones equivalentes.

¿Qué Reutilizar?

Aspecto¿Reutilizar?Notas
Algoritmo de pacingSí (como referencia)Lógica transferible a Go
Estados de campañaSí (como referencia)Ciclo de vida completo
Código fuenteNoPerl/PHP legacy, AGPLv2

Omnidialer

AspectoDetalle
Repositoriogithub.com/omnidialer/omnidialer
StackPython 3.12, Flask, Gearman, PostgreSQL, Redis
LicenciaNo especificada
EnfoqueDiscador basado en ARI

Arquitectura

Omnidialer es un discador moderno que utiliza ARI (Asterisk REST Interface) en lugar de AMI:

  • Python 3.12: Lenguaje moderno, tipado opcional
  • Flask: Framework web ligero
  • Gearman: Distribución de trabajo
  • PostgreSQL: Persistencia
  • Redis: Cache y colas

Integración vía ARI

Omnidialer demuestra la integración moderna con Asterisk:

Omnidialer → ARI REST API → Asterisk
                        ← WebSocket events

Ventajas de ARI vs AMI:

  • API REST moderna y bien documentada
  • WebSocket para eventos en tiempo real
  • Control granular de canales y bridges
  • Mejor soporte para aplicaciones de terceros

Modos de Discador

  • Predictive: Algoritmo adaptativo
  • Power: Ratio fijo

License

No especificada. Se requiere verificación antes de usar cualquier código.

¿Qué Reutilizar?

Aspecto¿Reutilizar?Notas
Patrón de integración ARISí (como referencia)Excelente modelo para Go
Código fuenteVerificarSin licencia especificada

Asterisk

AspectoDetalle
Repositoriogithub.com/asterisk/asterisk
StackC, dynamic module loading
LicenciaGPLv2 con excepción de protocolo
EnfoquePlataforma telefónica completa
Producción25+ años, estándar de facto

Arquitectura

Asterisk es una plataforma de comunicaciones unificada:

  • C: Core de alto rendimiento
  • Dynamic modules: Carga dinámica de módulos
  • Multiple interfaces: CLI, AMI, ARI, AGI
  • Codec support: Transcoding completo

Interfaces de Control

InterfaceDescripciónUso Recomendado
CLICommand-line interfaceAdministración, debugging
AMIAsterisk Manager InterfaceLegacy, integración antigua
ARIAsterisk REST InterfaceRecomendado: Integración moderna
AGIAsterisk Gateway InterfaceScripts de IVR legacy

ARI (Asterisk REST Interface)

ARI es la interfaz moderna para controlar Asterisk desde aplicaciones externas:

Capacidades:

  • Crear/destruir canales
  • Controle de bridges (conference, transfers)
  • IVR navigation
  • Play/record audio
  • Eventos en tiempo real vía WebSocket

Endpoints principales:

  • GET /channels - Listar canales activos
  • POST /channels/create - Crear un canal
  • POST /channels/{id}/answer - Contestar llamada
  • POST /channels/{id}/play - Reproducir audio
  • POST /channels/{id}/record - Grabar audio
  • POST /channels/{id}/redirect - Redirigir
  • `DELETE /channels/{id}# - Colgar

License

GPLv2 con excepción de protocolo:

Escenario¿Permitido?
Usar ARI desde aplicación proprietaria (excepción de protocolo)
Modificar el core de AsteriskNo (obliga a开源)
Distribuir Asterisk modificadoNo (obliga a开源)
Usar como servicio externo
Comunicarse vía REST/WebSocket

La excepción de protocolo permite que aplicaciones externas se comuniquen con Asterisk sin obligar a que la aplicación sea GPL. Esto es crítico para nuestro producto.

Decisión

Usar Asterisk como sustrato telefónica vía ARI. Nunca reimplementar SIP/RTP. Comunicación exclusiva vía REST API y WebSocket.


Tabla Comparativa

AspectoOMniLeadsChatwootZammadVICIdialOmnidialerAsterisk
LenguajePythonRubyRubyPerl/PHPPythonC
FrameworkDjango 7.2Rails 7.2Rails 8.0LAMPFlaskN/A
Base de datosPostgreSQLPostgreSQLPostgreSQLMySQLPostgreSQLN/A
LicenciaLGPL v3MITAGPL-3.0AGPLv2No specGPLv2+ex
Contact CenterParcialNoSolo dialer
HelpdeskParcialNoNoNo
DiscadorExternoNoNoNativoNativoNativo
TelefónicaKamailio+ASNoNoAsteriskAsteriskNativo
Multi-tenantNoNoNoN/A
API RESTGraphQLParcial
WebSocketNo
ReutilizableReferenciaMITEstudioAlgoritmoPatrón ARISustrato
Riesgo LegalAltoBajoAltoAltoVerificarBajo

Clasificación por Utilidad

UtilidadProyectosAcción
Sustrato telefónicaAsteriskUsar como servicio externo vía ARI
Referencia de diseñoChatwoot, OMniLeadsEstudiar patrones, no código
Algoritmo de discadorVICIdialEstudiar lógica de pacing
Patrón ARIOmnidialerReferencia de integración moderna
No usar códigoZammad, OMniLeads, VICIdialLicencias restrictivas
Referencia de canalesChatwootPatrón polimórfico (MIT)

Decisiones Derivadas del Análisis

1. Telefónica: Asterisk vía ARI

  • Nunca reimplementar SIP/RTP
  • Comunicación vía REST + WebSocket
  • Aplicación Go se conecta como cliente ARI

2. Canales: Patrón de Chatwoot

  • Inbox polimórfico → Channel → Conversation → Message
  • Adaptador por canal con interfaz común
  • Licencia MIT permite referencia directa

3. Discador: Lógica de VICIdial

  • Algoritmo adaptativo de pacing
  • Reimplementar en Go, no copiar Perl/PHP
  • Referencia conceptual, no código

4. Modelo de Dominio: OMniLeads como referencia

  • Estados de campaña (4 estados)
  • IVR como grafo
  • Colas y routing

5. No Reutilizar Código de:

  • Zammad (AGPL)
  • OMniLeads (LGPL)
  • VICIdial (AGPLv2, Perl/PHP legacy)

6. Verificar Licencia de:

  • Omnidialer (sin licencia especificada)
  • Cualquier dependencia nueva