Colaboración Multi-Agent con LangGraph: arquitecturas Supervisor y Swarm

En sistemas de IA conversacional complejos, un único agente suele toparse con límites de contexto, seguridad y paralelismo. La solución consiste en descomponer la responsabilidad en varios agentes especializados que se coordinan mediante un grafo dirigido. LangGraph ofrece dos patrones principales para lograrlo: Supervisor (centralizado) y Swarm (descentralizado).

  1. Fundamentos de la arquitectura Multi-Agent

Un multi-agente se compone de:

  • Roles aislados: cada agente posee su propio prompt de sistema, conjunto reducido de herramientas y estado interno.
  • Mecanismo de comunicación: intercambio de mensajes a través de un state compartido o mediante handoff directo.
  • Planificación: puede ser centralizada (un nodo Supervisor decide) o distribuida (cada agente decide a quién delega).
  1. Casos de uso que justifican múltiples agentes

Dimensión Agente único Multi-agente
Ventana de contexto Acumula todo el historial Cada agente carga solo lo necesario
Seguridad Todas las herramientas visibles Herramientas segregadas por rol
Ejecución Secuencial Paralela cuando los sub-procesos son independientes
Reutilización Nula El "agente revisor" se reutiliza en cualquier proyecto
  1. Implementación con LangGraph

3.1 Patrón Supervisor (centralizado)

Un nodo Supervisor analiza la petición y despacha a los agentes adecuados. Los agentes hijos no se comunican entre sí; siempre vuelven al Supervisor.

from langgraph.graph import StateGraph, END
from langgraph.prebuilt import create_react_agent
from langchain_openai import ChatOpenAI
from typing import TypedDict, Annotated
from langgraph.graph.message import add_messages

class EstadoCompartido(TypedDict):
    mensajes: Annotated[list, add_messages]
    siguiente: str

llm = ChatOpenAI(model="gpt-4-turbo")

investigador = create_react_agent(
    model=llm,
    tools=[buscar_web, leer_pdf],
    prompt="Eres un investigador. Devuelve solo hechos verificados.",
    name="investigador"
)

desarrollador = create_react_agent(
    model=llm,
    tools=[leer_repo, escribir_codigo, ejecutar_tests],
    prompt="Eres un desarrollador. No busques en internet.",
    name="desarrollador"
)

# Nodo Supervisor
def planificar(estado: EstadoCompartido):
    ultimo = estado["mensajes"][-1]["content"]
    if "investigar" in ultimo.lower():
        return {"siguiente": "investigador"}
    elif "implementar" in ultimo.lower():
        return {"siguiente": "desarrollador"}
    else:
        return {"siguiente": END}

builder = StateGraph(EstadoCompartido)
builder.add_node("planificar", planificar)
builder.add_node("investigador", investigador)
builder.add_node("desarrollador", desarrollador)

builder.set_entry_point("planificar")
builder.add_conditional_edges("planificar",
                              lambda s: s["siguiente"],
                              {"investigador": "investigador",
                               "desarrollador": "desarrollador",
                               END: END})
builder.add_edge("investigador", "planificar")
builder.add_edge("desarrollador", "planificar")

grafo = builder.compile()

3.2 Patrón Swarm (descentralizado)

Cada agente decide autónomamente a quién entrega el turno mediante una herramienta handoff.

from langgraph.prebuilt import create_react_agent
from langgraph.swarm import create_swarm

soporte = create_react_agent(
    model=llm,
    name="soporte",
    tools=[consultar_pedido, cancelar_pedido, entregar_a_facturacion, entregar_a_tecnico],
    prompt="Atiende al cliente. Si es un tema de facturación, usa entregar_a_facturacion."
)

facturacion = create_react_agent(
    model=llm,
    name="facturacion",
    tools=[emitir_factura, procesar_reembolso, entregar_a_soporte],
    prompt="Resuelve temas de facturación y vuelve a soporte."
)

tecnico = create_react_agent(
    model=llm,
    name="tecnico",
    tools=[diagnosticarico, reiniciar_servicio, entregar_a_soporte],
    prompt="Resuelve incidencias técnicas y vuelve a soporte."
)

swarm = create_swarm(
    agents=[soporte, facturacion, tecnico],
    default_active_agent="soporte",
    model=llm
)

respuesta = swarm.invoke({"messages": [{"role": "user", "content": "No puedo acceder a mi panel de facturación"}]})

3.3 Sub-agente como herramienta

Para flujos lineales (recolección → redacción → publicación) puedes tratar a cada sub-agente como una herrameinta de alto nivel:

def herramienta_investigador(args: dict) -> str:
    sub = create_react_agent(
        model=llm,
        tools=[scraping, buscar_scholar],
        prompt="Investiga y resume los hallazgos en 200 palabras."
    )
    return sub.invoke({"messages": [("user", str(args))]})["messages"][-1]["content"]

# El Supervisor invoca `herramienta_investigador` igual que cualquier otra tool.

  1. Gestión de estado y aislamiento

LangGraph permite tres estrategias:

  1. Estado global: todos los agentes leen y escriben en el mismo diccionario.
  2. Estado privado: cada agente usa un sub-grafo con su propio TypedDict.
  3. Híbrida: comparte solo los campos imprescindibles (ej. resumen) y mantiene internos los scratchpads.
class EstadoGlobal(TypedDict):
    tarea: str
    resultados: list[str]

class EstadoPrivado(TypedDict):
    notas_internas: str
    archivos_temp: list[str]

# Sub-grafo investigador
investigador_builder = StateGraph(EstadoPrivado)
# ... lógica interna ...
investigador_subgraph = investigador_builder.compile()

# Grafo principal
main_builder = StateGraph(EstadoGlobal)
main_builder.add_node("investigador", investigador_subgraph)

  1. Buenas prácticas y errores comunes

  • No fragmentes tareas triviales: si un solo agente resuelve el flujo en menos de 10 pasos, mantenlo simple.
  • Supervisor ligero: que solo enrute; si empieza a razonar sobre el dominio, conviértelo en otro agente.
  • Límites de recursión: establece recursion_limit para evitar loops infinitos en Swarm.
  • Esquemas estructurados: usa JSON Schema para que los agentes interpreten correctamente los mensajes.
  • Prueba en caliente: ejecuta primero un agente único, identifica el cuello de botella y después decide la partición.
  1. Cuándo elegir cada patrón

Escenario Patrón recomendado
Pipeline claramente secuencial (análisis → diseño → código → tests) Supervisor
Chatbot con intenciones impredecibles Swarm
Requiere aprobación humana intermedia Supervisor con nodo HITL
Agentes negocian entre sí (subastas, acuerdos) Swarm o red peer-to-peer

En resumen, la clave está en asignar la herramienta correcta al agente correcto y delegar la tarea correcta al momento correcto. La complejidad extra se paga con ganancias en seguridad, paralelismo y claridad de responsabilidades.

Etiquetas: LangGraph LangChain Multi-Agent Supervisor Pattern Swarm Pattern

Publicado el 10-5 10:40