Гайд · LangGraph 2026

Как собрать ИИ-агента на LangGraph:state, tools, MCP и human-in-the-loop

State, tools, MCP и human-in-the-loop — схема, которая держит контент-пайплайн под контролем

Подписаться на Maya Pro Approve перед publish · MCP как руки

Если вы один раз спросили нейросеть «напиши пост» и получили нормальный текст — кажется, что создание ИИ-агента уже решено. На практике длинный контент-пайплайн ломается именно там, где чат «забывает» контекст: бриф уехал, фактчек не сработал, а черновик улетел в Telegram без вашей подписи.

Коротко: ИИ-агент — это не «умный чат», а система, которая проходит шаги, вызывает инструменты и хранит состояние задачи. Один промпт хорош для разовой генерации. Граф нужен, когда есть ветки, циклы и опасные действия.

Зачем агенту граф, а не один промпт

Типичная боль владельца контента выглядит так:

  1. Агент нашёл источники и начал писать.
  2. В середине процесса контекст раздулся — качество упало.
  3. «Публикация» сработала раньше, чем вы успели проверить факты.
  4. После сбоя сервера черновик пропал, и всё пришлось начинать заново.

Именно поэтому в гайде мы собираем агента на LangGraph: не как демо в ноутбуке, а как управляемый конвейер research → draft → QA → approve → публикация.

Маркер: простыми словами. ИИ-агент — программа, которая сама решает, какой шаг сделать дальше: вызвать поиск, написать черновик, проверить текст или остановиться и спросить человека.

Конвейер, а не чат

Research → draft → QA → approve → publish. Ветки, циклы и пауза перед необратимым действием — то, чего нет у одного промпта.

5
узлов в базовом графе
HITL
шлюз перед publish

Итог выбора

Один промпт — разовая генерация. Граф — когда есть память задачи, tool-вызовы и риск «опубликовать раньше времени».

LangGraph и LangChain — кто за что отвечает

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

По открытой документации LangChain Inc., LangGraph позиционируют как low-level orchestration runtime: durable execution, streaming, human-in-the-loop и persistence. Компании вроде Klarna, Uber и J.P. Morgan используют его там, где нужен контроль, а не «магический чатбот из коробки».

Маркер: простыми словами. LangChain — набор кирпичиков (модель, tool, промпт). LangGraph — схема, по которой эти кирпичики ходят по маршруту с остановками и памятью.

Когда хватает цепочки LangChain

Хватает цепочки, если сценарий почти линейный:

  • один запрос → один ответ;
  • максимум один-два tool-вызова;
  • нет долгой паузы «подожди одобрения человека»;
  • нет ветвлений «если QA провален — верни на правку».

Пример: «перепиши заголовок под Wordstat» или «сделай 5 вариантов CTA». Здесь сложный граф только замедлит работу.

Когда нужен граф со state и ветками

Граф нужен, когда у задачи есть «память» и развилки:

  • research может вернуть агента к поиску;
  • draft ↔ QA крутятся, пока оценка не ок;
  • перед WordPress/Telegram обязателен ручной approve;
  • после сбоя надо продолжить с того же thread_id, а не с нуля.

Итог выбора: no-code (n8n, Albato, Salebot) силён в интеграциях и быстрых сценариях без Python. LangGraph оправдан, когда нужны циклы самоисправления, явный state и предохранитель перед необратимым действием. Гибрид тоже рабочий: LangGraph думает и тормозит, Make/n8n доставляет по расписанию — но этот материал именно про code-first сборку.

Визуализация · не hero

StateGraph с шлюзом HITL перед публикацией

На схеме — не «чат в одном окне», а управляемый граф: state течёт по узлам, tools/MCP дают руки, а перед publish граф останавливается на interrupt — пока человек не даст approve.

  • State + checkpoint: черновик и правки не пропадают между шагами.
  • Tools / MCP: поиск, фактчек, черновик WP/Telegram — как внешние «руки».
  • HITL-шлюз: без approve пакет не уходит в publish — только в draft-контур.

Дальше разберём state и checkpoint: какие поля помнить между шагами контента и как не потерять черновик после сбоя.

Редакционная метафора цикла LangGraph: бриф → draft → фактчек → HITL → publish. Не скриншот Studio.

State агента: что помнить между шагами контента

Без state агент каждый раз «просыпается заново». С state он знает: какой бриф, какой черновик, какой статус публикации, какие каналы выбраны.

Маркер: простыми словами. State — это общая «тетрадка» агента: список полей, которые узлы читают и дописывают. Не чат-история ради истории, а структура задачи.

Базовый паттерн в LangGraph Python: StateGraph + готовый MessagesState (ключ messages с reducer add_messages). Для контента MessagesState обычно наследуют и добавляют свои поля.

Какие поля state нужны черновику, правкам и публикации

Минимальный набор под контент-завод:

ПолеЗачем
briefисходный бриф: тема, тон, канал
messagesдиалог модели и tool-ответы
draft_html / draft_mdактуальный черновик
qa_score / qa_notesрезультат фактчека
channelsWordPress, Telegram и т.д.
approvedчеловек сказал «можно» или нет

Так state держит не «всё подряд», а только то, без чего следующий узел слеп.

Checkpoint: как не потерять черновик после сбоя

Маркер: простыми словами. Checkpointer — «сейв» игры: снимок state на границах шагов. Без него human-in-the-loop и восстановление после рестарта не работают.

Два слоя persistence в docs:

  • Checkpointer — краткосрочная память внутри thread (HITL, откат, устойчивость к сбоям);
  • Store — долгосрочная память между thread (предпочтения, факты о бренде).

Практика выбора:

  1. Разработка: InMemorySaver (старое имя MemorySaver — alias). Живёт в RAM и не переживает рестарт процесса.
  2. Локальный диск: SqliteSaver / AsyncSqliteSaver.
  3. Прод: PostgresSaver / AsyncPostgresSaver (пакет langgraph-checkpoint-postgres), перед боем — saver.setup(). У Postgres thread_id не длиннее 255 символов.

Важно: checkpoint пишется на границе super-step, не «посередине функции». После interrupt узел перезапускается с начала — поэтому publish-логика должна стоять после паузы или быть идемпотентной (повторный вызов не дублирует пост).

Tools: какие действия агенту можно доверить

Tools — это «руки» агента: поиск, чтение базы, запись черновика, выкладка. В кастомном графе обычно используют ToolNode(tools) и условие tools_condition из langgraph.prebuilt: цикл «модель вызвала tool → tool вернул результат → модель снова думает».

Маркер: простыми словами. Tool calling — модель не «магически публикует», а выбирает функцию из списка: например search_web, write_draft, publish_draft. Вы решаете, какие функции вообще существуют.

Поиск, генерация, проверка фактов, выкладка

Разделите tools по риску:

УровеньПримерыПравило
Безопасныепоиск, Wordstat, чтение docsможно свободно
Средниегенерация черновика, правкилимит длины и формата
Опасныепубликация в WP/TG, отправка клиентутолько после HITL

Для контент-пайплайна хорошая схема:

  • research_* — собрать факты и ссылки;
  • draft_* — собрать текст в шаблон;
  • qa_* — проверить факты/тон/запрещённые обещания;
  • publish_* — писать только draft или публиковать после approve.

Где tool calling ломает качество текста

  1. Слишком много tools «на всё» — модель путается и уходит в лишние вызовы.
  2. Publish-tool доступен с первого шага — агент «оптимизирует» и публикует сырой текст.
  3. В tool возвращают простыню без структуры — state раздувается, RAG и фактчек деградируют.
  4. Ошибки tool глотаются молча — агент уверенно врёт дальше.

Практический совет: лучше 4–7 ясных tools с понятными описаниями, чем зоопарк из двадцати «универсальных».

MCP: подключаем внешние сервисы без зоопарка интеграций

Когда tools разрастаются, появляется боль: отдельный клиент под WordPress, отдельный под Telegram, отдельный под файлы. MCP снимает часть этого хаоса.

MCP простыми словами: протокол, а не «ещё один плагин»

Маркер: простыми словами. MCP (Model Context Protocol) — единый способ подключить внешние сервисы к агенту. MCP-сервер отдаёт список инструментов; агент вызывает их одинаково, без новой самописной обвязки под каждый API.

Запросы вроде «что такое mcp» и «mcp сервер» сейчас высокочастотные не случайно: людям нужен понятный слой «рук» для ИИ, а не ещё один проприетарный connector.

Схема: LangGraph → tools → MCP-сервер

Официальный мост: пакет langchain-mcp-adapters (MultiServerMCPClient, load_mcp_tools). Типичный поток:

  1. Поднять MCP-клиент (один или несколько серверов).
  2. Получить tools: tools = await client.get_tools().
  3. Привязать к модели: model.bind_tools(tools).
  4. Положить в граф через ToolNode(tools) и tools_condition.

Транспорты: stdio, http / streamable HTTP, sse. Для web-сервера осторожнее со stdio (он скорее для desktop): на проде предпочтительнее HTTP MCP или обычный @tool. Ошибки выполнения MCP-tool по умолчанию часто приходят как ToolMessage со статусом ошибки — агент может самоисправиться; сбои транспорта обычно падают исключением.

Реалии РФ: сам LangGraph и Python-пакеты ставятся через pip/uv. Оплата зарубежных LLM API и доступ к отдельным облакам из России бывают нестабильны — заранее заложите рабочий путь: доступный провайдер моделей, прокси/корпоративный биллинг или локальная/RU-совместимая модель. MCP-серверы под WordPress, Telegram и Wordstat как раз помогают держать «руки» ближе к вашему стеку, даже если модель меняется.

Полезный первоисточник по runtime: документация LangGraph. Для моста MCP смотрите репозиторий langchain-mcp-adapters.

Human-in-the-loop: где человек должен остановить агента

Автономия без тормозов в контенте заканчивается одинаково: пост ушёл клиенту или в канал с ошибкой в цифре. Human-in-the-loop (HITL) — принцип «человек в контуре»: агент работает сам, но на критичных точках ждёт вас.

Маркер: простыми словами. HITL — красная кнопка «стоп» внутри графа. Агент дошёл до опасного места, сохранил state и ждёт approve/правки.

В LangGraph это делается через interrupt(payload) внутри узла или tool. State сохраняется checkpointer’ом. Продолжение — Command(resume=value) с тем же thread_id. Альтернатива проще, но грубее: статические breakpoints interrupt_before=["publish"] / interrupt_after=["draft"] при compile().

Точки approve перед публикацией и перед дорогими вызовами

Ставьте паузу минимум в двух местах:

  1. Перед публикацией в WordPress/Telegram — обязательный гейт.
  2. Перед дорогими вызовами — массовый краулинг, длинный RAG по большой базе, пакетная генерация десятков статей.

Практический паттерн для мессенджеров: thread_id = chat_id Telegram + Postgres checkpointer. Тогда workflow можно «заморозить на дни» и продолжить по кнопке «одобрить».

Правило идемпотентности: логика «реально опубликовать» должна идти после interrupt(), иначе при resume пост уйдёт дважды.

Что делать, если HITL превратили в ручной ад

HITL ломается, когда человек подтверждает каждый чих. Тогда агент не экономит время, а создаёт очередь микрокнопок.

Как не скатиться в ад:

  • approve только на необратимых действиях;
  • в payload interrupt кладите короткий diff: заголовок, 3 риска, каналы;
  • правки текста — отдельным полем resume, а не «перепиши всё с нуля в чате»;
  • безопасные шаги (поиск, черновик v1) пусть идут без вас.

Тот же смысл сейчас виден и вне LangGraph: хуки вроде «не коммить без тестов» — это тот же предохранитель перед необратимым действием.

Сборка под контент-пайплайн: от брифа до поста

Ниже — рабочий how-to, который новичок может повторить. Цель не «красивый ноутбук», а черновик под WordPress/Telegram с паузой перед выкладкой.

Узлы: бриф → draft → фактчек → правка → публикация

1

Установка

Ставим runtime и MCP-адаптеры.

pip install -U langgraph langchain-mcp-adapters

При необходимости добавьте пакет checkpointer под SQLite/Postgres.

2

Опишите state

Наследуйте MessagesState, добавьте brief, draft_html, qa_score, channels, approved.

3

Соберите StateGraph

Узлы: researchdraftqaapprovepublish → END. Между qa и draft поставьте условное ребро: если qa_score низкий — назад на правку.

4

Подключите tools / MCP

Безопасные tools — freely. Publish-tool либо спрячьте за interrupt, либо сделайте режим draft_only.

5

Compile с checkpointer

graph = builder.compile(checkpointer=saver)
config = {"configurable": {"thread_id": "content-42"}}

Без thread_id пауза HITL не привяжется к задаче.

6

Interrupt перед publish

В узле approve вызовите interrupt({...}) с кратким summary. После вашего «да» — Command(resume=...) и только затем publish.

7

Запуск

Для отладки удобен stream_events (в актуальных docs — с флагами interrupted). Для простого сценария хватит invoke с проверкой __interrupt__ в результате.

Признак успеха: агент дошёл до approve, state сохранился, после resume появился один черновик/пост в выбранном канале, повторный resume не создал дубль.

Типичные ошибки новичка:

  1. Нет checkpointer → после паузы/рестарта граф «амнезирует». Решение: Sqlite/Postgres + один thread_id.
  2. Publish до interrupt() → при resume двойная публикация. Решение: publish строго после approve.
  3. Раздутый контекст в messages → модель тупеет. Решение: в state держать сжатый draft, сырые tool-логи обрезать.

RAG: когда агенту нужна база знаний, а не только промпт

RAG-агент нужен, когда факты живут у вас: брендбук, кейсы, запреты, прайс, старые лонгриды. Без RAG модель будет «додумывать». С RAG узел research сначала достаёт фрагменты базы, потом пишет.

Не тащите RAG «на всякий случай». Если задача — переписать один абзац под тон бренда, хватит короткого system prompt и 2–3 эталонов. Если задача — серия статей без фактических галлюцинаций, RAG обязателен.

Мультиагентность: один граф или команда ролей

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

Роли редактора, исследователя и публикатора

Практичная раскладка под контент:

  • Исследователь — только facts и источники;
  • Автор — только текст по брифу и фактам;
  • Редактор/QA — критика, фактчек, тон;
  • Публикатор — выкладка после HITL.

Это могут быть отдельные субагенты или просто разные узлы одного StateGraph. Для старта почти всегда выгоднее один граф и разные узлы: меньше гонок, проще отладка, один checkpointer.

Где субагенты дают скорость, а где — хаос

Субагенты полезны, когда задачи реально параллельны: один копает источники, другой готовит структуру, третий собирает визуальный бриф. Хаос начинается, когда у каждого своя «правда» без общего state, нет единого approve и нет лимита на tool-вызовы.

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

Один граф

Разные узлы, один state, один HITL. Быстрый старт и прозрачная отладка.

Субагенты позже

Параллельный research и структура — только после стабильного approve-gate.

Отладка в LangGraph Studio и типичные поломки

LangGraph Studio помогает увидеть граф глазами, а не гадать по логам. Смотрите: какой узел активен, что лежит в state, где оборвался tool/MCP, на каком interrupt зависли.

Смотрим граф, state и сбои tool/MCP

Чек-лист отладки:

  1. Откройте путь выполнения: не зациклился ли draft ↔ qa.
  2. Проверьте размер messages — нет ли простыни из сырых HTML.
  3. На MCP-ошибках смотрите: это ошибка tool (агент может исправиться) или transport (сервер лежит).
  4. На HITL убедитесь, что resume идёт с тем же thread_id.
  5. Для регрессий поведения подключайте трассировку/eval (в экосистеме — LangSmith): один и тот же бриф не должен сегодня публиковать бред, а вчера — нормальный текст.

Чеклист перед боем: что проверить за 15 минут

  • Есть checkpointer не только в RAM, если нужен рестарт.
  • У каждой задачи уникальный thread_id.
  • Publish недоступен до approve.
  • Publish идемпотентен.
  • MCP на проде не через хрупкий stdio без необходимости.
  • В state нет лишних мегабайт логов.
  • Есть ручной сценарий «отклонить и вернуть на draft».
  • Каналы по умолчанию = draft-only.

Что проверяли по источникам

  1. Позиционирование LangGraph как orchestration runtime — docs overview.
  2. Persistence: checkpointer vs store, InMemory/Sqlite/Postgres — docs persistence.
  3. Interrupt / Command(resume) — docs interrupts.
  4. MCP adapters и паттерн ToolNode — GitHub langchain-mcp-adapters.
  5. Свежий RU-контекст по HITL/StateGraph и экономике DIY-агента — обзоры на Хабре и рыночные оценки (порядка десятков тысяч ₽ и дней при самостоятельной сборке; подрядчик — существенно дороже; точные сметы зависят от ТЗ).

Частые вопросы

Короткие ответы для поиска и AI-выдачи

Чем LangGraph отличается от «просто агента в ChatGPT»

В ChatGPT вы ведёте диалог. В LangGraph вы описываете маршрут: узлы, условия, память, паузы и tools. Это разница между «попросить написать пост» и «собрать конвейер, который нельзя случайно опубликовать без вас».

Нужен ли Python, чтобы собрать агента на LangGraph

Для этого гайда — да, базовый Python. Установка через pip/uv, код графа читается как схема шагов. Если Python сейчас стоп-фактор, начните с no-code автоматизаций для простой доставки, а LangGraph берите, когда нужны циклы, state и HITL. В экосистеме есть и no-code builder (LangSmith Fleet), но кастомный publish-gate и поля state под контент-завод обычно проще контролировать в коде.

Если Python пока стоп-фактор, а нужна рабочая автоматизация «бриф → черновик → выкладка», начните с системного маршрута: обучение по автоматизации и вайбкодингу на kv-ai.ru — логичное продолжение темы агентов, Make и контент-завода из этого гайда.

Можно ли совместить MCP и human-in-the-loop в одном графе

Да. MCP даёт tools, HITL — тормоз перед опасным tool. Типовая связка: MCP-инструменты в ToolNode, а interrupt() — в узле approve или внутри publish-tool до необратимого вызова.

С чего начать, если цель — контент, а не демо в ноутбуке

  1. Один канал (лучше Telegram draft или WP draft).
  2. Четыре узла: research → draft → approve → publish.
  3. Sqlite checkpointer.
  4. Один HITL перед publish.
  5. Только после стабильности добавляйте MCP, RAG и второго субагента.

Так вы получаете не «ещё одного чат-бота», а управляемый кусок контент-завода: агент ускоряет рутину, человек держит качество и бренд.

Beget — надёжный хостинг и VPS