
Con la llegada de la IA, proyectos que antes eran inalcanzables a nivel individual hoy son posibles gracias a herramientas como github copilot. Bri Flow nace de una necesidad concreta: diseñar flujos conversacionales fijos con lógica compleja, integrables con agentes, formularios y sistemas RAG, manteniendo control, seguridad y extensibilidad. En este artículo explico cómo lo hice, qué decisiones técnicas tomé
Motivación y enfoque general
Problema inicial Las herramientas cerradas que probé no encajaban: poca flexibilidad para lógica avanzada, difícil integración con LLMs y RAG, y escasa capacidad para reutilizar subflujos. Además, necesitaba que los flujos fueran deterministas y auditables.
Decisión clave Representar el flujo como JSON estructurado. Con ese contrato claro, cualquier backend puede interpretar y ejecutar la lógica. Arquitectura y flujo de ejecución
Componentes principales
- Editor visual: interfaz para crear nodos y conexiones; exporta JSON con la estructura del flujo.
- Backend (.NET): intérprete del JSON, expression engine, funciones nativas, ejecución de llamadas REST, integración con agentes/LLMs y gestión de sesiones.
- Frontend: consume la API del backend; recibe JSON procesado que indica qué componente renderizar (botón, formulario, carrusel, mensaje, etc.).
Flujo de datos (conceptual) Editor → JSON → Backend (.NET interpreta y ejecuta) → Frontend (renderiza según JSON procesado) → Usuario. El backend mantiene la sesión del usuario, el estado del flujo y filtra contenido por idioma cuando procede.
Idea central
Las expresiones no son código externo: son cadenas definidas dentro del JSON que exporta el editor. El backend recibe ese JSON, extrae las expresiones y las evalúa en tiempo de ejecución contra el contexto de la sesión y las variables del flujo. Por eso fue necesario diseñar un lenguaje/expression engine propio: las expresiones deben ser flexibles, seguras, deterministas y controlables desde el backend.
Beneficios prácticos
- Procesar listas devueltas por servicios REST directamente en el flujo.
- Evitar código ad-hoc en cada integración: la lógica se define en expresiones dentro del JSON.
- Reutilización y trazabilidad: toda la lógica queda en el flujo exportado.
Ejemplos prácticos y fragmento JSON
A continuación un ejemplo simplificado que ilustra cómo se modela un flujo en JSON y cómo se usan expresiones para controlar la ejecución.
{
"schema_version": 2,
"flow_id": "principal",
"version": "1.0.223",
"name": "principal",
"description": "Flujo ejemplo",
"locales": ["es","pt","en"],
"start_node": "start",
"nodes": {
"start": {
"id": "start",
"type": "start",
"next": { "flow_id": "principal", "node_id": "response_1" },
"variables": [
{ "name": "selected_button_button_1", "defaultValue": "", "isList": false }
]
},
"response_1": {
"id": "response_1",
"type": "response",
"next": { "flow_id": "principal", "node_id": "agent_call_1" },
"i18n": {
"es": { "text": ["hola"] },
"pt": { "text": ["oi"] },
"en": { "text": ["hi"] }
}
},
"agent_call_1": {
"id": "agent_call_1",
"type": "agent_call",
"next": { "flow_id": "principal", "node_id": "button_1" },
"save_as": "agent_agent_call_1",
"model": {
"provider": "azure-openai",
"deployment": "gpt-4o-mini",
"temperature": 0.2,
"max_tokens": 800
}
},
"button_1": {
"id": "button_1",
"type": "button",
"save_as": "selected_button_button_1",
"options": [
{ "target": { "flow_id": "", "node_id": "end_1" }, "label": "Opción 1", "value": "Opción 1" },
{ "target": { "flow_id": "", "node_id": "end_1" }, "label": "Opción 2", "value": "Opcion 2" }
]
},
"end_1": { "id": "end_1", "type": "end", "next": null }
}
}
Ejemplo LINQ-like (expresión dentro del engine)
itemsVar.where(x => x.active).select(x => x.id).orderBy(x => x)
La pieza final es el frontend: llama a la API y renderiza los componentes según la estructura del JSON recibido; el backend se encarga de procesar la información y devolverla lista para pintar, adaptando la respuesta a la sesión del usuario y al idioma seleccionado al iniciar el flujo.
- Editor Bri Flow: https://elbrinner.com/flow/
- Código fuente del editor: https://github.com/elbrinner/BRI-FLOW