Inicio / Artículos

IA agente con LangChain — Parte 7: Creación de multiagentes

Parte 7 de la IA agente con LangChain: sistemas multiagente en LangGraph, cómo los agentes dividen el trabajo, transfieren el estado y son coordinados por un nodo supervisor.

Editor: REACTAPP.TOP13 min de lectura3075 palabras

Fuentes: Agentic AI with LangChain — Part 7: Building Multi-Agent Systems with LangGraph

Esta guía reconstruye el proceso desde las materias primas hasta un sistema funcional para: IA agente con LangChain — Parte 7: Creación de sistemas multiagente con LangGraph. El enfoque está en pasos operativos, verificaciones explícitas y código que se puede incorporar directamente a un repositorio sin tener que adivinar la intención. En la etapa de visión general, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto el camino óptimo como el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.

Por qué son importantes los multiagente

Al trabajar en la etapa de “Por qué son importantes los multiagentes”, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de un fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.

Conceptos técnicos utilizados en este artículo

Al trabajar en los Conceptos Técnicos Utilizados en esta etapa, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas. Haga una verificación después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.

Resumen del proyecto: Un agente asistente financiero

Al trabajar en la etapa de Visión General del Proyecto: Aspectos Financieros, anote primero el contrato: los datos de entrada necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza transparencia en los cambios posteriores del código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando se pasa de la versión de demostración a entornos compartidos. Haga una verificación después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior. Al trabajar en la etapa de Visión General del Proyecto: Aspectos Financieros, anote primero el contrato: los datos de entrada necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza transparencia en los cambios posteriores del código. Documente tanto el camino óptimo como el camino de recuperación. Las intentonas repetidas, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras adicionales realizadas posteriormente.

1. Configuración del sistema

La etapa de Configuración del Sistema 1 funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando falla un paso, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado. Mantenga el estado del grafo simple y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.

OPENAI_API_KEY="<Your OpenAI API Key>"
LANGSMITH_TRACING=true
LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
LANGSMITH_API_KEY="<Your LangSmith API Key"
LANGSMITH_PROJECT="agent-ai"
class BaseConfig(BaseSettings):
    OPENAI_API_KEY: Optional[str]

model_config = SettingsConfigDict(env_file=".env", extra="ignore")

2. Estructura del Proyecto

La etapa 2 de Estructura del Proyecto funciona mejor cuando se trata como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Trate esta etapa como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace completaciones parciales silenciosas. Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación posterior.

project/
├── tools/
│   ├── __init__.py
│   ├── financial_search.py # fetch stock prices for companies
│   ├── python_REPL.py      # async wrapper of PythonREPL()
|   └── wikipedia_search.py # fetch financial summary of companies
│
├── graphs/            # implement subagents and multi-agents
│   ├── agent.py       # implement research and analyst in a single agent
│   ├── sub_agents.py  # implement research and analyst sub agents
│   ├── multi_agent_supervisor.py # implement supervisor multi-agents
│   └── multi_agent_swarm.py # implement swamp multi-agents
│
├── config.py           # pydantic BaseConfig
│── utils.py            # utility for printing and executing agents
├── .env                # environment variable definition
├── .gitignore
└── requirements.txt     # package requirements

3. Herramientas del Agente Asistente Financiero

Los 3 Herramientas de la etapa funcionan mejor cuando se tratan como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la demostración a entornos compartidos. Exponga las herramientas con esquemas limitados y etiquetas explícitas de efectos secundarios. Los administradores necesitan saber qué llamadas modifican el estado antes de aprobarlas automáticamente. Los 3 Herramientas de la etapa funcionan mejor cuando se tratan como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.

3.1. Herramienta de búsqueda de datos almacenados

Para la etapa de datos 3 1 Stock Data, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el error debe indicar una única responsabilidad y no un proceso complicado. Autentique en la pasarela de entrada y vuelva a autorizarlo en el plano de datos. Un token portador por sí solo no constituye un límite entre tenencias.

# define LangChain tool to retrieve stock data
@tool
async def stock_data_tool(
        company_ticker: Annotated[str, "The ticker symbol of the company to retrieve their stock performance data."],
        num_days: Annotated[int, "The number of business days of stock data required to respond to the user query."]
) -> str:

        # fetch stock data asynchronously from yfinance
        # check full code for _fetch_stock_sync function
        df = await asyncio.to_thread(_fetch_stock_sync, company_ticker, f"{num_days}d")

        return (f"Successfully executed the stock performance data retrieval tool to retrieve "
                f"the last *{num_days} days* of data for company **{company_ticker}**:\n\n{df.to_markdown()}")

3.2. Herramienta de ejecución de código en Python

En la fase de código Python 3.2, defina las entradas, el responsable de cada paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Considere esta fase como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace las completaciones parciales silenciosas. Separe la construcción del cliente del bucle de mensajes para que sea posible cambiar los proveedores sin tener que reescribir la máquina de estados de la conversación.

@tool
async def python_repl_tool(
        code: Annotated[str, "The python code to execute to generate your chart."],
) -> str:

    # wrap LLM generated code and execute it by python.REPL()
    # repl = PythonREPL().
    clean_code = textwrap.dedent(code).strip()
    result = await asyncio.to_thread(repl.run, clean_code)

    return (
        f"Successfully executed the Python REPL tool.\n\n"
        f"Python code executed:\n```python\n{code}\n```\n\n"
        f"Code output:\n```\n{result}```"
    )

3.3. Herramienta de búsqueda de Wikipedia

Para la etapa de búsqueda en Wikipedia 3x3, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Registre los tiempos de ejecución y el costo de tokens o consultas junto con los resultados funcionales. La visibilidad temprana del costo evita facturas inesperadas cuando el proceso pasa de entornos de demostración a entornos compartidos. Autentíquese en la pasarela y vuelva a autorizarse en el plano de datos. Un token portador por sí solo no constituye un límite entre tenencias. Para la etapa de búsqueda en Wikipedia 3x3, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras realizadas posteriormente.

@tool()
async def wikipedia_tool(
        query: Annotated[str, "The Wikipedia search to execute to find key summary information."],
) -> str:
    """Use this to search Wikipedia for factual information asynchronously."""
    headers = {"User-Agent": "MyLangChainAgent/1.0 (contact@example.com)"}

    async with httpx.AsyncClient(headers=headers, follow_redirects=True) as client:

        # Step 1: Search Wikipedia for matching pages
        search_url = "https://en.wikipedia.org/w/api.php"
        search_params = {
            "action": "query",
            "list": "search",
            "srsearch": query,
            "format": "json"
        }
        response = await client.get(search_url, params=search_params)
        search_data = response.json()
        results = search_data.get("query", {}).get("search", [])
        title = results[0]["title"]

        # Step 2: Fetch the page extract/summary
        summary_url = f"https://en.wikipedia.org/api/rest_v1/page/summary/{title}"
        summary_res = await client.get(summary_url)
        summary_data = summary_res.json()
        summary = summary_data.get("extract", "No summary available.")

        return f"Successfully executed:\nWikipedia summary: {summary}"

4. Swarm Multi-Agents

Al trabajar en la etapa 4 de Swarm Multi-Agents, primero escribe el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación ayuda a mantener honestas las futuras modificaciones del código. Prefiere unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el fallo debe referirse a una sola responsabilidad y no a un proceso complicado. Haz una verificación después de los pasos costosos. La función de reanudación no debe volver a realizar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.

4.1. Arquitectura de Swarm Multi-Agents

Al trabajar en la Arquitectura de etapas 4.1, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.

4.2. Implementación de múltiples agentes en swarms

Al trabajar en la etapa 4 2 Swarm Multi-agents, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando se pasa de entornos de demostración a entornos compartidos. Haga un punto de control después de los pasos costosos. La reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior. Al trabajar en la etapa 4 2 Swarm Multi-agents, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente tanto el camino óptimo como el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.

llm = ChatOpenAI(api_key=api_key, model="gpt-4o-mini")

# Create a handoff tool for researcher -> analyst
transfer_to_analyst = create_handoff_tool(
    agent_name="analyst",
    description="Transfer user to the analyst assistant, who can create visualizations of provided data.",
)

# create research agent as a subagent
research_agent = create_agent(
    llm,
    tools=[wikipedia_tool, stock_data_tool, transfer_to_analyst],
    system_prompt="You provide summaries from Wikipedia, and can query load raw, numerical stock performance data.",
    name="researcher"
)

# define the checkpointer
checkpointer = InMemorySaver()

# create swarm agents
swarm_agent = create_swarm(
    agents=[research_agent, analyst_agent],
    default_active_agent="researcher"
).compile(checkpointer=checkpointer)

5. Supervisor Multi-Agents

La etapa de 5 Supervisores Multi-Agentes funciona mejor cuando se trata como una superficie medible. Capture un registro exitoso, un caso de fallo y la nota de reversión antes de ampliar el alcance. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando falla un paso, el fallo debe apuntar a una sola responsabilidad y no a un proceso complicado. Mantenga el estado del grafo simple y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.

5.1. Arquitectura de Supervisor Multi-Agents

La arquitectura 5 1 de las fases funciona mejor cuando se trata como una superficie medible. Capture un registro exitoso, un caso de fallo y la nota de reversión antes de ampliar el alcance. Considere esta fase como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace completaciones parciales silenciosas. Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación después de las interrupciones.

5.2. Implementación de supervisores multiagentes

La etapa de Supervisor Multi-agents 5 2 funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos. Mantenga el estado del grafo plano y tipado; los bloques anidados ocultan qué nodo escribió qué campo y causan interrupciones en la continuación del proceso. La etapa de Supervisor Multi-agents 5 2 funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el camino de recuperación juntos. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.

llm = ChatOpenAI(api_key=api_key, model="gpt-4o-mini")

# create a checkpointer
checkpointer = InMemorySaver()

# create research subagent
research_agent = create_agent(
    llm,
    tools=[wikipedia_tool, stock_data_tool],
    system_prompt="You provide summaries from Wikipedia, and can query load raw, numerical stock performance data.",
    name="researcher"
)

# Create the supervisor multi-agent graph and compile it
supervisor = create_supervisor(
    model=llm,
    agents=[research_agent, analyst_agent],
    prompt=(
        "You are a supervisor managing two agents:\n"
        "- a research agent. Assign research and data collection tasks to this agent\n"
        "- an analyst agent. Assign the creation of visualizations via code to this agent\n"
        "Assign work to one agent at a time, do not call agents in parallel.\n"
        "Do not do any work yourself."
    ),
    add_handoff_back_messages=True,
    output_mode="last_message"
).compile(checkpointer=checkpointer)

6. Resumen final

En la fase de Resumen final 6, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el error debe indicar una única responsabilidad y no un proceso complicado. Incluya la aprobación humana en aquellas tareas que implican gastos o modificaciones en datos de producción. La conexión en tiempo de compilación no equivale a la completitud del proceso empresarial.

Lista de verificación operativa

La fase de Lista de verificación operativa funciona mejor cuando se trata como una superficie medible. Capture una transcripción de referencia, un caso de fallo y la nota de reversión antes de ampliar el alcance.

Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un único lugar que los operadores puedan auditar sin tener que leer todo el grafo.

Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y dificultan la reanudación después de interrupciones.

Agregue una prueba de funcionamiento básica que ejerza la ruta crítica en los procesos CI utilizando fixtures, y no APIs pagadas en tiempo real, siempre que lo permitan los presupuestos.

Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son algo que se añada posteriormente.

Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y dificultan la reanudación después de interrupciones.