Inicio / Artículos

Agentes LangGraph en paralelo que revisan solicitudes de pull a través de webhooks FastAPI.

Cómo un webhook, una cola de Redis y cuatro agentes LangGraph convierten una solicitud de pull en una revisión estructurada e evaluada por IA en aproximadamente 30 segundos, con ngrok para pruebas locales.

Editor: REACTAPP.TOP12 min de lectura2837 palabras

Fuentes: Building a Multi-Agent PR Code Review System With LangGraph, FastAPI, Webhooks, and Docker

Cualquiera que haya abierto una solicitud de integración conoce esa espera. Se termina una función, se sube el código y luego pasan dos horas, o un día entero, o incluso más. Cuando finalmente un compañero de equipo lo revisa, hay una docena de comentarios y la mitad se refieren a cosas que el software podría haber detectado: una clave API hardcodeada, una función llamada x, una consulta SQL vulnerable a inyecciones. El autor corrige todo, vuelve a subir el código y espera de nuevo.

La revisión de código en sí es esencial, así que ese no es el problema. La frustración radica en que tantos comentarios iniciales son mecánicos, con las mismas categorías de errores en cada solicitud. La idea detrás de este sistema es permitir que una IA detecte de inmediato todo lo obvio para que los revisores humanos puedan dedicar su tiempo a la arquitectura y la lógica, donde realmente se necesita el juicio humano. Funciona mejor de lo que cabría esperar.

Por qué varios agentes son mejores que uno

El diseño ingenuo envía la diferencia del PR a un modelo con instrucciones para que la revise. Eso funciona bien para cambios pequeños. A medida que los PRs crecen, un modelo al que se le pide considerar la seguridad, el rendimiento y la calidad del código al mismo tiempo pierde enfoque y las conclusiones empeoran.

La especialización soluciona este problema. Asigna a cada agente una única tarea: uno que solo se ocupe de la seguridad, otro solo del rendimiento, otro solo de la calidad del código, y un cuarto que tome los tres informes y escriba una revisión clara y profesional. Este patrón de múltiples agentes ofrece resultados notablemente mejores que un agente generalista.

El diseño general, con cada componente encargado de una responsabilidad específica:

You open a Pull Request on GitHub
              │
              ▼
    GitHub fires a webhook
              │
              ▼
    FastAPI receives it instantly
    └── Verifies HMAC signature
    └── Pushes job to Redis queue
    └── Returns 202 to GitHub ✅
              │
              ▼
    ARQ Worker picks up the job
              │
              ▼
    LangGraph Pipeline starts
              │
    ┌─────────┼─────────┐
    ▼         ▼         ▼
 Agent 1   Agent 2   Agent 3
 Quality   Security  Performance
    │         │         │
    └─────────┼─────────┘
              ▼
           Agent 4
        Final Reviewer
              │
              ▼
    Comment posted on your PR ✅
    (in under 30 seconds)

Paso 1: el webhook de GitHub

Todo comienza con un webhook. Cuando se abre o actualiza una solicitud de fusión, GitHub envía una petición HTTP POST a una URL que usted configura; dicha petición incluye el número de la solicitud, su título, el autor, el repositorio y la acción que la desencadenó. Un servidor FastAPI escucha en esa URL.

La primera acción del servidor ante cualquier petición es verificar la firma. GitHub firma cada carga útil con un hash HMAC-SHA256 utilizando una clave secreta que usted define, y cualquier discrepancia hace que la petición sea rechazada de inmediato, por lo que nadie puede enviar eventos falsos de solicitudes de fusión al endpoint.

La siguiente decisión es la crucial: el servidor no inicia la revisión por IA de inmediato. Coloca una tarea en una cola de Redis y responde a GitHub con 202 Accepted en menos de un segundo. La razón es que GitHub espera una respuesta vía webhook dentro de 10 segundos, mientras que una revisión completa con tres llamadas paralelas a modelos de lenguaje lleva de 25 a 30 segundos. Revisar el contenido directamente haría que GitHub pensara que el servidor falló y lo intentaría de nuevo, por lo que la PR sería revisada varias veces con comentarios duplicados. Una cola de tareas resuelve este problema de forma definitiva. GitHub recibe su respuesta rápida y el trabajo real se realiza en segundo plano.

Paso 2: ngrok para el desarrollo local

Durante el desarrollo local, el servidor FastAPI funciona en localhost:8000, a la cual GitHub no puede acceder desde Internet. ngrok cubre esta brecha al crear un túnel seguro entre una URL pública y la máquina local. Un comando es suficiente para iniciarlo:

ngrok http 8000

Devuelve de inmediato una dirección HTTPS pública como esta:

https://abc123.ngrok-free.app

Pega esa dirección en la configuración del webhook de GitHub y así GitHub podrá enviar los eventos directamente al ordenador portátil. Cada vez que se abre un PR, la solicitud viaja desde los servidores de GitHub a través de los servidores de ngrok hasta la aplicación local FastAPI. En la terminal, todo el intercambio aparece como una sola línea:

23:03:02 POST /api/webhook    202 Accepted  ✅

Una línea, bajo otra, y GitHub queda satisfecho mientras el verdadero trabajo comienza entre bastidores. Una advertencia: la versión gratuita de ngrok genera una nueva URL con cada reinicio, por lo que la URL del webhook de GitHub debe actualizarse cada vez.

Paso 3: el pipeline de LangGraph

Este es el núcleo del sistema. LangGraph es un marco para flujos de trabajo multiagente con estado. Los agentes se convierten en nodos en un grafo, las aristas los conectan y el estado compartido fluye entre ellos. Imagina un diagrama de flujo donde cada caja representa un agente de IA y las flechas indican qué datos se mueven a dónde y en qué orden.

Estado compartido

Todos los agentes leen y escriben en un objeto de estado compartido que contiene el número de la PR y los detalles del repositorio, la diferencia obtenida con los cambios reales en el código, los resultados de revisión de cada agente y el comentario sintetizado final. Este objeto se transmite por la red como un testigo en una carrera de relevos, donde cada agente añade su parte antes de pasarla al siguiente.

Nodo 0: obtener la PR

Un nodo dedicado se ejecuta antes que cualquier agente y consulta la API de GitHub para obtener el título, el autor y la rama de la PR, junto con la diferencia completa de cada archivo modificado. Convierte todo eso en una cadena de texto ordenada que los LLM pueden leer, y la misma diferencia formateada se envía a cada uno de los revisores.

La expansión paralela: agentes 1, 2 y 3

Después de la obtención de los datos, la red se expande hacia tres agentes al mismo tiempo. Ellos reciben la misma diferencia, se ejecutan en el mismo instante y no saben nada unos de otros.

El agente de calidad del código funciona exclusivamente en su propio mundo. Su indicador de sistema abarca la legibilidad, las convenciones de nomenclatura, las violaciones del principio DRY, el manejo de errores y la mantenibilidad, y devuelve JSON estructurado con una puntuación del 1 al 10 además de una lista de problemas específicos, cada uno con el nombre del archivo, el número de línea y la solución sugerida.

El agente de seguridad solo busca vulnerabilidades: inyección SQL a partir de datos no sanitizados, claves, contraseñas o tokens codificados directamente en el código, falta de verificaciones de autenticación y datos sensibles en los registros. No sabe nada sobre rendimiento ni estilo.

El agente de rendimiento solo piensa en la eficiencia: patrones de consultas a la base de datos N+1, bucles anidados con complejidad O(n²) o peor aún, llamadas de E/S bloqueantes dentro de funciones asíncronas, y falta de índices u oportunidades de caché.

El paralelismo es importante en cuestión de tiempo. Si se ejecutan secuencialmente, los tres agentes necesitarían entre 60 y 90 segundos en total. Si se ejecutan juntos, terminan en aproximadamente 7 a 12 segundos, que corresponde al tiempo del agente más lento y no a la suma de los tres.

El fan-in: agente 4

El revisor final espera automáticamente a que los tres especialistas hayan terminado. LangGraph se encarga de esa sincronización, por lo que no es necesario escribir lógica de espera o consulta. Cuando los tres informes llegan en formato JSON estructurado, el agente 4 realiza una acción y escribe el comentario final de revisión en Markdown.

El Agente 4 no realiza ninguna análisis. Nunca vuelve a examinar el código y solo combina y formatea lo que informaron los especialistas. Eso es intencional: incluso si su redacción varía ligeramente, los hallazgos subyacentes siguen siendo exactamente los que produjeron los especialistas. Su comentario comienza con un veredicto general y una puntuación que es la media de las puntuaciones de los tres agentes, luego resume lo que encontró cada agente, y finaliza con una lista de problemas que deben corregirse antes de la fusión, limitada a problemas críticos y de alta gravedad.

Un problema en el estado paralelo

Un detalle técnico sutil es fácil de pasar por alto. Una vez que los agentes en paralelo completan sus tareas y escriben de nuevo en el estado compartido, cada uno debe devolver únicamente la clave que posee. Si cada agente devuelve todo el objeto de estado, LangGraph recibe simultáneamente tres copias conflictivas de cada campo compartido y lanza un InvalidUpdateError. La solución es sencilla pero no obvia: adjuntar un reductor Annotated a los campos en los que escriben los agentes en paralelo, y hacer que cada agente devuelva solo su propio resultado. Se aprende esto al encontrarse con el error, y la mayoría de los tutoriales de LangGraph nunca lo mencionan.

Paso 4: el resultado

La prueba está en una prueba. Un archivo de Python que contenía cuatro problemas intencionados, un secreto codificado directamente, una vulnerabilidad de inyección SQL, un bucle anidado O(n²) y nombres poco adecuados, fue subido a una rama y abierto como solicitud de integración. Una revisión apareció en la PR 27 segundos después. Este era el código que se incluyó:

import sqlite3

# Hardcoded secret — security agent should catch this
API_KEY = "sk-prod-supersecretkey123"

def get_user(user_id):
    conn = sqlite3.connect("users.db")
    # SQL injection — security agent should catch this
    query = f"SELECT * FROM users WHERE id = {user_id}"
    return conn.execute(query)

def process(users):
    # O(n²) nested loop — performance agent should catch this
    for user in users:
        for item in users:
            print(user, item)

# Bad naming — quality agent should catch this
def x(a, b, c):
    return a + b + c

Y esto es lo que el sistema publicó en la PR:

## 🤖 AI Code Review

**Overall Verdict:** ❌ REJECTED
**Score:** 2.33/10

---

### 📋 Code Quality
Score: 2/10 | 8 Issues Found

Function naming is completely unclear — x, a, b, c give no
indication of purpose. No error handling on database operations.
No docstrings or type hints on any function.

### 🔒 Security
Score: 2/10 | 4 Critical Vulnerabilities

Hardcoded API key on line 3 exposes credentials in version
control — CRITICAL. SQL query on line 9 directly interpolates
user input, creating a SQL injection vulnerability — CRITICAL.

### ⚡ Performance
Score: 3/10 | 4 Issues Found

Nested loop in process() creates O(n²) complexity — will become
extremely slow as the users list grows. Database connection is
opened but never closed, creating a connection leak.

---

### 🚨 Must Fix Before Merge

- Remove API_KEY hardcoding — use environment variables instead
- Parameterize the SQL query to prevent injection attacks
- Refactor nested loop — use set operations or single pass
- Close database connections properly or use a context manager

---

Great effort on the overall structure! Addressing these critical
issues will significantly improve the security and reliability
of this code. Looking forward to the revised version. 🙌

Dos minutos y 27 segundos después de crear la solicitud de integración, la revisión identificó cuatro categorías reales de problemas con referencias específicas a las líneas de código y sugerencias de solución. No hubo participación humana ni tiempo de espera; simplemente se obtuvo retroalimentación estructurada y útil de inmediato.

Ejecutarlo localmente

Todo comienza con una sola orden de Docker: se establecen las variables de entorno, se crea un token de GitHub y se configura el webhook; ngrok conecta el servidor local a GitHub, y una PR de prueba muestra cómo aparece la revisión en tiempo real. Cambiar entre Claude y OpenAI solo requiere modificar una variable de entorno, y los pasos de configuración están documentados en el archivo README del repositorio.

Lecciones de la implementación

Los agentes especializados superan a los generalistas. Asignar una tarea por agente genera resultados más precisos y dirigidos, ya que el agente de seguridad no se ve influenciado por el estilo del código y el agente de rendimiento no gasta tokens en nombres de variables.

La cola de tareas forma parte de la arquitectura y no es una opción. El tiempo de espera de 10 segundos de GitHub es estricto, y sin Redis ni un proceso en segundo plano, las entregas fallidas se intentan nuevamente y se acumulan revisiones duplicadas. Muchos tutoriales omiten este aspecto, pero es precisamente lo que hace que el sistema sea fiable.

La ejecución paralela cambia la cálculo. Tres llamadas secuenciales de 10 segundos cada una necesitan al menos 30 segundos, mientras que tres llamadas paralelas solo requieren 10. LangGraph hace que el uso del paralelismo sea sencillo de implementar, y la diferencia es drástica.

La salida estructurada es lo que hace que los agentes estén listos para su uso en producción. Cada agente devuelve un esquema JSON estricto, y si la interpretación falla, la tarea fracasa de manera limpia sin que nada se publique en GitHub. El sistema entrega o bien una buena revisión o bien nada, pero nunca datos inútiles.

Abstraiga el LLM desde el primer día. Un patrón de fábrica que permite alternar entre Claude y OpenAI mediante una variable de entorno tarda unos diez minutos en crearse y ahorra horas de refactorización posterior, ya que se pueden probar modelos y comparar libremente su calidad en la revisión.

Qué deja sin cambios en la revisión de código

La revisión de código no desaparecerá, y para decisiones arquitectónicas, lógica de negocio y equilibrios delicados en el diseño, nada reemplaza a un ser humano. La primera revisión mecánica es otra cuestión: los secretos codificados, las inyecciones SQL, los bucles cuadráticos y los nombres poco claros pueden automatizarse, lo que libera a los revisores humanos para tareas que requieren inteligencia humana. Este sistema detecta los problemas obvios en unos 30 segundos para que los compañeros de equipo puedan concentrarse en los importantes.

Lecturas relacionadas

  • Mapeo del ecosistema de IA de Laravel: Prism, LarAgent, Neuron AI y Boost — De simples llamadas a LLM a agentes completos en Laravel: qué hacen Prism, LarAgent, Neuron AI, el SDK de IA y Boost, con un ejemplo de RAG para preguntas sobre políticas de recursos humanos.
  • Comparación de los modos de transmisión de LangGraph: actualizaciones, valores y astream_events — Un ejemplo funcional de LangGraph muestra cuándo transmitir actualizaciones de nodos, snapshots completos del estado o eventos a nivel de token, además de un patrón para entornos de producción y errores comunes.
  • Python para desarrolladores de JS: Un agente para Gmail y Calendar con FastAPI y LangGraph — Aprende Python creando un asistente personal que solo maneje borradores: FastAPI, Google OAuth para Gmail y Calendar, herramientas de LangGraph, modelos locales de Ollama y transmisión en tiempo real mediante SSE.
  • 10 frameworks de agentes de IA que debes conocer en 2026: LangGraph, CrewAI y más — Diez frameworks de agentes clasificados según cómo coordinan a los mismos, con sus ventajas y desventajas, usos óptimos y una guía para elegir uno adecuado para tu equipo.
  • Tu primer agente LangGraph: un asistente de fútbol con herramientas y enrutamiento — Tutorial paso a paso de LangGraph: estado compartido, herramientas, un nodo planificador, bordes condicionales y un resumen en markdown, desarrollado alrededor de un asistente ficticio para estadísticas de fútbol.
  • RAG en Python sencillo: fragmentación, TF-IDF, similitud coseno y técnicas de prompt — Crea generación reforzada por recuperación únicamente con el módulo matemático: fragmentación por ventana deslizante, vectores TF-IDF, clasificación por similitud coseno, un prompt bien estructurado y sus limitaciones.
  • LLMOps para un agente de tareas: MLflow Traces, Evals y una puerta de control CI — Crea un asistente de tareas PydanticAI con FastAPI, haz el seguimiento de su funcionamiento con MLflow, evalúa sus resultados con herramientas GenAI y bloquea las regresiones en GitHub Actions, todo ello con modelos locales.
  • IntentFlow: Gobernar agentes LLM con políticas compiladas y trazas verificables — Una introducción a IntentFlow, un lenguaje experimental que aplica políticas en los agentes fuera del modelo y genera trazas en cadena de hash que un auditor puede verificar de forma independiente.
  • Conceptos de LangGraph en lenguaje sencillo: estado, memoria y orquestación — Antes de escribir código: qué significan la orquestación, el tiempo de ejecución, los agentes con estado, la memoria a corto y largo plazo, los agentes múltiples y la intervención humana en LangGraph.
  • Creación de agentes autocorregibles con LangGraph: cinco consejos prácticos — Construya un agente de búsqueda de LangGraph que intente nuevamente en caso de fallo, con explicaciones sobre el estado, los bordes condicionales, la creación de puntos de control, la aprobación humana y los nodos pequeños, todo ello mediante código funcional.
  • Construyendo un agente de soporte LEPA con LangGraph — Wire SupportState, nodos de recepción y clasificación, bordes condicionales y START/END para que una solicitud de soporte escolar pueda aclararse o continuar hacia los documentos correspondientes.
  • Un bot de revisión de pull requests de código abierto: LangGraph, Node.js y GitHub Webhooks — Revisar solicitudes de pull requests con un agente LangGraph en fases que verifica la seguridad, el rendimiento y la arquitectura, y publica comentarios a nivel de línea a través de la API de GitHub.
  • Un harness de producción para Claude Code: seis capas desde Slack hasta el código fusionado — Cómo un harness de seis capas convierte los tickets de Slack en código fusionado: captura de eventos, bucles de agente con control, estado duradero, autoreparación, capacidad de observación y control por parte del operador.
  • Ingeniería de bucles: cuatro bucles anidados para agentes de IA que se mejoran por sí mismos — Cómo cuatro bucles de control anidados (ReAct, reintentos, cola, escalada de colinas) junto con un juez, un medidor de presupuesto y una verificación contra modificaciones hacen que un agente sea fiable, como se demuestra en la evaluación de seguros.
  • Orquestación de Multi-Agentes en Bedrock y LangGraph: Cuatro patrones — Patrones supervisor-trabajador, pipeline, fan-out y debate con LangGraph en AWS Bedrock, además de mecanismos de transferencia de tareas, controles de presupuesto, seguimiento y modos de fallo en producción.
  • Notas prácticas: Construyendo un pipeline ISR moderno para modalidad de código en sistemas grandes — Guía paso a paso de las Notas prácticas: Construyendo un pipeline ISR moderno para modalidad de código en sistemas grandes: contratos, verificaciones y espacios de código listos para usar por los equipos que implementan este patrón.
  • Un servicio de soporte con cinco ejecutores en Gemini 3.1 y ADK: triaje, investigación, acción, control de calidad y orquestador — Crea un sistema de soporte al cliente multiejecutor con Google ADK y Gemini 3.1: transferencias por escritura, bucles de corrección de control de calidad, Engine de Ejecutores o Cloud Run, sesiones y costos.
  • Diseño de un buscador de empleos multiejecutor: pipeline, HyDE y observabilidad — Un pipeline de LangGraph de nueve pasos que relaciona currículos con empleos, con ocho opciones de diseño en HyDE, enrutamiento de modelos, límites de tasa y seguimiento.
  • RAG con LangChain desde cero: Cargadores, fragmentos, embeddings, evaluación — Construye un sistema de preguntas y respuestas para documentos paso a paso: carga de archivos, fragmentación, embeddings, las fases de indexación y recuperación, y cómo calificar la recuperación y las respuestas.
  • Construcción de un sistema de investigación multi-agente con LangChain Deep Agents — Una visión práctica del patrón de Deep Agents: un orquestador, agentes especializados, herramientas seguras y una interfaz frontal en Streamlit, probado con LLMs locales y en la nube.
  • Un agente con buen contexto vence a un enjambre: por qué las transferencias dañan el código multiagente — Por qué la cadena de agentes multiplica los errores, cómo las transferencias pierden el estado, cuándo los agentes en paralelo sí ayudan, y una regla sencilla: distribuir la lectura, serializar la escritura y corregir el contexto primero.