Главная / Статьи

Deep Agents в LangChain: планирование, подагенты и банковский шлюз

Как deepagents используют планирование, файловую систему и подагентов в цикле инструментов, в чем их отличие от ReAct, и как распределять инструменты между агентами разных доменов через шлюз.

Издатель: REACTAPP.TOP9 мин чтения2002 слов

Источники: Beyond Simple Agents: Engineering DeepAgents for Enterprise with LangChain

Многие команды могут нанять агента, работающего с ноутбука. Гораздо меньше из них способны поддерживать его в рабочем состоянии в реальных условиях, и именно в этом разрыве находит применение концепция глубоких агентов. Это не просто модное словосочетание — это реакция на конкретное ограничение: обычный цикл вызова инструментов теряет эффективность, когда задача становится длинной, многоэтапной или запутанной.

Ограничения простого цикла

Самый базовый агент — это LLM, работающий в цикле и вызывающий различные инструменты. Такой агент обычно имеет ограниченную глубину, поэтому не может планировать долгосрочные действия или выполнять сложные, многоэтапные задачи. Он хорошо справляется с одним вопросом, но терпит неудачу при решении более крупных задач.

Продукты вроде Deep Research, Manus и Claude Code смогли преодолеть эту проблему благодаря четырем компонентам: инструменту планирования, субагентам, файловой системе и подробному запросу. Проект deepagents возник в результате попытки понять, что делает Claude Code настолько универсальным, и развить эти возможности дальше. В LangChain такие агенты называются «deep agents», поскольку они способны планировать сложные задачи и выполнять их в течение длительного времени. По сути, это путь LangChain к автономным агентам в стиле Claude Code, которые могут справляться с реальными многоэтапными задачами, а не только с однократными вопросами.

deepagents — это автономная библиотека, созданная на основе ключевых компонентов агентов LangChain и работающая в среде выполнения LangGraph, которая обеспечивает надежное выполнение задач, потоковую обработку данных и возможность участия человека в процессе. Хорошим описанием может служить метафора «узда для агента»: тот же цикл вызова инструментов, что и в других фреймворках, но дополненный дополнительными встроенными инструментами и функциями.

Четыре составляющих

Планирование. Встроенный инструмент write_todos позволяет агенту разбивать крупные задачи на отдельные шаги, отслеживать прогресс и корректировать план по мере поступления новой информации.

Система файлов для хранения контекста. Инструменты вроде ls, read_file, write_file и edit_file позволяют агенту сохранять объемный контекст в оперативной памяти или на диске, чтобы окно контекста не переполнялось и можно было обрабатывать результаты любого размера. Старые сообщения автоматически сводятся к краткому изложению, когда диалог становится слишком длинным.

Подагенты. Встроенный инструмент для выполнения задач создает специализированных подагентов с изолированным контекстом. Основной агент остается свободным от лишних данных, в то время как помощник занимается конкретной подзадачей более детально.

Длинные системные промпты. Промпты, сгенерированные из Claude Code, бывают длинными и содержат подробные инструкции по использованию инструментов, а также примеры действий в определенных ситуациях. Без них эти агенты были бы гораздо менее функциональными. Промпты по-прежнему играют важную роль.

Место в стеке LangChain

Существует три уровня, каждый из которых строится на предыдущем. LangGraph — это среда выполнения агентов, подходящая для объединения рабочих процессов и агентов. LangChain — это фреймворк для агентов, позволяющий использовать основной цикл, создавать промпты и инструменты с нуля. Deep Agents — это платформа для автономных агентов, работающих в течение длительного времени, которые получают преимущества от встроенного планирования, файловой системы и других дополнений. Эта платформа построена на абстракции агентов LangChain, которая в свою очередь основана на LangGraph.

Пример из банковской сферы

Представьте банк, предоставляющий пять инструментов для работы с конкретной областью: поиск банкоматов по почтовому индексу, список сотрудников, занимающихся инвестициями, в определенном городе, получение информации о компаниях из инвестиционного портфеля банка, подробности о планах выхода на пенсию и поиск филиалов в разных регионах. Каждый из этих инструментов хорошо справляется с одной узкой задачей. Проблемы начинаются, когда пользователь просит выполнить несколько таких задач одновременно:

Можете ли вы перечислить точки расположения банкоматов банка XYZ, а также компании, входящие в его инвестиционный портфель, и указать местоположение сотрудников, ответственных за инвестиции, в Чикаго?

Чтобы ответить на этот вопрос, необходимо распознать несколько целей в одном запросе, выбрать и скоординировать подходящие инструменты, сохранить контекст между разными источниками данных и объединить результаты в один связный ответ. Архитектуры, разработанные для одноэтапных или линейных процессов, часто терпят неудачу в таких ситуациях. Именно для решения подобных задач и создаются сложные агенты.

Последовательность действий выглядит следующим образом.

  1. Планирование. Основной оркестратор анализирует сложный вопрос и с помощью функции write_todos разделяет его на три задачи: получение информации о точках расположения банкоматов, список компаний портфеля и данные о сотрудниках в Чикаго.
  • Создание элементов. Вместо того чтобы обрабатывать все три задачи последовательно в одном объемном контексте, система запускает три подагента — по одному на каждую задачу; у каждого свое окно контекста, что предотвращает взаимное вмешательство.
  • Вызов инструментов. Каждый подагент использует именно тот инструмент из пяти, который необходим: get_atm_centers(zipcode=...), get_trusted_portfolio_companies() и get_investment_officers(city="Chicago").
  • Синтез результатов. Полученные данные возвращаются оркестратору, который объединяет их в один хорошо структурированный ответ и отмечает выполненные задачи.
  • Простой агент для вызова инструментов обрабатывал бы все три задачи по очереди в рамках одного контекста. Он мог бы забыть ранние результаты, потерять нить того, на какой вопрос отвечает, или достичь лимита объема контекста. Глубокий агент сохраняет отдельность каждой задачи и отслеживает прогресс по списку дел, так что даже если один вызов провалится или вернет неполные данные, координатор будет знать текущее положение дел.

    Структура связей проста:

    from deepagents import create_deep_agent
    
    agent = create_deep_agent(
        tools=[
            get_atm_centers,         # your ATM tool
            get_investment_officers, # your officers tool
            get_portfolio_companies, # your portfolio tool
            get_retirement_plans,    # your retirement tool
            get_bank_locations,      # your locations tool
        ],
        system_prompt="You are XYZ Bank's AI assistant. Always answer completely and cite sources."
    )
    
    result = agent.invoke({"messages": [{"role": "user", "content": "Can you give me a list of ATM centers for XYZ bank and also list the name of companies XYZ has in its investment portfolio? Also can you give me the location of XYZ investment agents in Chicago?"}]})
    

    Агент решает, какие инструменты вызвать, в каком порядке и как объединить полученные результаты. Вам не нужно самостоятельно писать логику маршрутизации, и именно в этом заключается настоящая ценность данного инструмента.

    Реакция системы ReAct на действия глубоких агентов при отсутствии инструмента

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

    Глубокий агент проверяет свой реестр инструментов и формирует список задач перед тем, как приступить к действиям, поэтому с самого начала видит, что нет инструментов для работы с кредитными картами. Он запускает подагентов для трех задач, которые выполняются параллельно и завершаются нормально, отмечает пункт, касающийся кредитных карт, как «инструмент не доступен», и возвращает один синтезированный ответ. Этот ответ полностью охватывает все три вопроса и ясно сообщает пользователю, что инструмент для работы с кредитными картами не настроен и его возможно потребуется добавить. Ничего не ломается, и о частичном успехе сообщается четко.

    ReAct, сокращение от Reasoning plus Acting, следует строгому циклу «Мышление — Действие — Наблюдение», шаг за шагом, без предварительного плана. Это приводит к трём проблемам:

    • Он работает последовательно: сначала банкоматы, затем портфель, затем сотрудники. Проблема с кредитными картами проявляется только в конце, после того как выполнены все остальные действия.
  • Он никогда не сканирует доступные инструменты. Он находит отсутствующий инструмент во время выполнения, когда пытается его вызвать, и в зависимости от LLM и реализации может остановиться, попробовать снова с выдуманным именем инструмента или, что хуже всего, сгенерировать правдоподобный список кредитных карт, поскольку ожидает наличия ответа.
  • Поскольку сбой происходит внутри цикла, ничто не гарантирует, что три предыдущих результата дойдут до пользователя в целостном виде. Агент может просто выдать ошибку и ничего не вернуть.
  • ReAct подходит для коротких, четко определенных задач, где известно наличие каждого инструмента. Deep agents предназначены для более сложного реального мира, где вопросы являются сложными, инструменты могут отсутствовать, но при этом необходимо получить максимально возможную пользу из того, что имеется.

    Вопрос дизайна: один агент с всеми инструментами?

    Значит ли это, что нам следует создавать множество инструментов и предоставлять их все через одного агента? Нет. Один агент, содержащий 50 и более инструментов, является антипаттерном. Лучшей структурой является иерархия агентов. Представьте себе агента, конфигурация которого включает сотни инструментов — от поиска в интернете и работы с электронной почтой до бронирования рейсов и запуска ракет, — с указанием «решить проблему самостоятельно». Иногда это может сработать, и время от времени он может ответить на жалобу о задержке доставки, забронировав рейс, заполнив налоговую декларацию и заказав пиццу. Никто этого не хочет.

    Владение доменами

    Основное правило заключается в том, что каждый доменный агент владеет небольшой, целостной группой инструментов — в идеале от трех до пяти — из одной бизнес-области. Агент-шлюз никогда не взаимодействует с инструментами. Он лишь анализирует намерение, направляет запрос к соответствующему доменному агенту и объединяет полученные ответы. Это та же сепарация ответственностей, что используется в микросервисах.

    В случае банковского сектора естественное разделение выглядит следующим образом:

    • Агент филиала и банкомата с методами get_atm_centers и get_bank_locations, отвечающий за физическое присутствие: почтовые индексы, города, часы работы.
    • Агент по инвестициям с методами get_portfolio, get_officers и get_retirement_plans, отвечающий за управление деньгами, включая финансовые регулирования, сертификацию сотрудников и типы планов.
    • Агент по продуктам с методом get_credit_cards (если таковой существует), а также по кредитам и сберегательным счетам, отвечающий за каталог продуктов. Если какой-либо инструмент отсутствует, только этот агент сообщает об этом пробеле, а остальные продолжают работу без изменений.

    Код отражает такую же структуру:

    from deepagents import create_deep_agent
    # Each domain agent is self-contained
    branch_agent = create_deep_agent(
        tools=[get_atm_centers, get_bank_locations],
        system_prompt="You are the Branch & ATM specialist for XYZ Bank..."
    )
    investments_agent = create_deep_agent(
        tools=[get_portfolio, get_officers, get_retirement_plans],
        system_prompt="You are the Investments specialist for XYZ Bank..."
    )
    products_agent = create_deep_agent(
        tools=[get_credit_cards],  # sparse now, grows over time
        system_prompt="You are the Products specialist for XYZ Bank..."
    )
    # Gateway knows nothing about tools — only about agents
    gateway = create_deep_agent(
        tools=[
            branch_agent.as_tool(name="branch_atm_agent"),
            investments_agent.as_tool(name="investments_agent"),
            products_agent.as_tool(name="products_agent"),
        ],
        system_prompt="""You are the XYZ Bank assistant gateway.
        Parse the user's intent, delegate to the right domain agent(s),
        and synthesize a unified response. Never answer directly — always route."""
    )
    

    Почему это масштабируется

    По мере добавления новых функций банком шлюз и другие агенты доменов остаются неизменными. Вы можете добавить инструмент к соответствующему агенту домена или создать новый, например для кредитов или борьбы с мошенничеством, и зарегистрировать его в шлюзе. Любые изменения ограничиваются одним доменом.

    Представьте себе «лес» инструментов. Агент, имеющий 30 таких инструментов, не понимает контекста домена и может вызвать функцию get_retirement_plans при ответе на вопрос о рабочем времени банкомата лишь потому, что оба вопроса находятся в пределах его функционала. Агенты доменов избегают этого, присваивая каждому из них четкую идентичность через системные указания и набор инструментов. Агент, знающий свою роль, принимает более точные решения в рамках своей области ответственности.

    Полезный тест: если вы спорите о том, принадлежит ли инструмент агенту A или агенту B, значит либо этот инструмент выполняет слишком много функций и его следует разделить, либо вам нужна третья область. Граница должна казаться столь же очевидной, как понимание того, куда направить вопрос — руководителю отделения или инвестиционному советнику.

    Открытые вопросы

    Остаются два вопроса: зависят ли сложные агенты в большой степени от выбора основной модели и можно ли с их помощью создать полное решение «от начала до конца». На второй вопрос ответ — да, и следующим логичным шагом является практическая реализация этого банковского сценария.