Суть
Главный тезис: агенты — это графы, а не цепочки. Линейная цепочка вход → LLM → tool → выход не умеет ветвиться, циклиться, прерываться и восстанавливаться — а агенту это нужно. LangGraph даёт три примитива, из которых собирается любая логика:
- State — единое строго типизированное состояние, передаваемое между узлами (LangGraph State, правила обновления — LangGraph Reducers).
- Node (узел) — Python-функция, принимающая
stateи возвращающая его частичное обновление. - Edge (ребро) — переход между узлами, обычный или условный (функция-маршрутизатор) (LangGraph Nodes and Edges).
Граф собирается через StateGraph(...) builder и переводится в исполняемый объект вызовом .compile().
Зачем это нужно
LangChain-цепочки — это API для прототипирования; для production нужны контроль потока, циклы, retry, воспроизводимость и human-in-the-loop. LangGraph закрывает именно это (подробно — LangGraph vs LangChain). Показательно: высокоуровневая create_agent() из LangChain сама написана на LangGraph.
Карта концепций (atomic)
Ядро State Machine:
- LangGraph State — типизированное неизменяемое состояние, схема данных графа
- LangGraph Reducers — как обновления состояния мержатся (
Annotated[type, reducer],add_messages) - LangGraph Nodes and Edges — узлы, обычные/условные рёбра, builder,
compile
Production-механизмы:
- LangGraph Checkpointers — персистентность состояния, восстановление по
thread_id - LangGraph HITL — прерывания и аппрувы (human-in-the-loop)
- LangGraph Time Travel — replay/fork по истории чекпоинтов
- LangGraph Reliability — идемпотентность, циклы+лимиты,
RetryPolicy - LangGraph Observability — LangGraph Studio, LangFuse/LangSmith
Практические паттерны:
- LangGraph ReAct Loop — минимальный цикл
agent ↔ ToolNode - LangGraph Intent Router — двухуровневая маршрутизация intent → инструмент
- LangGraph MCP as Node — MCP-сервер как узел графа + fallback RAG→MCP
Учебная последовательность
State → Reducers → Nodes/Edges → (собрать минимальный LangGraph ReAct Loop) → Checkpointers → HITL → Time-Travel → Reliability → практические паттерны (Intent Router, MCP-as-Node).
Когда граф, а когда что-то другое
Против PydanticAI и голого цикла — критерий разобран в Agent Architecture: граф покупают, когда поток перестал быть линейным и вы уже начали писать ветвления, лимиты циклов и персистентность руками. PydanticAI решает соседнюю задачу (типобезопасность на границе с моделью) и ставится рядом, а не вместо.
Против MCP/A2A-кооперации развилка проходит по границе процесса и организации. Граф — это оркестрация внутри одного приложения: общее состояние, общий рантайм, полная трассировка. Как только участники — отдельные системы с собственным жизненным циклом, а тем более чужие команды, общее состояние становится невозможным, и нужен протокол с явными контрактами: MCP для подключения инструментов, Agent2Agent Protocol для общения агентов между платформами.
Формулировка, по которой удобно решать: если можно передать объект состояния — это граф; если приходится передавать сообщение с контрактом — это протокол. Гибрид нормален: узел графа вызывает удалённого агента по A2A, оставаясь для остальной системы обычным шагом (LangGraph MCP as Node — тот же приём для MCP).
Связано с
Mastra — те же механизмы в TypeScript под другими именами; таблица соответствия там
Agent vs Workflow — «граф vs цепочка» = «агент vs workflow»
ReAct — ReAct-цикл реализуется как граф;
create_agent()написан на LangGraphAgent Architecture — LangGraph как способ собрать агентный цикл
PydanticAI — другой фреймворк для агентов (типизация вывода vs оркестрация графа)
Orchestrator Adapter — как не растащить вызовы фреймворка по всему приложению
Альтернативный взгляд: граф как actor model
Основная линия заметки объясняет LangGraph со стороны разработчика: цепочки не умеют ветвиться и восстанавливаться, граф умеет. Это взгляд «чем удобнее». Другой заход — со стороны вычислительной модели: LangGraph силён не потому, что удобнее, а потому что стоит на Pregel Model, системе Google для распределённой обработки графов, и на модели акторов из объектных языков.
Что меняется от смены рамки:
- Узел — не «функция в пайплайне», а актор. Своё изолированное состояние, общение только сообщениями, никакой общей изменяемой памяти. Разработчику с фоном C# или Java эта модель знакома напрямую — она не изобретена для LLM, а заимствована.
- Параллелизм становится первичным, а не побочным. Дело не в том, что граф «умеет ветвиться», а в том, что внутри супершага узлы физически не видят промежуточных результатов друг друга. Гонка за общее поле исключена конструктивно, а не дисциплиной разработчика.
- Компиляция — это верификация.
.compile()не просто собирает исполняемый объект: он строит граф зависимостей, ловит недостижимые узлы и проверяет рёбра до запуска. Скомпилированный граф неизменяем, поэтому потокобезопасен и держит тысячи независимых сессий. - Восстановление — следствие модели, а не фича. Состояние согласовано на границе супершага, значит эта граница и есть естественная точка сохранения.
Отсюда же следует граница применимости, которой нет в «продуктовом» взгляде: LangGraph окупается там, где логика выразима явно — аудит, кредитный скоринг, комплаенс. На задачах, где важна не траектория, а реплика (диалоговый ассистент «поговорить»), граф вырождается в бесконечность сценариев, и проект тонет в ветках.