Содержание
- LangGraph: Что это такое
- Как LangGraph устроен и работает
- Ключевые компоненты и архитектура
- Принципы функционирования
- Возможности и функции
- Основной функционал
- Сценарии применения и бизнес-задачи
- Практическое использование LangGraph
- Пример 1: Простой агент с инструментом (ReAct-подобный цикл)
- Пример 2: Команда из двух агентов (супервизор и исполнитель)
- Плюсы и подводные камни
- Преимущества и выгоды
- Ограничения и сложности внедрения
- Альтернативы и конкуренты
- Тренды и будущее LangGraph
- Выводы: ключевые моменты
- Дополнительные материалы
Отлично, задача ясна. Сажусь за статью. Я буквально живу этой темой последние месяцы, перелопатил кучу документации и исходников, так что постараюсь объяснить всё так, будто мы сидим за чашкой кофе, а не на скучной лекции. Поехали!
***
LangGraph: Что это такое
Представь, что ты строишь умного ассистента с помощью больших языковых моделей (LLM). Сначала всё просто: получил вопрос, отправил в модель, отдал ответ. Для таких линейных задач отлично подходит LangChain Expression Language (LCEL). Это как конвейер на заводе: деталь движется только вперёд по одной линии.
Но что, если твой ассистент должен принимать решения? Например, если он не уверен в ответе, он должен сначала поискать информацию в интернете. А если нашёл, то проанализировать её. А если пользователь просит что-то уточнить, вернуться на шаг назад. Простой конвейер тут же сломается. Нужна целая схема завода с развилками, петлями и контрольными пунктами.
Вот для этого и создали LangGraph. Если говорить просто, LangGraph — это библиотека для создания сложных, циклических и управляемых LLM-приложений, где логика работы представлена в виде графа. Она расширяет возможности LCEL, позволяя строить не просто цепочки, а целые карты принятия решений для ваших ИИ-агентов.
Основная проблема, которую решает LangGraph, — это ограниченность линейных потоков. Он даёт разработчику полный контроль над логикой работы агента, позволяя ему зацикливаться, возвращаться, выбирать разные пути и даже запрашивать вмешательство человека. Это переход от простых «вопрос-ответ» систем к по-настоящему автономным и разумным агентам.
Как LangGraph устроен и работает
В основе LangGraph лежит простая, но мощная идея: любое сложное взаимодействие можно представить как граф состояний. Ваше приложение перемещается из одного состояния в другое, выполняя на каждом шаге определённые действия. Это похоже на компьютерную игру, где ваш персонаж (состояние) перемещается по локациям (узлам), а его путь зависит от выполненных квестов (условий).
Ключевые компоненты и архитектура
Архитектура LangGraph строится на трёх китах. Поняв их, ты поймёшь 90% всей магии:
- State (Состояние): Это сердце вашего графа. Представь его как рюкзак, который агент носит с собой, переходя от узла к узлу. В этом «рюкзаке» хранится вся важная информация: история сообщений, результаты поиска, промежуточные выводы. Обычно это простой словарь или Pydantic-модель. Каждый узел может что-то прочитать из рюкзака или положить в него что-то новое.
- Nodes (Узлы): Это «рабочие лошадки» графа. Каждый узел — это функция или любой другой вызываемый объект, который выполняет конкретное действие. Например, один узел может вызывать LLM, другой — выполнять поиск в интернете с помощью инструмента, третий — форматировать данные. Узел принимает текущее состояние (рюкзак) и возвращает обновление для него.
- Edges (Рёбра): Это «дорожные знаки» и «стрелки», которые соединяют узлы. Рёбра определяют, в какой узел пойдёт агент после завершения текущего. Они бывают двух видов:
- Обычные рёбра: Просто соединяют узел А с узлом Б. После А всегда идёт Б.
- Условные рёбра (Conditional Edges): Это самая мощная часть. Такое ребро смотрит на результат работы узла (например, агент решил использовать инструмент или нет) и на основе этого решает, куда двигаться дальше. Именно они позволяют создавать циклы, ветвления и сложную логику.
Всё это собирается в объект Graph, который компилируется в исполняемую машину состояний. У графа есть обязательные точки входа (START) и выхода (END), которые определяют начало и конец работы.
Принципы функционирования
Процесс работы графа интуитивно понятен. Представь, что мы строим агента-исследователя.
- Вход: Пользователь даёт задачу: «Найди информацию о влиянии кофе на сон». Эта задача попадает в начальное состояние графа.
- Первый узел: Граф стартует и переходит к первому узлу, например, «Планировщик». Этот узел (LLM) анализирует задачу и решает: «Нужно использовать инструмент поиска». Он добавляет это решение в общее состояние.
- Условное ребро: После «Планировщика» стоит условное ребро. Оно проверяет состояние: «Агент решил использовать инструмент?». Да, решил. Значит, ребро направляет поток к узлу «Исполнитель Инструмента». Если бы агент решил, что информации достаточно, ребро направило бы его сразу к узлу «Генератор Ответа».
- Второй узел: Узел «Исполнитель Инструмента» запускает поиск в интернете, получает результаты и добавляет их в состояние.
- Возврат в цикл: От узла «Исполнитель Инструмента» ребро ведёт обратно к «Планировщику». Теперь «Планировщик» видит новую информацию (результаты поиска) и снова принимает решение. Возможно, теперь он скажет: «Информации достаточно, можно генерировать ответ».
- Выход из цикла: Условное ребро видит новое решение и направляет поток к узлу «Генератор Ответа».
- Финальный узел: Этот узел берёт всю собранную информацию из состояния и генерирует красивый, связный ответ для пользователя. После этого он указывает, что работа завершена.
- Конец: Поток доходит до специального узла END, и работа графа завершается.
Ключевая идея в том, что состояние (наш «рюкзак») передаётся по цепочке, постоянно обогащаясь, а условные рёбра действуют как умные диспетчеры, направляя поток по нужной траектории.
ИИ-агенты для оптимизации бизнес-процессов
Код курса
AGENT
Ближайшая дата курса
2 февраля, 2026
Продолжительность
24 ак.часов
Стоимость обучения
66 000
Возможности и функции
LangGraph — это не просто ещё одна библиотека. Это новый подход к созданию сложных систем на базе LLM, открывающий массу возможностей.
Основной функционал
- Циклическое выполнение: Главное преимущество. Агент может возвращаться к предыдущим шагам, уточнять информацию, исправлять ошибки — до тех пор, пока не достигнет нужного результата. Это основа для создания самокорректирующихся систем.
- Явное управление состоянием: Вы всегда точно знаете, какая информация доступна агенту в каждый момент времени. Это упрощает отладку и делает поведение системы более предсказуемым по сравнению с «чёрным ящиком», где всё решает одна LLM.
- Человек в цикле (Human-in-the-loop): В любой точке графа можно вставить узел, который будет ждать подтверждения от человека. Например, перед выполнением деструктивной операции (удаление файла, отправка письма) агент может спросить: «Вы уверены?».
- Потоковая передача промежуточных шагов: Можно транслировать состояние графа в реальном времени. Это идеально для UI: пользователь видит, чем сейчас занят агент («Ищу информацию…», «Анализирую данные…»), что значительно улучшает пользовательский опыт.
- Параллельное выполнение: LangGraph позволяет запускать несколько узлов одновременно, если они не зависят друг от друга. Например, можно параллельно искать информацию в трёх разных источниках, а затем объединять результаты.
Сценарии применения и бизнес-задачи
Теория — это хорошо, но где это всё применяется на практике? Вот несколько реальных сценариев.
- Продвинутые RAG-системы (Retrieval-Augmented Generation): Классический RAG просто находит документы и отдаёт их модели. С LangGraph можно построить систему, которая сначала генерирует поисковые запросы, ищет документы, оценивает их релевантность, если релевантность низкая — переформулирует запросы и ищет снова (цикл!). И только потом генерирует ответ на основе проверенных данных.
- Мультиагентные команды: Можно создать команду из нескольких агентов с разными ролями. Например, «Супервизор» получает общую задачу, декомпозирует её и раздаёт подзадачи «Агенту-исследователю» и «Агенту-кодеру». LangGraph выступает в роли координатора, передавая информацию между ними и решая, кто следующим вступает в работу.
- Планировщики задач: Агент, который получает сложную цель («организуй мне поездку в Сочи на выходные»), разбивает её на шаги («найти билеты», «забронировать отель», «составить план досуга»), а затем последовательно выполняет каждый шаг, постоянно обновляя общий план в зависимости от результатов.
- Интерактивные чат-боты поддержки: Бот может вести пользователя по сложной процедуре диагностики. Вместо того чтобы пытаться угадать проблему, он задаёт уточняющие вопросы, выполняет проверки и, в зависимости от ответов, движется по разным веткам графа, пока не найдёт решение или не передаст диалог живому оператору.
Практическое использование LangGraph
Давай от слов перейдём к делу. Вот пара простых, но наглядных примеров, которые покажут всю мощь LangGraph.
Пример 1: Простой агент с инструментом (ReAct-подобный цикл)
Создадим базового агента, который может отвечать на вопросы, а если не знает ответа — обращаться к инструменту (в нашем случае, фейковому поисковику). Это классический паттерн ReAct (Reason + Act).
import os
from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
# --- 1. Определяем состояние графа ---
# State - это "рюкзак" нашего агента. В нем будут храниться все сообщения.
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], operator.add]
# --- 2. Определяем узлы (nodes) ---
# Узлы - это функции, выполняющие основную работу.
def call_model(state):
"""Вызывает LLM для принятия решения или генерации ответа."""
messages = state['messages']
# Привязываем инструмент к модели, чтобы она знала о его существовании
response = model_with_tools.invoke(messages)
# Возвращаем обновление для состояния - добавляем ответ модели
return {"messages": [response]}
def call_tool(state):
"""Вызывает инструмент, если модель этого захотела."""
last_message = state['messages'][-1] # Последнее сообщение - это вызов инструмента
# Здесь была бы реальная логика вызова API, поиска и т.д.
# Мы просто вернем "заглушку"
tool_output = "В Москве сегодня солнечно, +25 градусов."
# Возвращаем результат работы инструмента в виде специального сообщения
return {"messages": [HumanMessage(content=tool_output, name="tool")]}
# --- 3. Определяем условное ребро (conditional edge) ---
# Эта функция решает, куда двигаться дальше.
def should_continue(state):
"""Определяет, нужно ли вызывать инструмент или можно завершать работу."""
last_message = state['messages'][-1]
# Если в последнем сообщении есть вызов инструмента...
if "tool_calls" in last_message.additional_kwargs:
# ...то направляем граф к узлу 'action' (вызов инструмента)
return "action"
else:
# ...иначе завершаем работу
return "end"
# --- 4. Собираем граф ---
# Инициализируем модель и инструменты (для примера)
# Убедись, что у тебя есть OpenAI API ключ в переменных окружения
# os.environ["OPENAI_API_KEY"] = "sk-..."
model = ChatOpenAI(model="gpt-4o")
# "Притворяемся", что у нас есть инструмент для получения погоды
tools = [{"type": "function", "function": {"name": "get_weather", "description": "Узнать погоду в городе"}}]
model_with_tools = model.bind_tools(tools)
# Создаем объект графа, указывая тип его состояния
workflow = StateGraph(AgentState)
# Добавляем узлы в граф
workflow.add_node("agent", call_model)
workflow.add_node("action", call_tool)
# Устанавливаем точку входа
workflow.set_entry_point("agent")
# Добавляем условное ребро. После узла 'agent' вызываем 'should_continue'.
# В зависимости от результата ('action' или 'end') переходим к соответствующему узлу.
workflow.add_conditional_edges(
"agent",
should_continue,
{
"action": "action",
"end": END
}
)
# От узла 'action' всегда возвращаемся к 'agent', чтобы он обработал результат
workflow.add_edge('action', 'agent')
# Компилируем граф в исполняемый объект
app = workflow.compile()
# --- 5. Запускаем граф ---
inputs = {"messages": [HumanMessage(content="Какая погода в Москве?")]}
for output in app.stream(inputs):
# stream() позволяет видеть все промежуточные шаги
for key, value in output.items():
print(f"Вывод из узла '{key}':")
print("---")
print(value)
print("\n---\n")
final_state = app.invoke(inputs)
print("Финальный ответ:", final_state['messages'][-1].content)
В результате выполнения этого кода мы увидим, как граф проходит через несколько состояний. Сначала узел agent (модель) решит, что нужно вызвать инструмент get_weather. Затем условное ребро направит его к узлу action, который вернёт фейковые данные о погоде. После этого граф вернётся к узлу agent, который, имея на руках новые данные, сгенерирует финальный ответ: «В Москве сегодня солнечно, +25 градусов.».
Пример 2: Команда из двух агентов (супервизор и исполнитель)
Этот пример сложнее. Мы создадим «супервизора», который будет решать, какому из «исполнителей» отдать задачу. Это основа для построения сложных мультиагентных систем.
from typing import TypedDict, Annotated, List, Union
from langchain_core.agents import AgentAction, AgentFinish
from langchain_core.messages import BaseMessage
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolExecutor
# --- 1. Инструменты и исполнитель ---
@tool
def search_tool(query: str):
"""Ищет информацию в интернете по запросу."""
# Заглушка для реального поиска
return f"Результаты поиска по запросу '{query}': LangGraph - это круто."
# ToolExecutor - удобный класс для выполнения списка инструментов
tool_executor = ToolExecutor([search_tool])
# --- 2. Агенты (реализованы как простые функции-узлы) ---
# Модель для наших агентов
model = ChatOpenAI(model="gpt-4o", temperature=0)
def researcher_agent(state):
"""Агент-исследователь: использует инструменты для поиска информации."""
print("АКТИВЕН АГЕНТ: Исследователь")
messages = state['messages']
# Привязываем инструменты к модели
model_with_tools = model.bind_tools([search_tool])
response = model_with_tools.invoke(messages)
return {"messages": [response]}
def router(state):
"""Супервизор-маршрутизатор: решает, какой агент должен работать следующим."""
print("АКТИВЕН АГЕНТ: Супервизор")
last_message = state['messages'][-1]
# Если последний шаг - вызов инструмента, то передаем управление исполнителю
if "tool_calls" in last_message.additional_kwargs:
return "tool_executor"
# Иначе решаем, достаточно ли информации или нужен еще один поиск
# Это упрощенная логика, в реальности здесь может быть еще один вызов LLM
if "Результаты поиска" in last_message.content:
return "end" # Завершаем, если нашли информацию
else:
return "researcher" # Отправляем на исследование
def call_tool_executor(state):
"""Узел для выполнения инструментов."""
print("АКТИВЕН: Исполнитель инструментов")
last_message = state['messages'][-1]
action = last_message.tool_calls[0]
output = tool_executor.invoke([action])
return {"messages": [HumanMessage(content=str(output), name="tool")]}
# --- 3. Состояние и граф ---
class AgentState(TypedDict):
messages: List[BaseMessage]
# Собираем граф
workflow = StateGraph(AgentState)
workflow.add_node("researcher", researcher_agent)
workflow.add_node("tool_executor", call_tool_executor)
# Условное ребро-супервизор
workflow.set_entry_point("researcher")
workflow.add_conditional_edges(
"researcher",
router,
{"researcher": "researcher", "tool_executor": "tool_executor", "end": END}
)
workflow.add_edge("tool_executor", "researcher")
app = workflow.compile()
# --- 4. Запуск ---
inputs = {"messages": [HumanMessage(content="Расскажи мне про LangGraph.")]}
final_state = app.invoke(inputs)
print("\n--- ФИНАЛЬНЫЙ РЕЗУЛЬТАТ ---")
print(final_state['messages'][-1].content)
В этом сценарии «Супервизор» (функция router) играет роль условного ребра. После каждого шага он анализирует состояние и решает, что делать дальше: снова запустить «Исследователя», вызвать «Исполнителя инструментов» или закончить работу. Это демонстрирует, как LangGraph позволяет оркестрировать работу нескольких логических единиц (агентов) для достижения общей цели.
Плюсы и подводные камни
Как и у любого мощного инструмента, у LangGraph есть свои сильные стороны и моменты, которые стоит учитывать перед внедрением.
Преимущества и выгоды
- Невероятная гибкость: Это главный плюс. Вы больше не ограничены линейной логикой. Циклы, ветвления, динамическое принятие решений — вы можете смоделировать практически любой процесс. Это позволяет создавать агентов, которые могут исправлять свои ошибки, запрашивать дополнительную информацию и адаптироваться к ситуации.
- Прозрачность и управляемость: В отличие от монолитных «агентских» фреймворков, где вся магия происходит внутри, LangGraph даёт вам полный контроль. Вы явно определяете каждый шаг, каждое возможное состояние и каждое правило перехода. Это делает отладку намного проще, а поведение системы — более предсказуемым.
- Отличная интеграция с экосистемой LangChain: LangGraph является частью LangChain и без проблем работает со всеми его компонентами: моделями, инструментами, ретриверами и, что особенно важно, с системой трассировки LangSmith. LangSmith визуализирует выполнение графа, что бесценно при отладке.
- Масштабируемость сложности: Можно начать с простого графа из двух узлов и постепенно усложнять его, добавляя новые ветки логики, новых агентов и инструменты. Архитектура не ломается при росте сложности, а органично её вмещает.
Ограничения и сложности внедрения
- Повышенная сложность входа: LangGraph определённо сложнее, чем LCEL. Вам придётся думать в терминах состояний, узлов и рёбер. Для простой задачи «вопрос-ответ-RAG» он будет избыточен и только усложнит код. Это инструмент для сложных задач.
- Больше шаблонного кода (boilerplate): Определение состояния, функций-узлов, условных рёбер — всё это требует написания большего количества кода по сравнению с одной строкой в LCEL. Нужно быть готовым к тому, что код будет более многословным.
- Отладка логики графа: Хотя сам процесс выполнения прозрачен, отладка *логики* переходов может быть нетривиальной. Если ваш условный роутер работает неправильно, агент может уйти в бесконечный цикл или пойти не по той ветке. Здесь очень помогает визуализация в LangSmith.
В общем, LangGraph — это не замена LCEL, а его логическое продолжение для тех случаев, когда простой линейной цепочки уже недостаточно.
Альтернативы и конкуренты
LangGraph — не единственный инструмент для создания агентов. Важно понимать его место в экосистеме.
Основной «конкурент» — это сам LangChain Expression Language (LCEL). Но это скорее не конкуренция, а разделение ролей. LCEL идеален для построения направленных ациклических графов (DAG), то есть любых линейных или ветвящихся, но не зацикленных цепочек. Если вам нужно просто получить данные, обработать их и отдать LLM — LCEL будет проще, быстрее и лаконичнее. LangGraph нужен тогда, когда в этой цепочке появляется слово «если»: *если* результат плохой, вернись назад; *если* пользователь просит уточнить, спроси ещё раз.
Другой популярный фреймворк — Microsoft Autogen. Он использует иной подход. Вместо явного графа состояний, Autogen фокусируется на «общении» между агентами. Вы определяете нескольких агентов с разными ролями (например, «Писатель», «Критик», «Программист») и запускаете их в общем «чате». Они сами решают, кто и когда должен говорить, чтобы решить задачу. Это более гибкий и «эмерджентный» подход, но он менее контролируемый. В LangGraph вы — дирижёр, который точно знает, какой инструмент когда играет. В Autogen вы — модератор джазовой импровизации.
Ещё одна альтернатива — CrewAI. Он похож на Autogen, но предлагает более структурированный, высокоуровневый подход к определению «команды» агентов и процессов их взаимодействия (например, иерархического или последовательного). CrewAI проще для быстрого старта, так как абстрагирует много деталей. LangGraph же является более низкоуровневым и гибким конструктором. Если CrewAI — это готовый набор для сборки модели самолёта, то LangGraph — это 3D-принтер, на котором вы можете напечатать любые детали для любой модели.
Тренды и будущее LangGraph
LangGraph появился совсем недавно, но уже стал де-факто стандартом для создания сложных агентов в экосистеме LangChain. Его будущее выглядит очень перспективным. Скорее всего, развитие пойдёт в сторону упрощения создания и отладки графов. Можно ожидать появления визуальных редакторов, где можно будет «рисовать» логику агента, а код будет генерироваться автоматически. Также будет углубляться интеграция с LangSmith для ещё более детальной аналитики и отладки поведения агентов. Тренд на мультиагентные системы только набирает обороты, и LangGraph идеально подходит на роль «оркестратора» для таких систем.
Выводы: ключевые моменты
Давай подведём итоги. Что самое важное нужно вынести из этой статьи?
- LangGraph — это библиотека для создания LLM-агентов со сложной, нелинейной логикой (циклами, ветвлениями).
- Он работает на основе концепции графа состояний: Состояние (общая память), Узлы (действия) и Рёбра (правила перехода).
- Главное преимущество — полный контроль и гибкость. Вы можете строить самокорректирующиеся, интерактивные и мультиагентные системы.
- Это не замена LCEL, а инструмент для более сложных задач. Если ваша логика линейна, оставайтесь на LCEL.
- Начинать с LangGraph сложнее, чем с других фреймворков, но он даёт несравнимо больше власти над поведением агента.
Если ты чувствуешь, что твой проект перерос простые цепочки вызовов, и тебе нужен надёжный каркас для построения по-настояшему умного и автономного агента — LangGraph твой лучший выбор.
Дополнительные материалы
- Официальная документация LangGraph на Python — https://langchain-ai.github.io/langgraph/
- Вводное видео от создателей на YouTube — https://www.youtube.com/watch?v=R9_f7v_r6k4
- Репозиторий с примерами на GitHub — https://github.com/langchain-ai/langgraph/tree/main/examples
- Статья-анонс в блоге LangChain — https://blog.langchain.dev/langgraph/
Image by: Tatyana Doloman
https://www.pexels.com/@tatyana-doloman-728740365
