Пошаговые инструкции intermediate 14 мин

Как собрать ИИ-агента на LangGraph: пошаговая инструкция

Практический гайд по созданию AI-агента на LangGraph: StateGraph, state, LLM node, tool node, conditional edges, запуск и короткая память через checkpointer.

AI-агенты LangGraph tool calling Инструкция Python memory

LangGraph — фреймворк для создания stateful AI-агентов и workflow на коде. Он полезен, когда no-code builder уже тесен: нужно явно управлять состоянием, шагами, tool calling, памятью, ветвлениями, логами и тестируемой архитектурой агента.

Короткая версия: создайте Python-проект, опишите state, добавьте LLM node, tool node, conditional edge, скомпилируйте граф и протестируйте цикл “модель решила — tool выполнил — модель ответила”.

Что мы соберем

Соберем минимального агента, который принимает сообщение пользователя, решает, нужен ли инструмент, вызывает tool для создания задачи и возвращает финальный ответ. Это не production-система, а понятный скелет, на который потом можно добавить память, RAG, проверки и API.

  • State хранит сообщения и промежуточные данные.
  • LLM node вызывает модель и решает, нужен ли tool.
  • Tool node выполняет выбранный инструмент.
  • Conditional edge направляет граф: продолжать к tool или завершать ответ.
  • Checkpointer позже добавляет память между сообщениями одного thread.

Что понадобится

  • Python 3.10+.
  • API-ключ модели, например OpenAI, Anthropic или другой провайдер через LangChain.
  • Базовое понимание Python-функций и виртуального окружения.
  • Терминал и редактор кода.
  • Тестовый сценарий агента без доступа к реальным данным клиентов.

Шаг 1. Создайте проект

Создайте отдельную папку проекта и виртуальное окружение. Для примера используем pip, но можно сделать то же самое через uv или poetry.

mkdir langgraph-agent-demo
cd langgraph-agent-demo
python -m venv .venv
.venv\Scripts\activate
pip install -U langgraph langchain langchain-openai python-dotenv

На macOS или Linux активация окружения будет другой: source .venv/bin/activate.

Шаг 2. Добавьте API-ключ

Создайте файл .env и положите туда ключ модели. Не вставляйте ключ прямо в код и не публикуйте .env в репозиторий.

OPENAI_API_KEY=sk-...

Если используете другого провайдера, замените пакет и модель в коде на подходящий вариант из экосистемы LangChain.

Шаг 3. Создайте файл агента

Создайте файл agent.py. Сначала импортируем зависимости, загружаем .env и описываем state. В LangGraph state — это объект, который передается между узлами графа.

import operator
from typing import Annotated, Literal, TypedDict

from dotenv import load_dotenv
from langchain_core.messages import AnyMessage, HumanMessage, SystemMessage, ToolMessage
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph

load_dotenv()


class AgentState(TypedDict):
    messages: Annotated[list[AnyMessage], operator.add]

Annotated с operator.add означает, что новые сообщения будут добавляться к списку, а не перезаписывать его. Это удобно для цикла “модель — tool — модель”.

Шаг 4. Опишите tool

Tool — это обычная Python-функция с описанием. Модель читает описание и решает, когда вызвать этот инструмент. Для демо сделаем безопасный tool: он не пишет в реальную CRM, а только возвращает текст о созданной задаче.

@tool
def create_task(title: str, priority: str = "normal") -> str:
    """Create a draft task for a human operator.

    Args:
        title: Short task title.
        priority: Task priority: low, normal, or high.
    """
    return f"Draft task created: {title} (priority: {priority})"


tools = [create_task]
tools_by_name = {tool.name: tool for tool in tools}

Шаг 5. Подключите модель

Создайте модель и привяжите к ней tools. В примере используем ChatOpenAI, но структура будет похожей и для других chat model провайдеров, если они поддерживают tool calling.

model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
model_with_tools = model.bind_tools(tools)

Шаг 6. Создайте LLM node

LLM node вызывает модель. Он получает state, добавляет системное сообщение и возвращает новое сообщение модели. Если модель решит вызвать tool, это будет видно в tool_calls последнего сообщения.

def call_model(state: AgentState) -> dict:
    system = SystemMessage(
        content=(
            "You are a careful assistant. "
            "If the user asks to create or register a task, use create_task. "
            "Do not perform destructive actions."
        )
    )

    response = model_with_tools.invoke([system] + state["messages"])
    return {"messages": [response]}

Шаг 7. Создайте Tool node

Tool node берет tool_calls из последнего сообщения модели, находит нужный инструмент, выполняет его и возвращает ToolMessage обратно в state. После этого граф снова отправит результат в модель, чтобы она сформулировала ответ пользователю.

def call_tools(state: AgentState) -> dict:
    outputs = []
    last_message = state["messages"][-1]

    for tool_call in last_message.tool_calls:
        selected_tool = tools_by_name[tool_call["name"]]
        result = selected_tool.invoke(tool_call["args"])
        outputs.append(
            ToolMessage(
                content=str(result),
                tool_call_id=tool_call["id"],
            )
        )

    return {"messages": outputs}

Шаг 8. Добавьте условный переход

Conditional edge решает, что делать дальше: если модель запросила tool, идем в tool node; если tool_calls нет, завершаем граф и возвращаем ответ.

def should_continue(state: AgentState) -> Literal["tools", "__end__"]:
    last_message = state["messages"][-1]

    if getattr(last_message, "tool_calls", None):
        return "tools"

    return END

Шаг 9. Соберите граф

Теперь описываем узлы и ребра. Граф стартует с model, затем либо идет в tools и возвращается к model, либо завершает выполнение.

builder = StateGraph(AgentState)

builder.add_node("model", call_model)
builder.add_node("tools", call_tools)

builder.add_edge(START, "model")
builder.add_conditional_edges("model", should_continue)
builder.add_edge("tools", "model")

agent = builder.compile()

Шаг 10. Запустите агента

Добавьте в конец файла тестовый запуск. Первый запрос должен заставить модель вызвать create_task.

if __name__ == "__main__":
    result = agent.invoke(
        {
            "messages": [
                HumanMessage(
                    content="Создай задачу: проверить заявку клиента по AI-агенту. Приоритет высокий."
                )
            ]
        }
    )

    print(result["messages"][-1].content)

Запустите файл командой python agent.py. Если все настроено правильно, модель вызовет tool, получит результат и вернет финальный ответ.

Шаг 11. Проверьте сообщения графа

Для отладки полезно вывести не только финальный ответ, но и весь список messages. Так видно, был ли tool call, какие аргументы модель передала и какой результат вернул tool.

for message in result["messages"]:
    print(type(message).__name__, message)

Это важная привычка: agentic workflow нельзя проверять только по красивому финальному ответу. Нужно видеть путь выполнения.

Шаг 12. Добавьте короткую память

Чтобы агент помнил сообщения внутри thread, добавьте checkpointer. Для локального эксперимента подойдет in-memory checkpointer. Для production лучше использовать устойчивое хранилище, например SQLite или Postgres checkpointer.

from langgraph.checkpoint.memory import InMemorySaver

checkpointer = InMemorySaver()
agent = builder.compile(checkpointer=checkpointer)

config = {"configurable": {"thread_id": "demo-user-1"}}

agent.invoke(
    {"messages": [HumanMessage(content="Меня зовут Ирина.")]},
    config=config,
)

result = agent.invoke(
    {"messages": [HumanMessage(content="Создай задачу по моей заявке.")]},
    config=config,
)

print(result["messages"][-1].content)

thread_id отделяет одну беседу от другой. Без него легко случайно смешать контекст разных пользователей.

Шаг 13. Добавьте ограничения

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

  • Не давайте агенту удалять данные без подтверждения человека.
  • Проверяйте аргументы tool перед выполнением.
  • Логируйте tool calls и результаты.
  • Разделяйте тестовые и production credentials.
  • Ограничивайте число циклов, чтобы агент не застревал в бесконечных вызовах.

Шаг 14. Что делать дальше

После минимального агента можно развивать архитектуру: добавить RAG, несколько tools, отдельный supervisor, streaming, structured output, persistent memory, тесты и трассировку через LangSmith. Но лучше добавлять по одному усложнению и каждый раз проверять поведение графа.

  • RAG: добавьте tool поиска по базе знаний.
  • CRM: замените demo tool на безопасную запись черновика.
  • Multi-agent: вынесите разные роли в отдельные subgraphs или supervisor-схему.
  • Observability: подключите трассировку и сохраняйте ошибки.
  • Production: используйте persistent checkpointer и ограничения прав.

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

LangGraph подходит новичкам?

LangGraph требует базового Python и понимания agentic workflow. Если вы хотите быстро собрать no-code прототип, проще начать с n8n или Flowise. Если нужен контроль над состоянием, ветвлениями и тестируемой логикой, LangGraph подходит лучше.

Чем LangGraph отличается от LangChain?

LangChain дает компоненты для работы с моделями, tools, prompts и интеграциями. LangGraph фокусируется на orchestration: state, graph, циклы, ветвления, memory, persistence и многошаговые агенты.

Можно ли использовать LangGraph с OpenAI, Claude или Gemini?

Да, если выбранный chat model provider поддерживается через LangChain и подходит для tool calling. Конкретные импорты и параметры модели могут отличаться.

Нужно ли сразу добавлять память?

Нет. Сначала соберите агент без памяти и убедитесь, что tool calling работает. Потом добавьте checkpointer и thread_id, чтобы агент мог продолжать диалог в рамках одной беседы.

Дальше по теме

Похожие материалы