Arquitectura Objetivo
Lenguaje: Go (principal)
Por qué Go
Go es la elección principal para la plataforma por:
- Rendimiento nativo: compilación a binario, sin runtime pesado. Latencia predecible.
- Concurrencia nativa: goroutines y channels para manejo de miles de conexiones simultáneas (WebSocket, ARI events, webhooks).
- Ecosistema de red: stdlib completa para HTTP, gRPC, WebSocket. Sin frameworks pesados.
- Simplicidad: lenguaje deliberadamente simple. Facilita onboard de desarrolladores y reduce defectos.
- Deployment: un solo binario estático. Sin dependencias de runtime. Ideal para containers y orquestación.
- Herramientas:
go fmt,go vet, race detector, profiling integrado. - Madurez: amplio uso en infraestructura de producción (Kubernetes, Docker, Terraform, Cloudflare).
Cuándo usar Python
Python se utiliza únicamente cuando existe una ventaja concreta y demostrable:
- Bibliotecas maduras sin equivalente en Go: procesamiento de audio/speech-to-text, ML pipelines, herramientas científicas.
- Procesamiento especializado: análisis de NLP, modelos de clasificación, herramientas de datos.
- Tooling: scripts de migración, generadores, herramientas internas.
- No para prototipado más rápido: esta justificación es inválida. Go es igual de productivo para prototipos y el resultado es producción-ready desde el inicio.
Regla: si Python se usa, es como servicio externo o worker aislado, nunca integrado en el binario principal.
Principios de Arquitectura
Clean Code, Clean Architecture
La arquitectura sigue los principios de Robert C. Martin:
- Independencia de frameworks: la lógica de negocio no depende de frameworks externos.
- Testabilidad: la lógica de negocio se puede testear sin UI, base de datos, o servicios externos.
- Independencia de UI: la UI (API REST, CLI, web) es un plugin que adapta la lógica de negocio.
- Independencia de infraestructura: la base de datos, mensajería, y servicios externos son plugins intercambiables.
Hexagonal (Puertos y Adaptadores)
┌──────────────────────────┐
│ Lógica de Negocio │
│ │
┌─────────┤ Puertos de Entrada │
│ │ (Use Cases) │
│ │ │
│ │ Puertos de Salida │
│ │ (Interfaces) │
│ └──────────┬───────────────┘
│ │
┌────┴────┐ ┌────┴────┐
│ Adapt. │ │ Adapt. │
│ Entrada │ │ Salida │
├─────────┤ ├─────────┤
│ REST API│ │PostgreSQL│
│ gRPC │ │Redis │
│ WebSocket│ │ARI Client│
│ CLI │ │S3 │
└─────────┘ └─────────┘Los puertos definen interfaces. Los adaptadores implementan interfaces concretas.
Pensamiento library-first
Cada componente se diseña como si pudiera ser una biblioteca:
- API pública clara y documentada.
- Dependencias mínimas.
- Reutilización entre bounded contexts.
- Testing independiente.
Lógica event-first
Los eventos de dominio son el centro de la arquitectura:
- Los eventos se producen después de cada acción significativa.
- Las proyecciones se derivan de eventos.
- Los procesos asíncronos reaccionan a eventos.
- El estado se reconstruye desde eventos.
Contratos explícitos
- Interfaces Go para contratos internos.
- Protocol Buffers para contratos gRPC.
- OpenAPI para contratos REST.
- Versionado explícito de contratos.
Límites de dominio claros
- Cada bounded context tiene su propio paquete.
- La comunicación entre contextos es vía eventos o interfaces explícitas.
- No hay dependencias directas entre bounded contexts en la misma capa.
Observabilidad desde el diseño
- Tracing: OpenTelemetry integrado desde el inicio.
- Logging: estructurado (JSON), con correlation IDs.
- Metrics: Prometheus, contadores y histogramas por operación.
- Health checks: endpoints de salud y readiness.
APIs internas tipadas
- Interfaces Go para contratos internos.
- Type-safe en compile time.
- Sin
interface{}oanyen contratos de negocio.
gRPC para límites de procesamiento reales
Cuando dos componentes corren en procesos separados:
- gRPC como protocolo de comunicación (no REST para inter-service).
- Protocol Buffers para serialización (eficiente y tipada).
- HTTP/2 como transporte (multiplexing, compresión).
- Streaming para eventos en tiempo real entre servicios.
Monolito Modular Primero
Filosofía
Empezar como monolito modular y solo separar cuando exista una razón técnica u operativa concreta:
- Identificar bounded contexts en el dominio.
- Implementar como paquetes Go separados dentro de un solo binario.
- Interfaces claras entre paquetes.
- Separar en servicios solo cuando:
- Requieren escalado independiente (ej: telefónica con Asterisk).
- Tienen requisitos de deployment diferentes (ej: workers asíncronos).
- Necesitan aislamiento de fallas fuerte.
- La latencia inter-service es aceptable.
Objetivo: <10 servicios principales
No crear microservicios por crear. Un monolito modular bien diseñado supera a una arquitectura de microservicios mal diseñada.
Bounded Contexts Propuestos
1. Core Application
Responsabilidades:
- Identidad y autenticación (OAuth2, SAML, 2FA).
- Gestión de tenants (multi-tenancy).
- Usuarios y roles (RBAC).
- Configuración del sistema.
- Permisos y políticas de acceso.
Dominio: quién puede hacer qué.
2. Messaging Gateway
Responsabilidades:
- Adapters para cada canal de comunicación.
- Routing de mensajes entrantes al contexto correcto.
- Enrutamiento de mensajes salientes al canal correcto.
- Normalización de mensajes entre canales.
- Gestión de templates por canal.
Dominio: comunicación con el exterior.
3. Conversation Management
Responsabilidades:
- Inbox de conversaciones.
- Asignación de conversaciones a agentes.
- Ciclo de vida de conversaciones (apertura, asignación, cierre, transferencia).
- Reglas de auto-asignación.
- SLA y escalamiento.
- Estado de conversaciones en tiempo real.
Dominio: gestión de la interacción cliente-agente.
4. Contact & CRM
Responsabilidades:
- Gestión de contactos (personas).
- Gestión de empresas (organizaciones).
- Atributos personalizados (schema flexible con JSONB).
- Historial de interacciones por contacto.
- Deduplicación y merge de contactos.
- Búsqueda y segmentación.
Dominio: conocimiento del cliente.
5. Campaign Engine
Responsabilidades:
- Gestión de campañas outbound.
- Pacing (velocidad de discado).
- Programación y calending.
- Gestión de leads y hopper.
- DNC (Do Not Call) management.
- Throttling por canal.
Dominio: comunicación proactiva.
6. Telephony
Responsabilidades:
- Integración con Asterisk vía ARI.
- Gestión de canales SIP.
- IVR dinámico.
- WebRTC signaling.
- Grabación de llamadas.
- Gestión de troncales y DID.
Dominio: telecomunicaciones.
7. Dialer
Responsabilidades:
- Discador predictivo.
- Discador progresivo.
- Discador preview.
- Algoritmos de pacing adaptivo.
- Detección de tonos de contestación.
- Throttling y rate limiting.
Dominio: discado automatizado.
8. Reporting & Analytics
Responsabilidades:
- Dashboards en tiempo real.
- Reportes históricos.
- Exportación (CSV, PDF).
- Métricas de agentes.
- Métricas de campañas.
- SLA reporting.
Dominio: datos y métricas.
9. Async Workers
Responsabilidades:
- Jobs en background (procesamiento de email, webhooks, notificaciones).
- Delivery de webhooks outbound.
- Procesamiento de archivos (grabaciones, exports).
- Tareas programadas (cron jobs).
- Retry logic y dead letter queues.
Dominio: trabajo asíncrono.
10. AI Services & Resident Agents
Responsabilidades:
- Integración con LLMs (OpenAI, Anthropic, Google, BYOK).
- Abstracción sobre proveedores de AI (puerto + adaptadores).
- Capacidades de IA para agentes humanos:
- Clasificación de mensajes.
- Sentiment analysis.
- Summarización de conversaciones.
- Sugerencia de respuestas.
- Detección de intención.
- Traducción en tiempo real.
- Agentes residentes autónomos:
- KPI Guardian: monitoreo de métricas y optimización automática.
- Security Sentinel: detección de abuso, fraude y spam.
- Policy Engine: gestión y optimización de políticas.
- Health Monitor: salud técnica de la plataforma.
- Sistema de skills para definir personalidad y restricciones de agentes.
- Motor de reglas para acciones autónomas dentro de políticas.
Dominio: inteligencia artificial aplicada y automatización autónoma.
11. MCP Server (Model Context Protocol)
Responsabilidades:
- Servidor MCP para integración externa con herramientas de IA.
- Chatbot integrado en la plataforma (lenguaje natural).
- Herramientas (tools) de consulta, gestión y acciones.
- Autenticación y autorización de conexiones MCP.
- Aislamiento por tenant en todas las operaciones.
- Rate limiting y auditoría de acciones MCP.
- Traducción de lenguaje natural a operaciones de dominio.
Dominio: interfaz de inteligencia artificial para el exterior y chatbot interno.
Decisión: Módulo vs Servicio
Módulos (mismo binario)
| Contexto | Justificación |
|---|---|
| Core Application | Fundacional, todas las demás dependen de él |
| Conversation Management | Lógica central de negocio, alta cohesión con Assignment |
| Contact & CRM | Core domain, acceso frecuente desde otros contextos |
| Campaign Engine | Lógica de negocio, requiere transaccionalidad |
| Reporting & Analytics | Queries contra la misma base de datos |
| AI Services | Abstraction layer, llamadas a APIs externas, agentes residentes |
| MCP Server | Servidor HTTP/WebSocket dedicado, seguridad aislada |
Servicios (proceso separado)
| Contexto | Justificación |
|---|---|
| Messaging Gateway | Requiere async processing, manejo de conexiones persistentes (WebSocket), escalado independiente por canal |
| Telephony | Proceso separado por Asterisk, necesita ARI client dedicado, escalado independiente |
| Dialer | Escalado independiente, puede ser CPU-intensive en discado predictivo |
| Async Workers | Background processing, escalado horizontal independiente, no bloquea el request cycle |
| MCP Server | Servidor HTTP/WebSocket, necesita escalado independiente, seguridad aislada |
| AI Agents (Residentes) | Workers de background que consumen eventos, escalado independiente, procesamiento intensivo |
Comunicación entre servicios
- Módulos: llamadas de función directas a través de interfaces Go.
- Servicios: gRPC para comunicación síncrona, eventos para asíncrona.
- Entre módulos y servicios: los servicios exponen gRPC, los módulos los consumen.
Base de datos
PostgreSQL como primario
PostgreSQL es la elección por:
- JSONB: soporte nativo para schema flexible (atributos personalizados).
- Row-Level Security (RLS): aislamiento a nivel de base de datos para multi-tenancy.
- Partitioning: particionamiento por tenant o por tiempo.
- Full-text search: capacidades de búsqueda integradas.
- Extensions: pgvector para embeddings, pg_trgm para búsqueda fuzzy.
- Madurez: probado en miles de implementaciones de producción.
Estrategia multi-tenant en base de datos
Opción A: Schema per tenant.
- Cada tenant tiene su propio schema en la misma base de datos.
- Pros: aislamiento fuerte, fácil de entender.
- Contras: overhead de migraciones, límite práctico de tenants.
Opción B: Row-Level Security (RLS).
- Una sola schema, tenant_id en cada tabla.
- RLS policy que filtra automáticamente por tenant.
- Pros: más simple, mejor escalabilidad, migraciones centralizadas.
- Contras: requiere configuración cuidadosa de RLS.
Recomendación: RLS para la mayoría de las tablas. Schema per tenant solo si un tenant tiene requisitos de aislamiento especial (enterprise, compliance).
Redis
Redis complementa PostgreSQL:
- Caching: sesiones, configuración de tenants, datos calientes.
- Pub/Sub: distribución de eventos en tiempo real entre procesos.
- Rate limiting: control de tasa por tenant, canal, o endpoint.
- Queues: colas de trabajo para async workers.
- Distributed locks: locks distribuidos para operaciones críticas.
- Sessions: almacenamiento de sesiones de agentes.
Diseño de API
REST para clientes externos
- Endpoints RESTful: recursos nombrados correctamente, métodos HTTP semánticos.
- JSON como formato: request y response en JSON.
- Autenticación: OAuth2 bearer tokens.
- Rate limiting: headers de rate limit (X-RateLimit-*).
- Paginación: cursor-based o offset-based.
- Filtros: query parameters para filtrado.
- Sorting: query parameters para ordenamiento.
gRPC para límites internos
- Protocol Buffers: serialización eficiente y tipada.
- HTTP/2: multiplexing y compresión.
- Streaming: server streaming, client streaming, bidirectional.
- Interceptors: logging, tracing, auth, rate limiting.
- Health checking: gRPC health checking protocol.
- Load balancing: client-side o proxy-based.
Documentación
- OpenAPI/Swagger: especificación para REST APIs.
- Protobuf: especificación nativa para gRPC.
- Code generation: generación automática de clientes y servidores.
- Versioning: versionado explícito en URLs (
/api/v1/) o headers.
Versioning
- URL path versioning:
/api/v1/contacts,/api/v2/contacts. - Backward compatibility: versiones antiguas se mantienen por periodo definido.
- Deprecation headers:
Deprecation,Sunsetheaders para comunicación de deprecación. - Migration guides: documentación para migrar entre versiones.