(No me pude resistir a poner este meme)
Introducción
Podría haber llamado este artículo: «De Diagrama a Código: cómo la IA Generativa transforma los procesos BPMN en aplicaciones funcionales«, pero me parecía muy largo.
Estoy seguro de que tú, como yo, haces diagramas de todo tipo. Y si trabajas con flujos empresariales, probablemente dominas los diagramas de procesos de negocio (BPMN). Pero hoy no vengo a hablarte de cómo modelarlos. Vengo a contarte algo aún más interesante: cómo la Inteligencia Artificial Generativa puede ayudarte a construir la base de tu código directamente desde un diagrama BPMN.
¿Qué es BPMN y por qué importa?
Business Process Model and Notation (BPMN) es un lenguaje gráfico estandarizado que permite modelar procesos de negocio de manera clara y comprensible para todos los involucrados: desde analistas de negocio hasta desarrolladores. La versión actual (v2.0.2) mejora la interoperabilidad y claridad del estándar, facilitando la conexión entre diseño e implementación.
BPMN define elementos como:
-
Eventos (inicio, fin, intermedios),
-
Actividades (tareas, subprocesos, transacciones),
-
Compuertas de decisión,
-
Flujos de mensajes y secuencia,
-
Piscinas y carriles para representar roles u organizaciones.
Esto permite representar cualquier proceso, desde un flujo simple de aprobación hasta una coreografía compleja entre múltiples entidades.
¿Y si tu BPMN generara el esqueleto del código?
Aquí es donde entra la IA Generativa. Mediante modelos entrenados con patrones de programación, flujos de procesos y estructuras semánticas, es posible convertir automáticamente un diagrama BPMN en plantillas de código base. Esto incluye:
-
Generación de microservicios o funciones serverless por cada actividad.
-
Definición de endpoints REST o eventos para tareas de entrada/salida.
-
Orquestación mediante motores como Azure Logic Apps, dependiendo del estilo del BPMN (orquestación vs coreografía).
-
Inclusión de pruebas automáticas, validaciones, y lógica condicional según las compuertas del diagrama.
En pocas palabras, el analista dibuja y la IA escribe el primer borrador del sistema.
¿Qué beneficios ofrece esto?
-
Velocidad de desarrollo: se reduce significativamente el tiempo desde el diseño del proceso hasta su puesta en marcha.
-
Trazabilidad y alineación: el código queda estructurado en torno a los procesos del negocio, facilitando auditorías y evolución.
-
Colaboración fluida: negocio y desarrollo hablan el mismo idioma, y el modelo BPMN es la fuente de verdad.
El futuro: del modelo al producto sin fricción
En un mundo en el que los procesos empresariales cambian rápidamente, poder adaptar sistemas sin reescribir manualmente todo el backend es una ventaja competitiva enorme. Y con la IA generativa, esto ya no es ciencia ficción.
Así que la próxima vez que estés frente a un diagrama BPMN, no lo veas solo como documentación. Estás diseñando la arquitectura viva de tu aplicación, y con la ayuda de la IA, podrías tener un prototipo funcional en minutos.
Ejemplo 1
Escenario: Aprobación de solicitud.
Flujo BPMN:
- Inicio
- Verificar solicitud
- Decisión: ¿es válida?
- Si sí, aprobar solicitud
- Si no, rechazar solicitud
- Fin
Esto es lo que tendríamos en formato «humano» y que podemos pasar a la IA Generativa para que nos saque la primera versión y usarla en una herramienta visual (recuerda pedir que sea formato «XML válido BPMN 2.0»). En este caso yo he explicado el flujo y el contexto a la IA Generativa, ella me muestra:
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
id="Definitions_1"
targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="Inicio">
<bpmn:outgoing>Flow_1</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="Task_Verify" name="Verificar solicitud">
<bpmn:incoming>Flow_1</bpmn:incoming>
<bpmn:outgoing>Flow_2</bpmn:outgoing>
</bpmn:task>
<bpmn:exclusiveGateway id="Gateway_Valid" name="¿Es válida?">
<bpmn:incoming>Flow_2</bpmn:incoming>
<bpmn:outgoing>Flow_3</bpmn:outgoing>
<bpmn:outgoing>Flow_4</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:task id="Task_Approve" name="Aprobar solicitud">
<bpmn:incoming>Flow_3</bpmn:incoming>
<bpmn:outgoing>Flow_5</bpmn:outgoing>
</bpmn:task>
<bpmn:task id="Task_Reject" name="Rechazar solicitud">
<bpmn:incoming>Flow_4</bpmn:incoming>
<bpmn:outgoing>Flow_6</bpmn:outgoing>
</bpmn:task>
<bpmn:endEvent id="EndEvent_1" name="Fin">
<bpmn:incoming>Flow_5</bpmn:incoming>
<bpmn:incoming>Flow_6</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1" sourceRef="StartEvent_1" targetRef="Task_Verify"/>
<bpmn:sequenceFlow id="Flow_2" sourceRef="Task_Verify" targetRef="Gateway_Valid"/>
<bpmn:sequenceFlow id="Flow_3" sourceRef="Gateway_Valid" targetRef="Task_Approve" name="Sí"/>
<bpmn:sequenceFlow id="Flow_4" sourceRef="Gateway_Valid" targetRef="Task_Reject" name="No"/>
<bpmn:sequenceFlow id="Flow_5" sourceRef="Task_Approve" targetRef="EndEvent_1"/>
<bpmn:sequenceFlow id="Flow_6" sourceRef="Task_Reject" targetRef="EndEvent_1"/>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="StartEvent_1_di" bpmnElement="StartEvent_1">
<dc:Bounds x="100" y="100" width="36" height="36"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_Verify_di" bpmnElement="Task_Verify">
<dc:Bounds x="160" y="90" width="100" height="56"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_Valid_di" bpmnElement="Gateway_Valid" isMarkerVisible="true">
<dc:Bounds x="290" y="95" width="50" height="50"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_Approve_di" bpmnElement="Task_Approve">
<dc:Bounds x="370" y="60" width="100" height="56"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Task_Reject_di" bpmnElement="Task_Reject">
<dc:Bounds x="370" y="140" width="100" height="56"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1_di" bpmnElement="EndEvent_1">
<dc:Bounds x="500" y="100" width="36" height="36"/>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1_di" bpmnElement="Flow_1">
<di:waypoint x="136" y="118"/>
<di:waypoint x="160" y="118"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_2_di" bpmnElement="Flow_2">
<di:waypoint x="260" y="118"/>
<di:waypoint x="290" y="118"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_3_di" bpmnElement="Flow_3">
<di:waypoint x="340" y="118"/>
<di:waypoint x="370" y="88"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_4_di" bpmnElement="Flow_4">
<di:waypoint x="340" y="118"/>
<di:waypoint x="370" y="168"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_5_di" bpmnElement="Flow_5">
<di:waypoint x="470" y="88"/>
<di:waypoint x="500" y="118"/>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_6_di" bpmnElement="Flow_6">
<di:waypoint x="470" y="168"/>
<di:waypoint x="500" y="118"/>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>
El codigo XML solo lo tienes que pegar en una herramienta de edición visual como y jugar con cargar o exportar el XML que puedes usar como Documentation as Code (CoD) traceable con Git, mantenible y junto a la documentación del microservicio:

Cargamos el archivo XML y listo:

Imagina ahora que has realizado cambios, en nuestor ejemplo no lo toco, que ya has exportado el XML a un fichero y copias el contenido en una IA Generativa pidiendo con un prompt que te genere el código en C# desde GitHub Copilot en Visual Studio Code, usando buenas prácticas, etc (ver este artículo). Por tanto, tu resultado para pegar a tu proyecto es el siguiente usando un Patron State ya que en mis buenas prácticas pido poner si se puede un patrón:
using System;
// Usado patron State
namespace WorkflowConPatronState
{
public class Solicitud
{
public string Id { get; set; }
public bool EsValida { get; set; }
public string Estado { get; set; }
}
// Interfaz del estado
public interface IEstadoWorkflow
{
void Ejecutar(Solicitud solicitud, WorkflowContexto contexto);
}
// Contexto del workflow
public class WorkflowContexto
{
private IEstadoWorkflow _estadoActual;
public WorkflowContexto()
{
_estadoActual = new EstadoInicio();
}
public void CambiarEstado(IEstadoWorkflow nuevoEstado)
{
_estadoActual = nuevoEstado;
}
public void Ejecutar(Solicitud solicitud)
{
_estadoActual.Ejecutar(solicitud, this);
}
}
// Estados concretos
public class EstadoInicio : IEstadoWorkflow
{
public void Ejecutar(Solicitud solicitud, WorkflowContexto contexto)
{
Console.WriteLine("Inicio del proceso");
contexto.CambiarEstado(new EstadoVerificarSolicitud());
contexto.Ejecutar(solicitud);
}
}
public class EstadoVerificarSolicitud : IEstadoWorkflow
{
public void Ejecutar(Solicitud solicitud, WorkflowContexto contexto)
{
Console.WriteLine($"Verificando solicitud {solicitud.Id}...");
solicitud.EsValida = solicitud.Id.StartsWith("A"); // Ejemplo simple
contexto.CambiarEstado(new EstadoDecision());
contexto.Ejecutar(solicitud);
}
}
public class EstadoDecision : IEstadoWorkflow
{
public void Ejecutar(Solicitud solicitud, WorkflowContexto contexto)
{
Console.WriteLine($"¿Es válida? {solicitud.EsValida}");
if (solicitud.EsValida)
contexto.CambiarEstado(new EstadoAprobar());
else
contexto.CambiarEstado(new EstadoRechazar());
contexto.Ejecutar(solicitud);
}
}
public class EstadoAprobar : IEstadoWorkflow
{
public void Ejecutar(Solicitud solicitud, WorkflowContexto contexto)
{
solicitud.Estado = "Aprobada";
Console.WriteLine($"Solicitud {solicitud.Id} aprobada.");
contexto.CambiarEstado(new EstadoFin());
contexto.Ejecutar(solicitud);
}
}
public class EstadoRechazar : IEstadoWorkflow
{
public void Ejecutar(Solicitud solicitud, WorkflowContexto contexto)
{
solicitud.Estado = "Rechazada";
Console.WriteLine($"Solicitud {solicitud.Id} rechazada.");
contexto.CambiarEstado(new EstadoFin());
contexto.Ejecutar(solicitud);
}
}
public class EstadoFin : IEstadoWorkflow
{
public void Ejecutar(Solicitud solicitud, WorkflowContexto contexto)
{
Console.WriteLine("Fin del proceso");
Console.WriteLine($"Estado final: {solicitud.Estado}");
}
}
// Ejecución
class Program
{
static void Main(string[] args)
{
var solicitud = new Solicitud { Id = "A123" };
var workflow = new WorkflowContexto();
workflow.Ejecutar(solicitud);
}
}
}
Ejemplo 2
Escenario: Gestión de Reclamaciones de Cliente en una Empresa de Seguros
Contexto: Un cliente presenta una reclamación a su compañía de seguros. El proceso debe validar la información, revisar la póliza, evaluar si aplica cobertura, y decidir si se aprueba o se rechaza la reclamación. Si se aprueba, se realiza el pago. Si se rechaza, se informa al cliente.
Flujo BPMN, explicado en pasos humanos, tras un brain stroming hemos decidido negocio y desarrollo lo siguiente:
-
Inicio
-
Recibir reclamación
-
Validar datos del cliente
-
Si hay errores en los datos, devolver la reclamación al cliente para corrección
-
-
Revisar póliza
-
Si la póliza está inactiva, rechazar directamente
-
-
Evaluar cobertura
-
Si la cobertura no aplica, rechazar
-
-
Calcular coste de indemnización
-
Aprobar pago por supervisor
-
Si no se aprueba, escalar a director
-
-
Realizar pago
-
Notificar al cliente
-
Fin
En vez de crear el XML, esto es lo que no pasa el equipo de Negocio, que no tienen por que saber XML ni nada de nada, solo con «pinta y colorea»:

Ahora copiamos el contenido del XML y se lo pasamos a una IA Generativa con la información de buenas prácticas, etc. (lo que os conté en Visual Studio Code y GitHub Copilot) para que nos genere un buen trozo de código:
// Dominio: Solicitud de Reclamación
public class Reclamacion
{
public string Id { get; set; }
public bool DatosValidos { get; set; }
public bool EsSiniestro { get; set; }
public bool CoberturaAplica { get; set; }
public decimal ImporteCalculado { get; set; }
public bool AceptaPago { get; set; }
public string Estado { get; set; } = "Iniciada";
}
// Cliente
public class Cliente
{
public Reclamacion IniciarReclamacion(string id)
{
Console.WriteLine("Cliente: Inicia reclamación");
return new Reclamacion { Id = id };
}
}
// Agente
public class Agente
{
public bool ValidarDatos(Reclamacion r)
{
Console.WriteLine("Agente: Validando datos...");
r.DatosValidos = true; // o lógica real
return r.DatosValidos;
}
public void NotificarCorreccion(Reclamacion r)
{
Console.WriteLine("Agente: Datos incorrectos. Se notifica al cliente para corrección.");
r.Estado = "Esperando corrección";
}
public void Evaluar(Reclamacion r)
{
Console.WriteLine("Agente: Evaluando si es siniestro");
r.EsSiniestro = true;
}
public bool VerificarCobertura(Reclamacion r)
{
Console.WriteLine("Agente: Verificando cobertura");
r.CoberturaAplica = true;
return r.CoberturaAplica;
}
public void CalcularIndemnizacion(Reclamacion r)
{
Console.WriteLine("Agente: Calculando indemnización");
r.ImporteCalculado = 1500m;
}
public void NotificarImporte(Reclamacion r)
{
Console.WriteLine($"Agente: Importe notificado: {r.ImporteCalculado}€");
}
public void SolicitarAceptacion(Reclamacion r)
{
Console.WriteLine("Agente: Solicitando aceptación del cliente");
r.AceptaPago = true; // Simulación
}
public void CerrarCaso(Reclamacion r)
{
Console.WriteLine("Agente: Caso cerrado");
r.Estado = "Cerrado";
}
}
// Supervisor
public class Supervisor
{
public bool AprobarPago(Reclamacion r)
{
Console.WriteLine("Supervisor: Revisión del pago");
return true; // Simulación
}
public void Rechazar(Reclamacion r)
{
Console.WriteLine("Supervisor: Reclamación rechazada");
r.Estado = "Rechazada";
}
public void NotificarCliente(Reclamacion r)
{
Console.WriteLine("Supervisor: Cliente notificado");
}
}
// Banco
public class Banco
{
public void EjecutarPago(Reclamacion r)
{
Console.WriteLine("Banco: Pago ejecutado");
}
public void NotificarPago(Reclamacion r)
{
Console.WriteLine("Banco: Cliente notificado del pago");
}
}
// Orquestador
public class WorkflowReclamacion
{
public void Ejecutar()
{
var cliente = new Cliente();
var agente = new Agente();
var supervisor = new Supervisor();
var banco = new Banco();
var reclamacion = cliente.IniciarReclamacion("RCL-1234");
if (!agente.ValidarDatos(reclamacion))
{
agente.NotificarCorreccion(reclamacion);
return;
}
agente.Evaluar(reclamacion);
if (!agente.VerificarCobertura(reclamacion))
{
Console.WriteLine("Agente: Reclamación no cubierta");
reclamacion.Estado = "No cubierta";
return;
}
agente.CalcularIndemnizacion(reclamacion);
agente.NotificarImporte(reclamacion);
agente.SolicitarAceptacion(reclamacion);
if (!supervisor.AprobarPago(reclamacion))
{
supervisor.Rechazar(reclamacion);
return;
}
banco.EjecutarPago(reclamacion);
banco.NotificarPago(reclamacion);
supervisor.NotificarCliente(reclamacion);
agente.CerrarCaso(reclamacion);
}
}
// Main
class Program
{
static void Main()
{
new WorkflowReclamacion().Ejecutar();
}
}
Totalmente de acuerdo contigo : el código que se ha generado es deliberadamente burdo y directo, pensado para mostrar cómo se puede implementar un flujo BPMN sin necesidad de tirar de un motor de workflow como los más usados en C# —por ejemplo, Windows Workflow Foundation (WF) (ya obsoleto), Elsa Workflows, o integraciones con Camunda vía REST.
Sin embargo, este enfoque tiene un valor importante: te permite modelar el proceso directamente en código sin acoplarte a ningún runtime externo.
Y si eres más exigente o quieres más flexibilidad, hay alternativas muy potentes:
Opción 1: Leer el BPMN directamente
Puedes escribir un pequeño motor que:
-
Parsear el XML BPMN (con
System.Xml.Linq
) -
Contuir una representación del flujo como grafo
-
Ejecutar los nodos dinámicamente (por ejemplo, usando reflexión o patrones como Strategy)
Opción 2: Generar YAML o JSON intermedio
Puedes transformar el BPMN en algo como esto:
proceso: Reclamacion
pasos:
- id: validar_datos
tipo: tarea
siguiente: evaluar_siniestro
- id: evaluar_siniestro
tipo: decision
condiciones:
- si: siniestro == false
siguiente: rechazar
- si: siniestro == true
siguiente: calcular_pago
Y luego construir un motor de interpretación en C# para ejecutar ese YAML o JSON, lo cual te da:
-
Separación clara entre lógica de negocio y definición de flujo
-
Soporte a múltiples flujos sin recompilar
-
Potencial para auditar, visualizar o modificar dinámicamente procesos
Conclusión
Los diagramas BPMN han sido durante años una herramienta valiosa para representar procesos de negocio. Pero hoy, con la ayuda de la IA Generativa, pueden convertirse directamente en código funcional, acortando la distancia entre el diseño y la implementación como nunca antes. Lo que antes era documentación estática, ahora puede ser el punto de partida operativo de una solución viva, ejecutable y alineada con los objetivos del negocio.
Lo más potente de esta idea no es solo la automatización del código. Es el cambio de mentalidad: modelar deja de ser una fase previa para convertirse en la base del producto. Al convertir procesos en software a través de herramientas generativas, reducimos el tiempo de entrega, aumentamos la trazabilidad y reforzamos la colaboración entre negocio y tecnología.
Y lo más importante: esto no se limita a los procesos de negocio clásicos. Este modelo de pensamiento se puede extender a cualquier tipo de flujo estructurado. Imagina un equipo de arquitectura que define cómo abordar el inicio de un nuevo proyecto. Esa conversación puede convertirse en un workflow visual, y desde ahí generar automáticamente una presentación en PowerPoint, un documento Markdown para onboarding o incluso tareas automatizadas en herramientas como Azure DevOps. Lo mismo se aplica a flujos de soporte, gestión de incidencias o cualquier protocolo operativo.
Lo que ves aquí es solo la punta del iceberg. La IA Generativa no es solo una herramienta para escribir código más rápido, sino un facilitador para transformar ideas en sistemas. En este nuevo paradigma, cada diagrama no es solo una ilustración: es un contrato, un prototipo y un ejecutable potencial. Y con ello, el proceso de construir software empieza mucho antes… y llega mucho más lejos.