langgraph-supervisor

repository·main·Indexed 23 days ago

https://github.com/langchain-ai/langgraph-supervisor-py

A Python library for building hierarchical multi-agent systems using LangGraph. It implements a supervisor multi-agent architecture where a central agent orchestrates specialized worker agents via tool-based handoffs. The library provides utilities like create_supervisor for workflow orchestration, create_handoff_tool for agent delegation, and support for both Graph and Functional APIs to define agents.

Tokens
5.7K
Snippets
10
Records
22
Agent score
82%

What's inside langgraph-supervisor

  1. Create multi-level hierarchical agent systems

    main

    Build complex hierarchies by nesting supervisors. A supervisor can manage other supervisors as if they were specialized agents. Ensure you call .compile(name="...") on the sub-supervisors so they can be correctly identified by the top-level supervisor.

    research_team = create_supervisor(
        [research_agent, math_agent],
        model=model,
        supervisor_name="research_supervisor"
    ).compile(name="research_team")
    
    writing_team = create_supervisor(
        [writing_agent, publishing_agent],
        model=model,
        supervisor_name="writing_supervisor"
    ).compile(name="writing_team")
    
    top_level_supervisor = create_supervisor(
        [research_team, writing_team],
        model=model,
        supervisor_name="top_level_supervisor"
    ).compile(name="top_level_supervisor")
  2. Quickstart: Create a supervisor with specialized agents

    main

    Use create_supervisor to orchestrate multiple agents (created via create_react_agent) under a single central supervisor. The supervisor decides which agent to invoke based on the provided prompt.

    1. Define tools and specialized agents using create_react_agent.
    2. Initialize the supervisor workflow with create_supervisor.
    3. Compile the workflow with .compile().
    4. Invoke the app with a message list.
    from langchain_openai import ChatOpenAI
    from langgraph_supervisor import create_supervisor
    from langgraph.prebuilt import create_react_agent
    
    model = ChatOpenAI(model="gpt-4o")
    
    # Define tools
    def add(a: float, b: float) -> float: ...
    def multiply(a: float, b: float) -> float: ...
    def web_search(query: str) -> str: ...
    
    # Create specialized agents
    math_agent = create_react_agent(
        model=model,
        tools=[add, multiply],
        name="math_expert",
        prompt="You are a math expert. Always use one tool at a time."
    )
    
    research_agent = create_react_agent(
        model=model,
        tools=[web_search],
        name="research_expert",
        prompt="You are a world class researcher with access to web search. Do not do any math."
    )
    
    # Create supervisor workflow
    workflow = create_supervisor(
        [research_agent, math_agent],
        model=model,
        prompt="""
        You are a team supervisor managing a research expert and a math expert. 
        For current events, use research_agent. 
        For math problems, use math_agent.
        ""
    )
    
    # Compile and run
    app = workflow.compile()
    result = app.invoke({
        "messages": [
            {"role": "user", "content": "what's the combined headcount of the FAANG companies in 2024?"}
        ]
    })
  3. Use the Functional API to create agents

    main

    You can define specialized agents using the LangGraph Functional API by combining @task and @entrypoint decorators.

    1. Use @task to define discrete, reusable units of work (e.g., an LLM call).
    2. Use @entrypoint() to define the agent's main execution logic. This function receives the current state and returns the updated state.
    3. Assign a .name attribute to the entrypoint function so the supervisor can identify and route to it.

    This approach is useful for creating lightweight, function-based agentic workflows that integrate seamlessly with the supervisor.

    from langgraph.prebuilt import create_react_agent
    from langgraph_supervisor import create_supervisor
    from langchain_openai import ChatOpenAI
    from langgraph.func import entrypoint, task
    from langgraph.graph import add_messages
    
    model = ChatOpenAI(model="gpt-4o")
    
    # Functional API - Agent 1 (Joke Generator)
    @task
    def generate_joke(messages):
        """First LLM call to generate initial joke"""
        system_message = {
            "role": "system", 
            "content": "Write a short joke"
        }
        msg = model.invoke(
            [system_message] + messages
        )
        return msg
    
    @entrypoint()
    def joke_agent(state):
        joke = generate_joke(state['messages']).result()
        messages = add_messages(state["messages"], [joke])
        return {"messages": messages}
    
    joke_agent.name = "joke_agent"
  4. Add short-term and long-term memory to supervisors

    main

    Since create_supervisor() returns a StateGraph, you can add persistence by passing a checkpointer (for short-term memory/thread persistence) or a store (for long-term memory/cross-thread persistence) to the .compile() method.

    from langgraph.checkpoint.memory import InMemorySaver
    from langgraph.store.memory import InMemoryStore
    
    checkpointer = InMemorySaver()
    store = InMemoryStore()
    
    workflow = create_supervisor(
        [research_agent, math_agent],
        model=model,
        prompt="You are a team supervisor...",
    )
    
    # Compile with checkpointer/store
    app = workflow.compile(
        checkpointer=checkpointer,
        store=store
    )
  5. How agent handoffs work in the supervisor workflow

    main

    The supervisor manages agent transitions through specialized handoff tools.

    Handoff Mechanism

    1. Tool Generation: create_supervisor automatically generates handoff tools for every agent in the agents list.
    2. Naming: If handoff_tool_prefix is provided (e.g., 'transfer_to_'), tools are named {prefix}{agent_name}. Otherwise, they are named transfer_to_{agent_name}.
    3. Handoff Messages:
      • add_handoff_messages: When True, a pair of (AIMessage, ToolMessage) is added to the history when a handoff occurs.
      • add_handoff_back_messages: When True, a pair of (AIMessage, ToolMessage) is added when an agent returns control to the supervisor, indicating a handoff has completed.
  6. Manage message history in supervisor workflows

    main

    Control how messages from worker agents are integrated into the overall conversation history using the output_mode parameter in create_supervisor.

    • output_mode="full_history": Includes the full message history from an agent in the conversation.
    • output_mode="last_message": Includes only the final response from the agent.
    # Include full history
    workflow = create_supervisor(
        agents=[agent1, agent2],
        output_mode="full_history"
    )
    
    # Include only the final agent response
    workflow = create_supervisor(
        agents=[agent1, agent2],
        output_mode="last_message"
    )
  7. Customize handoff tools

    main

    The supervisor uses handoff tools to delegate tasks. You can customize these using create_handoff_tool or by providing a custom tools list to create_supervisor.

    Customizing default handoff tools

    Use create_handoff_tool to change the tool name, description, or the target agent.

    from langgraph_supervisor import create_handoff_tool
    
    workflow = create_supervisor(
        [research_agent, math_agent],
        tools=[
            create_handoff_tool(agent_name="math_expert", name="assign_to_math_expert", description="Assign task to math expert"),
            create_handoff_tool(agent_name="research_expert", name="assign_to_research_expert", description="Assign task to research expert")
        ],
        model=model,
    )

    Configuration options for handoff tools

    • add_handoff_messages: (bool) Whether to add handoff tool invocation messages to the state. Defaults to True. Set to False for a more concise history.
    • handoff_tool_prefix: (str) A prefix for automatically generated tools. For example, handoff_tool_prefix="delegate_to" creates tools like delegate_to_research_expert.
    # Example: Customizing tool names and disabling handoff messages
    workflow = create_supervisor(
        [research_agent, math_agent],
        model=model,
        add_handoff_messages=False,
        handoff_tool_prefix="delegate_to"
    )
  8. Create a supervisor workflow with `create_supervisor`

    main

    The create_supervisor function allows you to orchestrate multiple agents (created via either the Graph API or Functional API) under a single supervisor LLM.

    To use it:

    1. Pass a list of agent objects (e.g., agents created via create_react_agent or @entrypoint functions) as the first argument.
    2. Provide a model (an LLM instance) that will act as the supervisor.
    3. Provide a prompt that explicitly instructs the supervisor on how to use each agent (e.g., "For X, use agent_name").

    Once created, call .compile() on the workflow to get a runnable application.

    from langgraph_supervisor import create_supervisor
    
    # Assuming research_agent and joke_agent are already defined
    workflow = create_supervisor(
        [research_agent, joke_agent],
        model=model,
        prompt=(
            "You are a team supervisor managing a research expert and a joke expert. "
            "For current events, use research_agent. "
            "For any jokes, use joke_agent."
        )
    )
    
    app = workflow.compile()
    result = app.invoke({
        "messages": [
            {
                "role": "user",
                "content": "Share a joke to relax and start vibe coding for my next project idea."
            }
        ]
    })
  9. Create custom handoff tools

    main

    For advanced control, you can implement a custom tool that returns a langgraph.types.Command. This allows you to:

    • Inject custom arguments (like a task_description) for the next agent.
    • Control the goto destination.
    • Update the state (e.g., setting active_agent or adding custom metadata).

    Note: When using Command(graph=Command.PARENT, ...), the state update is applied to the parent (supervisor) graph.

    from typing import Annotated
    from langchain_core.tools import tool, BaseTool, InjectedToolCallId
    from langchain_core.messages import ToolMessage
    from langgraph.types import Command
    from langgraph.prebuilt import InjectedState
    from langgraph_supervisor.handoff import METADATA_KEY_HANDOFF_DESTINATION
    
    def create_custom_handoff_tool(*, agent_name: str, name: str | None, description: str | None) -> BaseTool:
        @tool(name, description=description)
        def handoff_to_agent(
            task_description: Annotated[str, "Detailed description of what the next agent should do."],
            state: Annotated[dict, InjectedState],
            tool_call_id: Annotated[str, InjectedToolCallId],
        ):
            tool_message = ToolMessage(
                content=f"Successfully transferred to {agent_name}",
                name=name,
                tool_call_id=tool_call_id,
            )
            messages = state["messages"]
            return Command(
                goto=agent_name,
                graph=Command.PARENT,
                update={
                    "messages": messages + [tool_message],
                    "active_agent": agent_name,
                    "task_description": task_description,
                },
            )
    
        handoff_to_agent.metadata = {METADATA_KEY_HANDOFF_DESTINATION: agent_name}
        return handoff_to_agent
  10. Control parallel tool calling in the supervisor

    main

    The parallel_tool_calls argument in create_supervisor allows you to control whether the supervisor LLM can call multiple tools (or hand off to multiple agents) simultaneously.

    • Set parallel_tool_calls=True to enable parallel execution.
    • Set parallel_tool_calls=False to force sequential tool calls.

    Note: This is currently only supported by OpenAI and Anthropic models. For other providers, you must use explicit instructions in the system prompt to control parallel behavior.

  11. Forward worker messages directly to output

    main

    Use create_forward_message_tool to allow the supervisor to bypass its own processing and send a worker agent's last message directly to the final output. This saves tokens and prevents paraphrasing errors.

    Pass the name of the supervisor (e.g., `