Multi-agente con LangGraph: patrones de supervisor y trabajadores

By Carlos Montiel | Especialista en IA Empresarial
Publicado: 2026-07-28 | Por: Carlos Montiel | Lectura: ~4 minutos

Un solo agente con demasiadas herramientas se vuelve lento e impreciso. El patrón supervisor-trabajadores en LangGraph divide el problema entre agentes especializados coordinados por uno que decide a quién delegar.

Por qué dividir en varios agentes

Un agente con 20 herramientas distintas —búsqueda web, consulta a base de datos, generación de reportes, envío de correos— tiene dos problemas medibles: el modelo elige peor la herramienta correcta cuando el catálogo es grande, y el prompt de sistema se vuelve inmanejable. El patrón supervisor-trabajadores resuelve esto asignando subconjuntos pequeños de herramientas a agentes especializados, y delegando la decisión de "a quién le toca" a un nodo supervisor cuya única tarea es enrutar.

Estructura básica del supervisor

from typing import Literal from langgraph.graph import StateGraph, START, END from langchain_core.messages import HumanMessage class EstadoEquipo(TypedDict): mensajes: Annotated[list, operator.add] siguiente: str miembros = ["investigador", "analista_financiero", "redactor"] def supervisor(estado: EstadoEquipo) -> EstadoEquipo: prompt_sistema = ( f"Eres el supervisor de un equipo con estos miembros: {miembros}. " "Dado el estado de la conversación, decide quién debe actuar a continuación, " "o responde 'FINALIZAR' si la tarea está completa." ) respuesta = llm_con_salida_estructurada.invoke( [SystemMessage(content=prompt_sistema)] + estado["mensajes"] ) return {"siguiente": respuesta.siguiente}

El supervisor típicamente usa salida estructurada (`with_structured_output` sobre un modelo Pydantic con un campo `Literal` restringido a los nombres válidos de los miembros) para garantizar que el enrutamiento sea siempre a un nodo existente, evitando que el modelo invente un destino.

Conectando trabajadores y aristas condicionales

def nodo_investigador(estado: EstadoEquipo): resultado = agente_investigador.invoke({"messages": estado["mensajes"]}) return {"mensajes": [AIMessage(content=resultado["output"], name="investigador")]} builder = StateGraph(EstadoEquipo) builder.add_node("supervisor", supervisor) builder.add_node("investigador", nodo_investigador) builder.add_node("analista_financiero", nodo_analista) builder.add_node("redactor", nodo_redactor) for miembro in miembros: builder.add_edge(miembro, "supervisor") builder.add_conditional_edges( "supervisor", lambda estado: estado["siguiente"], {"investigador": "investigador", "analista_financiero": "analista_financiero", "redactor": "redactor", "FINALIZAR": END}, ) builder.add_edge(START, "supervisor") equipo = builder.compile()

Cada trabajador, tras actuar, regresa siempre al supervisor, que decide el siguiente paso. Este ciclo continúa hasta que el supervisor determina que la tarea está completa.

Simplificando el enrutamiento con Command

Las versiones recientes de LangGraph permiten que un nodo devuelva directamente un objeto `Command`, combinando la actualización de estado con la decisión de a qué nodo ir, sin necesitar una arista condicional separada:

from langgraph.types import Command def supervisor(estado: EstadoEquipo) -> Command[Literal["investigador", "analista_financiero", "redactor", "__end__"]]: respuesta = llm_con_salida_estructurada.invoke(estado["mensajes"]) destino = respuesta.siguiente if respuesta.siguiente != "FINALIZAR" else "__end__" return Command(goto=destino, update={"siguiente": destino})

Esto reduce el boilerplate de `add_conditional_edges` cuando la lógica de enrutamiento vive naturalmente dentro del propio nodo que decide.

Subgrafos para agentes complejos como nodos

Cuando un "trabajador" es en sí mismo un agente con su propio ciclo ReAct de herramientas, conviene construirlo como un `StateGraph` independiente y usarlo como nodo del grafo del supervisor mediante `.compile()`, que produce un `Runnable` compatible:

subgrafo_investigador = builder_investigador.compile() builder.add_node("investigador", subgrafo_investigador)

Esta composición jerárquica —grafos dentro de grafos— es la forma recomendada de escalar arquitecturas multi-agente sin que el grafo principal se vuelva ilegible: el supervisor no necesita saber que "investigador" internamente hace 4 llamadas a herramientas en un ciclo propio.

Cuándo NO usar este patrón

Si las tareas no requieren especialización real de herramientas o conocimiento, dividir en múltiples agentes añade latencia (cada salto por el supervisor es una llamada extra al modelo) y costo sin beneficio de calidad. En nuestra experiencia, el patrón se justifica quirúrgicamente cuando hay dominios claramente separables —por ejemplo, un agente que solo consulta bases de datos SQL y otro que solo redacta en lenguaje natural— y no como arquitectura por defecto para cualquier problema conversacional.

Carlos Montiel
Arquitecto de Soluciones IA Empresarial
Especialista en LLMs, Agentes y Orquestación
guatemalia.com/#contacto · info@guatemalia.com

¿Necesitas implementar IA en tu empresa?

Carlos Montiel es arquitecto de soluciones IA empresarial. Implementa LLMs, Agentes, RAG y orquestadores en empresas de Guatemala y Latinoamérica. Contáctalo para una consultoría.

Contactar a Carlos Montiel

info@guatemalia.com