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).
- 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).
- 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 |
- 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.
- Gestión de estado y aislamiento
LangGraph permite tres estrategias:
- Estado global: todos los agentes leen y escriben en el mismo diccionario.
- Estado privado: cada agente usa un sub-grafo con su propio
TypedDict. - 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)
- 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_limitpara 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.
- 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.