🧭 What Should Happen Next? — DevDeal Engine
Copiloto de Decisiones y Gobernanza Comercial para Dev Shops y Consultoras B2B
Hackathon ByeCode · Reto: "What Should Happen Next?"
💡 Inspiración y Planteamiento del Problema
En el ecosistema de consultoría de software, agencias digitales y Software Houses, el ciclo de ventas es de alto valor ($20,000 a $150,000 USD) y ciclo largo. Durante semanas, un prospecto técnico evalúa propuestas complejas entre esquemas de Precio Fijo (Fixed Price) y Tiempo y Materiales (T&M).
En este escenario, el equipo comercial enfrenta un dilema crítico:
- El costo de la insistencia indebida: Si un prospecto solicita tiempo para que su comité evalúe el presupuesto y un ejecutivo le insiste antes de tiempo, la venta se quema y se rompe la relación de confianza.
- El costo de la inacción o lentitud: Si el cliente hace una pregunta técnica sobre plazos o arquitectura y nadie le responde en menos de 24 horas, buscará a otro proveedor.
- La falacia del interés superficial: Que un cliente abra una propuesta en PDF diez veces ($\text{proposal.viewed}$) no significa que vaya a firmar el contrato. Confundir aperturas con intención de compra suele derivar en descuentos precipitados o presión contraproducente.
Nuestra inspiración fue construir DevDeal Engine: un sistema que procesa eventos asíncronos de interacción, interpreta el lenguaje del cliente mediante modelos de lenguaje (LLM) y aplica una capa de gobernanza determinista inviolable para responder con rigor matemático: ¿qué debe suceder después, cuándo y por qué?
🏗️ Cómo Construimos el Proyecto
Diseñamos una arquitectura híbrida desacoplada en 5 capas que une la flexibilidad semántica de la inteligencia artificial generativa con la certidumbre de reglas de negocio verificables.
┌──────────────────────────────┐
│ Ingesta de Eventos (JSONL) │
│ Deduplicación y Ordenamiento │
└──────────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ Reconstrucción de Estado │
│ (Línea de tiempo histórica) │
└──────────────┬───────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────────────┐ ┌───────────────────────┐
│ Motor Determinista │ │ Interprete de IA │
│ de Reglas (R1-R6) │ │ Google Gemini │
└───────────┬───────────┘ └───────────┬───────────┘
│ │
└───────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ Validador y Árbitro Formal │
│ (Prevalece la restricción) │
└──────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ Panel Streamlit + Feedback │
│ (Closed-Loop en Tiempo Real) │
└──────────────────────────────┘
1. Ingesta y Reconstrucción Cronológica del Estado
El sistema recibe un flujo de eventos en formato JSONL. Cada evento $e_i$ posee un identificador único, un tipo, un caso asignado y una marca temporal UTC:
$$e_i = \langle \text{id}_i, \text{case_id}_i, \text{type}_i, \tau_i, \mathbf{d}_i \rangle$$
Para evitar condiciones de carrera o inconsistencias temporales, definimos una relación de orden estricta $\prec$ sobre el conjunto de eventos de un caso:
$$e_a \prec e_b \iff (\tau_a < \tau_b) \lor \big(\tau_a = \tau_b \land \text{orden_llegada}(e_a) < \text{orden_llegada}(e_b)\big)$$
Con esta secuencia ordenada $\mathcal{H}_t = (e_1, e_2, \dots, e_n)$, el motor reconstruye el estado actual $\mathcal{S}_t$: mensajes recibidos, intentos de contacto previos, restricciones activas y estado de cierre.
2. Formalización Matemática de las Reglas Deterministas ($R_1$ a $R_6$)
Definimos el catálogo finito de acciones comerciales disponibles como:
$$\mathcal{A} = {\text{contact}, \text{request_information}, \text{resolve_objection}, \text{escalate}, \text{wait}, \text{no_action}}$$
El conjunto de acciones de contacto directo sobre el prospecto es:
$$\mathcal{A}_{\text{contacto}} = {\text{contact}, \text{request_information}, \text{resolve_objection}} \subset \mathcal{A}$$
Para garantizar el cumplimiento de las restricciones contractuales en el tiempo de evaluación $t_{\text{eval}}$, formulamos las restricciones como operadores lógicos sobre el espacio de acciones factibles $\mathcal{A}{\text{factible}}(t{\text{eval}})$:
Regla 1 (Cierre Definitivo): Si el caso ha sido cerrado (aceptado, rechazado o cancelado), no se permite intervención: $$\exists e \in \mathcal{H}t \mid \text{type}(e) = \text{case.closed} \implies \mathcal{A}{\text{factible}} = {\text{no_action}}$$
Regla 2 (Bloqueo Explícito): Si existe una restricción de no contacto activa: $$\text{contact_allowed} = \text{False} \implies \mathcal{A}{\text{factible}} \subseteq \mathcal{A} \setminus \mathcal{A}{\text{contacto}}$$
Regla 3 (Fecha de Desbloqueo Futura): Si el cliente solicitó no ser contactado antes de una fecha $t_{\text{not_before}}$: $$t_{\text{eval}} < t_{\text{not_before}} \implies \mathcal{A}{\text{factible}} \subseteq \mathcal{A} \setminus \mathcal{A}{\text{contacto}}$$ En este escenario, si se selecciona la acción $\text{wait}$, el timing queda parametrizado exactamente como: $$\text{timing} = \text{at_date}, \quad \text{scheduled_for} = t_{\text{not_before}}$$
Regla 4 (Periodo de Reposo / Cooldown de 24h): Si un ejecutivo ejecutó un contacto en $t_{\text{contacto}}$: $$\Delta t = t_{\text{eval}} - t_{\text{contacto}} < 24\,\text{horas} \land \neg\exists e_{\text{msg}} (\tau(e_{\text{msg}}) > t_{\text{contacto}}) \implies \mathcal{A}{\text{factible}} \subseteq \mathcal{A} \setminus \mathcal{A}{\text{contacto}}$$ El reposo solo se interrumpe si el cliente toma la iniciativa y envía un nuevo mensaje después del intento de contacto.
Regla 5 & 6 (Heurística Anti-Alucinación y Prevalencia): $$\text{Aperturas}(\mathcal{H}_t) \gg 0 \centernot\implies \text{IntenciónDeCompraConfirmada}$$ $$\text{RestricciónActiva} \land \text{FaltaInformación} \implies \text{Prevalece Restricción (escalate / wait)}$$
3. Modelo de Lenguaje e Inferencia Semántica (Google Gemini)
Integramos la API de Google Gemini (gemini-2.5-flash / gemini-3.8-flash) mediante el SDK oficial google-genai. Diseñamos un esquema de Prompt Engineering defensivo estructurado en tres apartados:
- Aislamiento de Entradas: Los mensajes del prospecto se delimitan como datos dentro de etiquetas
<mensaje_cliente>para prevenir inyecciones de instrucciones (Prompt Injection). - Desglose Epistémico: El modelo debe separar explícitamente:
- $\text{Hechos Observados: } \mathcal{O} = { \text{afirmaciones literales respaldadas por } \text{event_id} }$
- $\text{Inferencias: } \mathcal{I} = { \text{deducciones probabilísticas con nivel de certeza} }$
- $\text{Información Faltante: } \mathcal{M} = { \text{variables no esclarecidas en el expediente} }$
- Respaldo Determinista (Fallback Baseline): Si la cuota de la API se satura, el JSON del LLM presenta una anomalía estructural o la red falla, el sistema conmuta a un motor de reglas de respaldo determinista en $\mathcal{O}(1)$, garantizando una disponibilidad operativa del 100%.
4. El Bucle Cerrado (Closed-Loop Feedback)
Implementamos en src/devshop.py y app.py la capacidad de registrar la respuesta real del prospecto tras ejecutar la recomendación. Al registrar la llamada o acuerdo, el sistema genera eventos conformes al contrato (action.executed, message.received, constraint.updated, case.closed) y detona la reevaluación inmediata, mostrando visualmente la transición del estado:
$$\mathcal{H}{t + \Delta t} = \mathcal{H}_t \cup { e{\text{intervención}}, e_{\text{respuesta}} }$$
⚡ Desafíos Técnicos Enfrentados
La tendencia de los LLM a ser complacientes (Over-helpfulness):
Durante las pruebas iniciales con prompts abiertos, el modelo de IA sugería contactar al cliente o responder amablemente incluso cuando existía una restricción explícita decontact_allowed=falseo un periodo de reposo de 24 horas activo ($R_4$).
Solución: Implementamos el patrón "La IA interpreta, las reglas deciden". Construimos un validador determinista (src/validator.py) que audita la salida de la IA antes de publicarla. Si la IA viola una restricción, el árbitro anula la acción y la reemplaza porescalateowait, registrando la corrección para auditoría.Deduplicación e Idempotencia en Flujos Asíncronos:
En ventas reales, los correos se reenvían y los webhooks de CRM se disparan más de una vez. Diseñamos unStoreen memoria con indexación basada en tablas hash de $\mathcal{O}(1)$ sobreevent_id, ignorando réplicas sin corromper el cálculo de métricas.Reevaluación de Estados y Trazabilidad ("¿Qué cambió?"):
Al evaluar el casoP06contraupdates.jsonl(la llegada de una pregunta sobre cronograma mientras el cliente estaba en espera), el sistema debía comparar $\text{Rec}{t_1}$ vs $\text{Rec}{t_2}$. Implementamos un gestor de versiones que genera el diff campo por campo de las 11 propiedades del contrato de recomendación.Experiencia de Usuario en Streamlit sin recargas molestas:
Al operar en Streamlit, el usuario interactuaba al final de la página para registrar la intervención y, tras elst.rerun(), la pantalla permanecía abajo. Superamos esta limitación inyectando un componente HTML/JS de scroll suave que detecta contenedores dinámicos ([data-testid="stAppViewContainer"]) y reposiciona automáticamente la vista al inicio del expediente.
🎓 Lo Que Aprendimos
- La IA en sistemas empresariales críticos debe estar acotada: Un modelo de lenguaje por sí solo es un excelente intérprete semántico pero un mal árbitro de reglas. La verdadera confiabilidad en producción proviene de envolver la inteligencia artificial dentro de un arnés de validación formal basado en contratos estrictos.
- El valor del diseño centrado en contratos: Fijar una marca de tiempo determinista en
data/manifest.json($t_{\text{eval}} = \text{2026-10-09T16:00:00Z}$) en lugar de invocardatetime.now()permitió que toda la suite de pruebas unitarias (30 tests) fuera completamente reproducible y verificable en cualquier máquina o contenedor. - Separar hechos de suposiciones es clave en ventas B2B: Identificar formalmente la información faltante ($\text{missing_information}$) evita que los directores comerciales tomen decisiones multimillonarias basadas en conjeturas.
🚀 Tecnologías Utilizadas
| Capa | Herramientas y Librerías |
|---|---|
| Lenguaje Core | Python 3.13 / 3.10+ (Tipado estricto, dataclasses, datetime UTC) |
| Inteligencia Artificial | Google Gemini API (gemini-2.5-flash, gemini-3.8-flash) vía google-genai |
| Interfaz de Usuario | Streamlit, Streamlit Components (JavaScript custom scrolling) |
| Aseguramiento de Calidad | pytest (30 pruebas unitarias automatizadas) |
| Contenedorización & Servidor | Docker, Docker Compose, Linux Ubuntu 24.04 LTS en Vultr Cloud |
| Control de Versiones | Git, GitHub (josueRamosGarcia/whatShouldHappenNext) |
👥 Equipo de Desarrollo
- Gabriela Estefanía Mejía Rodríguez
- Josué Leonardo Ramos García
- David Jiménez García
- Eduardo Eutimio González López
Built With
- python
- vultr
Log in or sign up for Devpost to join the conversation.