Гайд · LangGraph 2026
Как собрать ИИ-агента на LangGraph:state, tools, MCP и human-in-the-loop
State, tools, MCP и human-in-the-loop — схема, которая держит контент-пайплайн под контролем
Если вы один раз спросили нейросеть «напиши пост» и получили нормальный текст — кажется, что создание ИИ-агента уже решено. На практике длинный контент-пайплайн ломается именно там, где чат «забывает» контекст: бриф уехал, фактчек не сработал, а черновик улетел в Telegram без вашей подписи.
Коротко: ИИ-агент — это не «умный чат», а система, которая проходит шаги, вызывает инструменты и хранит состояние задачи. Один промпт хорош для разовой генерации. Граф нужен, когда есть ветки, циклы и опасные действия.
Зачем агенту граф, а не один промпт
Типичная боль владельца контента выглядит так:
- Агент нашёл источники и начал писать.
- В середине процесса контекст раздулся — качество упало.
- «Публикация» сработала раньше, чем вы успели проверить факты.
- После сбоя сервера черновик пропал, и всё пришлось начинать заново.
Именно поэтому в гайде мы собираем агента на LangGraph: не как демо в ноутбуке, а как управляемый конвейер research → draft → QA → approve → публикация.
Маркер: простыми словами. ИИ-агент — программа, которая сама решает, какой шаг сделать дальше: вызвать поиск, написать черновик, проверить текст или остановиться и спросить человека.
Конвейер, а не чат
Research → draft → QA → approve → 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 сборку.
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 | результат фактчека |
channels | WordPress, Telegram и т.д. |
approved | человек сказал «можно» или нет |
Так state держит не «всё подряд», а только то, без чего следующий узел слеп.
Checkpoint: как не потерять черновик после сбоя
Маркер: простыми словами. Checkpointer — «сейв» игры: снимок state на границах шагов. Без него human-in-the-loop и восстановление после рестарта не работают.
Два слоя persistence в docs:
- Checkpointer — краткосрочная память внутри thread (HITL, откат, устойчивость к сбоям);
- Store — долгосрочная память между thread (предпочтения, факты о бренде).
Практика выбора:
- Разработка:
InMemorySaver(старое имяMemorySaver— alias). Живёт в RAM и не переживает рестарт процесса. - Локальный диск:
SqliteSaver/AsyncSqliteSaver. - Прод:
PostgresSaver/AsyncPostgresSaver(пакетlanggraph-checkpoint-postgres), перед боем —saver.setup(). У Postgresthread_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 ломает качество текста
- Слишком много tools «на всё» — модель путается и уходит в лишние вызовы.
- Publish-tool доступен с первого шага — агент «оптимизирует» и публикует сырой текст.
- В tool возвращают простыню без структуры — state раздувается, RAG и фактчек деградируют.
- Ошибки 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). Типичный поток:
- Поднять MCP-клиент (один или несколько серверов).
- Получить tools:
tools = await client.get_tools(). - Привязать к модели:
model.bind_tools(tools). - Положить в граф через
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 перед публикацией и перед дорогими вызовами
Ставьте паузу минимум в двух местах:
- Перед публикацией в WordPress/Telegram — обязательный гейт.
- Перед дорогими вызовами — массовый краулинг, длинный 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 → фактчек → правка → публикация
Установка
Ставим runtime и MCP-адаптеры.
pip install -U langgraph langchain-mcp-adaptersПри необходимости добавьте пакет checkpointer под SQLite/Postgres.
Опишите state
Наследуйте MessagesState, добавьте brief, draft_html, qa_score, channels, approved.
Соберите StateGraph
Узлы: research → draft → qa → approve → publish → END. Между qa и draft поставьте условное ребро: если qa_score низкий — назад на правку.
Подключите tools / MCP
Безопасные tools — freely. Publish-tool либо спрячьте за interrupt, либо сделайте режим draft_only.
Compile с checkpointer
graph = builder.compile(checkpointer=saver)
config = {"configurable": {"thread_id": "content-42"}}Без thread_id пауза HITL не привяжется к задаче.
Interrupt перед publish
В узле approve вызовите interrupt({...}) с кратким summary. После вашего «да» — Command(resume=...) и только затем publish.
Запуск
Для отладки удобен stream_events (в актуальных docs — с флагами interrupted). Для простого сценария хватит invoke с проверкой __interrupt__ в результате.
Признак успеха: агент дошёл до approve, state сохранился, после resume появился один черновик/пост в выбранном канале, повторный resume не создал дубль.
Типичные ошибки новичка:
- Нет checkpointer → после паузы/рестарта граф «амнезирует». Решение: Sqlite/Postgres + один
thread_id. - Publish до
interrupt()→ при resume двойная публикация. Решение: publish строго после approve. - Раздутый контекст в
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
Чек-лист отладки:
- Откройте путь выполнения: не зациклился ли
draft ↔ qa. - Проверьте размер
messages— нет ли простыни из сырых HTML. - На MCP-ошибках смотрите: это ошибка tool (агент может исправиться) или transport (сервер лежит).
- На HITL убедитесь, что resume идёт с тем же
thread_id. - Для регрессий поведения подключайте трассировку/eval (в экосистеме — LangSmith): один и тот же бриф не должен сегодня публиковать бред, а вчера — нормальный текст.
Чеклист перед боем: что проверить за 15 минут
- Есть checkpointer не только в RAM, если нужен рестарт.
- У каждой задачи уникальный
thread_id. - Publish недоступен до approve.
- Publish идемпотентен.
- MCP на проде не через хрупкий stdio без необходимости.
- В state нет лишних мегабайт логов.
- Есть ручной сценарий «отклонить и вернуть на draft».
- Каналы по умолчанию = draft-only.
Что проверяли по источникам
- Позиционирование LangGraph как orchestration runtime — docs overview.
- Persistence: checkpointer vs store, InMemory/Sqlite/Postgres — docs persistence.
- Interrupt / Command(resume) — docs interrupts.
- MCP adapters и паттерн ToolNode — GitHub
langchain-mcp-adapters. - Свежий 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 до необратимого вызова.
С чего начать, если цель — контент, а не демо в ноутбуке
- Один канал (лучше Telegram draft или WP draft).
- Четыре узла: research → draft → approve → publish.
- Sqlite checkpointer.
- Один HITL перед publish.
- Только после стабильности добавляйте MCP, RAG и второго субагента.
Так вы получаете не «ещё одного чат-бота», а управляемый кусок контент-завода: агент ускоряет рутину, человек держит качество и бренд.
