Cómo Crear un Constructor de Flujo de Trabajo Visual de Código Abierto para Agentes de IA en 2026
TL;DR
Un constructor de flujo visual para agentes de IA es un lienzo de nodos conectados más un motor que los ejecuta en orden de dependencia. El lienzo es un problema de UI (arrastrar, conectar, posicionar); el motor es un problema de grafo (ordenamiento topológico sobre un grafo acíclico dirigido, o DAG).
React Flow (publicado como el paquete @xyflow/react, versión actual 12.11.3, con licencia MIT) es la biblioteca de código abierto estándar para la mitad del lienzo. Renderiza nodos y bordes, maneja arrastre y zoom, y expone ganchos para leer y modificar el estado del grafo.
La mitad de ejecución —decidir qué se ejecuta, en qué orden, con qué entradas— no es algo que proporcione una biblioteca de lienzo. Debe escribirse como un pequeño motor separado: ordenar el grafo, ejecutar el manejador de cada nodo, y pasar la salida de cada nodo a los nodos que se conectan desde él.
Un nodo que necesita datos web en vivo (un nodo de "fetch" o "crawl") necesita una capa de fetch real detrás de él, no solo una llamada a fetch() — las páginas renderizadas en JavaScript y la protección anti-bot romperán silenciosamente una solicitud HTTP hecha a mano mucho antes de que lo haga el resto del flujo de trabajo.
El motor de ejecución de este artículo fue realmente ejecutado, no solo descrito: un grafo de cuatro nodos (disparador → rastreo → aviso → salida) fue ordenado topológicamente y ejecutado de extremo a extremo en este entorno, con salida real capturada mostrada a continuación.
Un constructor de flujo hecho a mano es un proyecto de fin de semana real y construible con dos piezas de código abierto verificadas (React Flow más un ordenamiento topológico), pero se entrega sin ninguna de las características operativas (autenticación, reintentos, registro a nivel de nodo, versionado) que necesita una herramienta de producción — este artículo establece ese límite explícitamente en lugar de pasarlo por alto.
Introducción: lo que realmente significa "construir tu propio constructor de flujo de agente"
Un constructor de flujo de agente de IA es, estructuralmente, dos sistemas separados que utilizan una UI: un lienzo donde una persona organiza y conecta nodos, y un motor que lee ese grafo y realmente lo ejecuta. El interés de búsqueda en herramientas de estilo "constructor de agentes abierto" ha crecido junto con plataformas de IA sin código y de bajo código, pero la mayoría de lo que aparece para esa frase es o bien un producto alojado sin código visible, o una breve demostración que dibuja un bonito lienzo y nunca ejecuta realmente nada. Este artículo construye lo real: un lienzo utilizando la biblioteca de código abierto React Flow, y un pequeño motor de ejecución ordenado por dependencia conectado a un nodo de obtención de datos en vivo, con el motor de ejecución realmente ejecutado y su salida capturada a continuación.
Dos cosas quedan intencionadamente fuera de alcance. Primero, esto no es un tutorial de ningún producto de flujo comercial o de código abierto específico — enseña el patrón subyacente con una biblioteca neutral para que el resultado sea tuyo para extender. Segundo, el "IA" en un nodo aquí significa que el manejador del nodo llama a un modelo de lenguaje o una herramienta; el motor del grafo en sí no tiene opinión sobre lo que un nodo hace internamente, que es exactamente lo que lo hace reutilizable para la automatización no relacionada con IA también.
Instalar: React Flow y un proyecto mínimo
React Flow se entrega como @xyflow/react en npm. En el momento de escribir esto, la versión publicada es 12.11.3 (confirmada directamente contra el registro de npm, e instalada limpiamente con un simple npm install en un proyecto nuevo durante la verificación para este artículo), y el paquete tiene licencia MIT según el repositorio de GitHub de xyflow.
Crea un proyecto mínimo con Vite + React, luego agrega la biblioteca:
React Flow también entrega una hoja de estilos que debe ser importada una vez, o el lienzo se renderiza sin ningún diseño en absoluto:
import'@xyflow/react/dist/style.css';
Configurar: el esqueleto del lienzo
Un lienzo de React Flow necesita tres cosas: un array de nodos, un array de bordes, y el componente <ReactFlow> en sí. El ejemplo mínimo de la documentación oficial es esta forma:
Esa versión es estática: las matrices nunca cambian una vez renderizadas. Un constructor real necesita que el lienzo reaccione a los arrastres y nuevas conexiones, para lo cual están useNodesState y useEdgesState. Cada gancho devuelve la matriz actual, un setter y un manejador de cambios que se conecta directamente a las props onNodesChange / onEdgesChange de <ReactFlow>:
La documentación de React Flow señala que estos ganchos están destinados a prototipar un flujo controlado, y que un constructor más grande debería pasar a un almacén de estado dedicado (mencionando específicamente Zustand) una vez que el estado de nodos y bordes necesita compartirse fuera del componente del lienzo — lo cual hace un motor de ejecución real, ya que tiene que leer el mismo gráfico que el lienzo está mostrando.
Implementación básica: un tipo de nodo para una acción de agente
Los tipos de nodo predeterminados (input, default, output) solo renderizan una etiqueta. Un flujo de trabajo de agente necesita tipos de nodos que lleven configuración — una URL para un paso de obtención, una plantilla de prompt para un paso de modelo — y expongan puntos de conexión a los que otros nodos pueden adjuntarse. El patrón de nodo personalizado de React Flow es un componente React sencillo registrado en un mapa nodeTypes:
Un nodo con un mango target (izquierda) y un mango source (derecha) puede estar en medio de una cadena: recibe una conexión de un nodo upstream y envía su propia salida corriente abajo. Un nodo disparador solo necesitaría un mango source; un nodo de salida terminal solo necesitaría un mango target.
Patrones avanzados: un motor de ejecución que realmente ejecuta el gráfico
El lienzo solo produce dos matrices: nodos y bordes. Convertir eso en un flujo de trabajo en ejecución significa responder a una pregunta a la que la biblioteca de UI no responde: ¿en qué orden se ejecutan los nodos? La respuesta es un orden topológico: visitar cada nodo solo después de que cada nodo que alimenta a este ya se haya ejecutado. Esto es teoría de grafos, no React, por lo que se escribió y ejecutó como un script sencillo para este artículo en lugar de dejarlo como un diagrama.
El gráfico probado: un nodo disparador, un nodo de rastreo que obtiene una página, un nodo de prompt que resume lo que devolvió el nodo de rastreo y un nodo de salida.
functiontopoSort(nodeList, edgeList){const indegree =newMap(nodeList.map((n)=>[n.id,0]));const adjacency =newMap(nodeList.map((n)=>[n.id,[]]));for(const edge of edgeList){ adjacency.get(edge.source).push(edge.target); indegree.set(edge.target, indegree.get(edge.target)+1);}const queue = nodeList.filter((n)=> indegree.get(n.id)===0).map((n)=> n.id);const order =[];while(queue.length){const id = queue.shift(); order.push(id);for(const next of adjacency.get(id)){ indegree.set(next, indegree.get(next)-1);if(indegree.get(next)===0) queue.push(next);}}if(order.length!== nodeList.length){thrownewError('El gráfico tiene un ciclo: un flujo de trabajo debe ser un DAG');}return order;}
La verificación de ciclos importa más de lo que parece: una interfaz de usuario de lienzo permitirá felizmente que alguien arrastre un borde que cree un bucle (el nodo A alimenta al nodo B alimenta al nodo A), y sin esta verificación, el motor podría colgarse o eliminar silenciosamente nodos en lugar de decirle a la persona que construyó el flujo de trabajo qué está mal.
Con un orden de ejecución en mano, ejecutar el flujo de trabajo es un bucle que llama al manejador de cada nodo e inserta salidas en entradas a lo largo de los bordes que apuntan a él:
asyncfunctionrun(nodes, edges){const order =topoSort(nodes, edges);const nodesById =newMap(nodes.map((n)=>[n.id, n]));const outputs =newMap();const log =[];for(const id of order){const node = nodesById.get(id);```javascript
const incoming = edges.filter((e) => e.target === id).map((e) => outputs.get(e.source));
let result;
switch (node.type) {
case 'trigger': result = 'ejecución-iniciada'; break;
case 'crawl': result = await runCrawlNode(node); break;
case 'prompt': result = runPromptNode(node, incoming[0]); break;
case 'output': result = incoming[0]; break;
default: throw new Error(`Tipo de nodo desconocido: ${node.type}`);} outputs.set(id, result); log.push({node: id,type: node.type,output: result });}return{ order, log };}
runCrawlNode es donde una llamada fetch() hecha a una URL arbitraria presenta problemas: muchas páginas reales se renderizan del lado del cliente, bloquean solicitudes sin una huella digital del navegador o necesitan un proxy para acceder de manera confiable. Para la ejecución de verificación de este artículo, ese controlador llamó al endpoint de POST /api/v1/crawl/scrape de Nstproxy Crawl (documentado en docs.nstproxy.com/docs/crawl) — que devuelve Markdown renderizado en lugar de HTML crudo — por lo que la tarea del nodo de rastreo se redujo a desenvvolver la respuesta en lugar de reimplementar un navegador:
asyncfunctionrunCrawlNode(node){const response =awaitfetch('https://api.nstproxy.com/api/v1/crawl/scrape',{method:'POST',headers:{'x-api-key': process.env.NSTPROXY_API_KEY,'Content-Type':'application/json'},body:JSON.stringify({url: node.data.url,formats:['markdown'],onlyMainContent:true}),});const envelope =await response.json();if(envelope.err)thrownewError(envelope.msg||'la solicitud de rastreo falló');const inner = envelope.data;if(!inner.success)thrownewError(inner.status||'el rastreo no se completó');return inner.data.markdown;}
Este entorno no tiene acceso a la red saliente hacia dominios arbitrarios y no tiene una clave de API de Nstproxy en vivo, por lo que la ejecución de verificación a continuación sustituye un accesorio HTTP local que devuelve exactamente el sobre de respuesta anidada que especifica la propia documentación de Nstproxy Crawl (código externo code/err/msg/data, interno data.success/status, carga útil de la página en data.data.markdown) en lugar del verdadero endpoint — esto se revela aquí en lugar de presentarse como una llamada API en vivo. La lógica de desenvoltura en sí (verificando err, luego success, luego leyendo data.data.markdown) es exactamente lo que se ejecuta contra el endpoint real; solo el objetivo de transporte cambió para esta prueba.
Ejemplo trabajado: ejecutando el grafo de cuatro nodos
El grafo utilizado para esta ejecución: start (disparador) → fetch (nodo de rastreo que apunta a una página de producto de Nstproxy Crawl) → prompt (resume lo que el nodo de rastreo devolvió) → output. Se ejecutó con Node.js (v22.22.2) en este entorno, con fetch apuntando a un servidor local de accesorio que sustituye a la verdadera API de Nstproxy Crawl por la razón explicada anteriormente.
Salida capturada:
{"order":["start","fetch","prompt","output"],"log":[{"node":"start","type":"trigger","output":"ejecución-iniciada"},{"node":"fetch","type":"crawl","output":"# Nstproxy Crawl\n\nNstproxy Crawl convierte una URL en Markdown limpio, JSON o una captura de pantalla con una sola llamada a la API, con renderizado en JavaScript y acceso respaldado por proxy incorporado."},{"node":"prompt","type":"prompt","output":"Resume esta página en una frase:\n\n# Nstproxy Crawl\n\nNstproxy Crawl convierte una URL en Markdown limpio, JSON o una captura de pantalla con una sola llamada a la API, con renderizado en JavaScript y acceso respaldado por proxy incorporado.\n\n[salida del modelo simulado] Nstproxy Crawl — resumen de una línea generado a partir de la página recuperada."},{"node":"output","type":"output","output":"Resume esta página en una frase:\n\n# Nstproxy Crawl\n\nNstproxy Crawl convierte una URL en Markdown limpio, JSON o una captura de pantalla con una sola llamada a la API, con renderizado en JavaScript y acceso respaldado por proxy incorporado.\n\n[salida del modelo simulado] Nstproxy Crawl — resumen de una línea generado a partir de la página recuperada."}]}
El arreglo order confirma que el orden topológico colocó cada nodo después de sus dependencias, y el arreglo log muestra la salida de cada nodo fluyendo hacia el siguiente — el Markdown del nodo de rastreo se convirtió en la entrada del nodo de aviso, y el resumen (simulado) del nodo de aviso se convirtió en la salida final. La llamada del modelo del nodo de aviso es un reemplazo determinista en lugar de una real llamada de API LLM, revelado de la misma manera que la sustitución del rastreo anterior; sustituir por una llamada de modelo real significa llamar al SDK del proveedor correspondiente dentro de runPromptNode en lugar de la línea simulada.
Eche un vistazo rápido
```
Cada nodo "fetch" en un flujo de trabajo como este eventualmente accede a una página que necesita renderizado de JavaScript o bloquea una solicitud HTTP simple; Nstproxy Crawl maneja esa capa con una llamada a la API en lugar de un navegador hecho a mano.
Una construcción de fin de semana de un lienzo más un motor de ordenación topológica demuestra que el patrón central funciona, pero le falta todo lo que una herramienta de flujo de trabajo de producción necesita alrededor de ese núcleo. No hay capa de persistencia; el gráfico en este artículo vive en la memoria durante una ejecución y nada se guarda entre sesiones. No hay manejo de reintentos o fallos parciales: si la solicitud del nodo de rastreo falla, toda la ejecución arroja en lugar de reintentar o redirigir a una rama de error. No hay un registro de ejecución por nodo mostrado de vuelta en la interfaz de usuario del lienzo, ninguna forma de pausar e inspeccionar el estado a mitad de ejecución, ninguna autenticación o control de acceso multiusuario, y no hay versionado de un flujo de trabajo guardado. También falta protección contra un controlador de nodo que ejecuta de forma segura código arbitrario proporcionado por el usuario: cualquier tipo de nodo de "código personalizado" en un producto real necesita un entorno de ejecución en un espacio aislado, que la declaración switch simple de este artículo no proporciona. Ninguno de estos es trabajo de React Flow para resolver; son el trabajo de ingeniería real de convertir este patrón en una herramienta de la que otras personas pueden depender. Si la capa de búsqueda de datos de un nodo de rastreo es la parte que se está externalizando en lugar de construirse a mano, vale la pena comprobar la tarificación de una API alojada frente al volumen de llamadas esperado antes de comprometer el paso de búsqueda de un flujo de trabajo a ella.
Solución de problemas
El lienzo se renderiza sin estilo o nodos superpuestos. Esto casi siempre significa que se omitió la importación @xyflow/react/dist/style.css — React Flow posiciona los nodos con coordenadas absolutas que dependen de su propia hoja de estilo base.
Un flujo de trabajo con un bucle se cuelga o suprime nodos en silencio. Este es el caso del ciclo que lanza la función topoSort mencionada anteriormente — una interfaz de usuario de lienzo no tiene una forma incorporada de evitar que alguien conecte un borde que crea un ciclo, por lo que el motor tiene que verificarlo explícitamente en lugar de asumir que cada gráfico que un usuario construye es un DAG válido.
Un nodo personalizado no acepta conexiones. Verifica que el componente del nodo incluya un Handle con el type correcto (source o target) y que realmente se esté renderizando — un componente de nodo personalizado que omite <Handle> se renderiza bien visualmente, pero nunca podrá conectarse a otro nodo.
Un nodo "fetch" funciona para algunas URL y falla para otras. Eso suele ser un problema de renderizado de JavaScript o detección de bots, no un error en el código del nodo — una llamada fetch() simple solo ve el HTML sin procesar que devuelve un servidor, no lo que un navegador renderizaría después de ejecutar los scripts de la página, razón por la cual el nodo de rastreo en este artículo llama a una API consciente de renderizado en lugar de obtener la URL directamente.
Conclusión
Construir un constructor de flujos de trabajo de agentes de IA se divide limpiamente en dos partes verificadas: React Flow (@xyflow/react, versión 12.11.3, con licencia MIT) para el lienzo, y un pequeño motor de ordenación topológica escrito a mano para la ejecución; ninguno depende del otro, razón por la cual pueden desarrollarse y probarse por separado, como hizo este artículo. El resultado es un patrón real y ejecutable en lugar de un diagrama, probado con un gráfico de cuatro nodos ejecutado de extremo a extremo. Lo que no es, es un producto terminado; la persistencia, los reintentos, el aislamiento y el control de acceso siguen siendo un trabajo de ingeniería real que se superpone a este núcleo. Para obtener información sobre la capa de búsqueda de datos utilizada en el ejemplo trabajado, consulte la publicación sobre el lanzamiento de Nstproxy Crawl.
FAQ
P: ¿Necesito específicamente React Flow, o puedo usar otra biblioteca?
React Flow (@xyflow/react) es la biblioteca utilizada y verificada en este artículo, pero no es la única opción: Svelte Flow (el equivalente de Svelte del mismo equipo) cubre proyectos que no son de React, y cualquier biblioteca de lienzo que exponga posiciones de nodos, bordes y una forma de registrar componentes personalizados puede cumplir el mismo papel. El motor de ejecución descrito aquí es completamente independiente de qué biblioteca de lienzo lo renderiza, ya que solo consume arreglos simples de nodos y bordes.
P: ¿El motor de ejecución necesita ejecutarse en el navegador?
No — y para la mayoría de los flujos de trabajo reales no debería. El lienzo se ejecuta en el navegador, por lo que una persona puede editar el gráfico, pero ejecutar un flujo de trabajo (especialmente uno con claves de API o pasos de larga duración) pertenece a un servidor. El motor mostrado en este artículo es JavaScript puro sin dependencia del navegador, por lo que puede ejecutarse en Node.js exactamente como se probó aquí, o dentro de cualquier entorno backend que soporte fetch.
P: ¿Cómo puedo evitar que alguien conecte un flujo de trabajo que se repita indefinidamente?
Recházalo antes de ejecutarlo. La función topoSort en este artículo lanza una excepción cuando el orden ordenado no incluye cada nodo, que es exactamente lo que sucede cuando existe un ciclo: captura ese error en la UI del lienzo y dile a la persona qué nodos están involucrados, en lugar de permitir que el motor se cuelgue.
P: ¿Puede un nodo llamar a más de un servicio externo?
Sí — un manejador de nodo es solo una función; puede hacer tantas llamadas como necesite antes de devolver su salida. La única restricción que impone el motor es que el manejador de un nodo solo recibe las salidas de los nodos con un borde que apunta hacia él, por lo que cualquier nodo que necesite datos de dos fuentes ascendentes necesita dos bordes entrantes.
P: ¿Cuál es la forma más rápida de agregar una llamada a un modelo de lenguaje real en lugar del nodo de aviso simulado?
Reemplaza el cuerpo de runPromptNode con una llamada al SDK del proveedor de modelo que se esté utilizando, pasando la salida del nodo entrante como contexto y devolviendo la respuesta del modelo como una cadena: el resto del motor (ordenamiento, paso de salida, registro) no necesita cambiar, ya que solo le importa que un manejador de nodo devuelva un valor.
P: ¿Por qué el nodo de rastreo llama a una API en lugar de usar fetch() directamente?
Una llamada fetch() simple solo recibe el HTML que un servidor envía antes de que se ejecute cualquier JavaScript del lado del cliente, y muchas páginas renderizan su contenido real después: una API consciente del renderizado ejecuta la página como lo haría un navegador antes de devolver Markdown o HTML, que es en lo que se basa el nodo de rastreo en el ejemplo trabajado de este artículo.
Cómo Crear un Constructor de Flujo de Trabajo Visual de Código Abierto para Agentes de IA en 2026
Construya un verdadero generador de flujos visuales de código abierto para agentes de IA: un lienzo de React Flow emparejado con un motor de ejecución de orden topológico verificado, probado de extremo a extremo con salida capturada real.
Ivy Lin
Aug. 24th 2026
110M+ IP reales con 99.9% de acceso exitoso
Respuesta media ultrarrapida ~0.5s para tareas de alta concurrencia
Desde solo $0.1/GB
Acceso inmediato a pools premium de proxies residenciales, datacenter, IPv6 e ISP.