LangChain Мультиагентные системы

Когда задача слишком сложна для обработки одним агентом, можно создать нескольких агентов с разными обязанностями и позволить им взаимодействовать как команда.


Зачем нужен мультиагентный подход

Проблемы с одним агентом:

  • Слишком длинный system_prompt может привести к рассеиванию внимания модели
  • Слишком много инструментов увеличивают вероятность того, что модель выберет неверный инструмент
  • Разные типы задач требуют разных компетенций и стилей поведения

Мультиагентный подход: каждый агент сосредоточен на одной предметной области, а сложные задачи выполняются благодаря совместной работе.


Метод 1: субагент как инструмент

Скомпилируйте агента в CompiledStateGraph, затем зарегистрируйте его как инструмент у родительского агента:

Пример

from dotenv import load_dotenv
load_dotenv()

from langchain.tools import tool
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.messages import HumanMessage

model = init_chat_model("deepseek:deepseek-v4-flash", temperature=0)

# Субагент 1: Эксперт по погоде
@tool
def get_weather(city: str) -> str:
    """Запросить погоду"""
    data = {"Ханчжоу": "Солнечно, 25°C", "Пекин": "Облачно, 18°C"}
    return data.get(city, f"{city}: данные временно недоступны")

weather_agent = create_agent(
    model=model,
    tools=[get_weather],
    name="weather_expert",  # Имя используется для идентификации и логирования
    system_prompt="Вы эксперт по погоде, специализирующийся на ответах на вопросы о погоде. Отвечайте кратко.",
)

# Субагент 2: Эксперт по вычислениям
@tool
def calculate(expression: str) -> str:
    """Вычислить математические выражения"""
    result = eval(expression, {"__builtins__": {}}, {})
    return f"{expression} = {result}"

math_agent = create_agent(
    model=model,
    tools=[calculate],
    name="math_expert",
    system_prompt="Вы эксперт по математике, специализируетесь на математических вычислениях. Отвечайте кратко.",
)

# Родительский агент: Координатор
# Зарегистрируйте субагентов как инструменты
@tool
def ask_weather_expert(question: str) -> str:
    """Обратитесь к эксперту по погоде по вопросам, связанным с погодой.

    Аргументы:
question: Вопросы о погоде
    """

    result = weather_agent.invoke(
        {"messages": [HumanMessage(content=question)]}
    )
    return result["messages"][-1].content


@tool
def ask_math_expert(question: str) -> str:
    """Проконсультируйтесь с экспертом по математике по вопросам математических вычислений.

    Аргументы:
вопрос: Задачи на математические вычисления
    """

    result = math_agent.invoke(
        {"messages": [HumanMessage(content=question)]}
    )
    return result["messages"][-1].content


coordinator = create_agent(
    model=model,
    tools=[ask_weather_expert, ask_math_expert],
    system_prompt="""Вы — ассистент-координатор. Выберите подходящего эксперта в зависимости от вопроса пользователя:
- Вопросы о погоде → используйте ask_weather_expert
- Задачи на математические вычисления → используйте ask_math_expert
- Если одновременно задействовано несколько предметных областей, консультируйтесь с каждым экспертом по очереди"""
,
)

# Тестовый составной вопрос
result = coordinator.invoke({
    "messages": [HumanMessage(
        content="Какая сегодня погода в Ханчжоу? Если температура 25 градусов, сколько это по Фаренгейту?"
        "(Формула: Fahrenheit = Celsius × 9/5 + 32)"
    )]
})
print(result["messages"][-1].content)

Результат выполнения:

根据天气专家的查询,杭州今天晴天,气温25°C.
换算成华氏度:25 × 9/5 + 32 = 77°F.
所以杭州今天25°C,相当于77°F,天气晴好。

Метод 2: Различение агентов с помощью параметра name

При встраивании субагента в качестве инструмента установка параметра name помогает отслеживать источник сообщений:

Пример

# Роль параметра name:
# 1. Имя используется в скомпилированном графе
# 2. Имя используется при встраивании в качестве узла подграфа в родительский граф
# 3. Все сообщения AI помечаются этим именем

agent = create_agent(
    model=model,
    tools=[...],
    name="customer_service",  # Назовите агента
)

Метод 3: Маршрутизация агентов с помощью промежуточного ПО

Более сложные мультиагентные сценарии могут реализовать динамическую маршрутизацию через промежуточное ПО:

Пример

from langchain.agents.middleware import before_model


# Определите наборы инструментов, используемые разными экспертами
general_tools = [tool_a, tool_b]
admin_tools = [tool_c, tool_d]


@before_model
def route_by_user_role(state, runtime):
    """Динамически переключать доступные инструменты в зависимости от роли пользователя"""
    context = runtime.context
    if context is None:
        return None

    user_role = context.get("user_role", "user")

    # Разные роли видят разные инструменты
    if user_role == "admin":
        available_tools = general_tools + admin_tools
    else:
        available_tools = general_tools

    # Примечание: before_model не может напрямую изменять инструменты,
    # Это нужно реализовать вместе с wrap_model_call или request.override
    return None

Паттерны архитектуры мультиагентных систем

ПаттернСтруктураПрименимый сценарий
Паттерн координатораОдин родительский Agent → несколько инструментов субагентовЗадачи, которые явно классифицируются по типу
Паттерн эстафетыВыход Agent A → вход Agent BОбработка в стиле конвейера (генерация → проверка → шлифовка)
Паттерн дебатовНесколько Agent выдают результаты параллельно → обобщить и принять решенияЗадачи, требующие многостороннего анализа

Мультиагентная система увеличивает сложность и расход Token. Не используйте multi-agent только ради «multi-agent» — сначала попробуйте решить задачу с помощью одного Agent + хорошо спроектированного system_prompt и Middleware. Вводите multi-agent только тогда, когда вам действительно нужна изоляция доменов или независимый контекст.

Другие расширения