Як побудувати AI агента з LangGraph та вибрати правильні інструменти

Практичний гайд зі створення AI агента за допомогою LangGraph та підбору оптимальних інструментів для нього

Більшість розробників стикаються з однією проблемою: вони будують AI-агентів через прості ланцюжки LangChain, але ті ламаються щойно логіка стає складнішою — агент не може повернутись до попереднього кроку, «застрягає» в циклі або не знає, який інструмент використати. LangGraph вирішує це через граф стану, де кожен вузол — це окрока дія, а ребра — умови переходу. У цьому туторіалі ти побудуєш повноцінного агента з трьома інструментами за 60–90 хвилин. Потрібен базовий рівень Python і аккаунт на OpenAI або Anthropic.

🛠️ Що знадобиться

  • Python 3.11+ — основна мова, переконайся що версія не нижча за 3.11, бо LangGraph використовує TypedDict з новими можливостями
  • LangGraph 0.3+ — безкоштовна бібліотека від LangChain Inc., встановлюється через pip; саме вона дає граф стану замість лінійних ланцюжків
  • LangChain 0.3+ — безкоштовна, потрібна для інтеграцій з LLM та інструментами
  • OpenAI API ключ — платний (≈$0.002 за запит для gpt-4o-mini), або безкоштовний Groq API якщо хочеш заощадити
  • Tavily API — безкоштовний план дає 1000 запитів/місяць; це пошуковий інструмент для агента
  • VS Code або PyCharm — редактор коду, обидва безкоштовні для особистого використання

📋 Покрокова інструкція

Крок 1: Встановлення залежностей та налаштування середовища

Відкрий термінал і створи новий проєкт: виконай mkdir langgraph-agent && cd langgraph-agent, потім python -m venv venv і активуй оточення командою source venv/bin/activate (на Windows: venv\Scripts\activate). Встанови всі потрібні бібліотеки однією командою: pip install langgraph==0.3.* langchain==0.3.* langchain-openai tavily-python python-dotenv. Створи файл .env в корені проєкту і додай туди два рядки: OPENAI_API_KEY=sk-твій-ключ та TAVILY_API_KEY=tvly-твій-ключ. Ключ Tavily отримай на сайті tavily.com → кнопка «Get API Key» → реєструйся через Google → ключ з’явиться в дашборді одразу після входу.

Крок 2: Визначення стану агента та інструментів

Створи файл agent.py і на початку визнач структуру стану — це серце LangGraph. Стан — це об’єкт TypedDict, який передається між вузлами графа і накопичує всю інформацію. Скопіюй цей код:

from typing import TypedDict, Annotated, List
from langgraph.graph import StateGraph, END
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, AIMessage, BaseMessage
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.tools import tool
import operator, os
from dotenv import load_dotenv

load_dotenv()

class AgentState(TypedDict):
    messages: Annotated[List[BaseMessage], operator.add]
    current_tool: str
    iteration_count: int

Поле messages з анотацією operator.add означає що повідомлення накопичуються, а не перезаписуються — це критично важливо для пам’яті агента.

Крок 3: Створення та реєстрація інструментів

Правильний вибір інструментів — це 70% успіху агента. Кожен інструмент повинен мати чіткий docstring, бо LLM читає саме його щоб вирішити чи використовувати цей інструмент. Додай три інструменти до agent.py:

# Інструмент 1: Пошук в інтернеті
search_tool = TavilySearchResults(max_results=3)
search_tool.name = "web_search"
search_tool.description = "Шукає актуальну інформацію в інтернеті. Використовуй коли потрібні свіжі дані, новини або факти після 2024 року."

# Інструмент 2: Калькулятор
@tool
def calculator(expression: str) -> str:
    """Обчислює математичні вирази. Приймає рядок типу '2 + 2 * 10'. Використовуй для будь-яких розрахунків."""
    try:
        result = eval(expression, {"__builtins__": {}}, {})
        return f"Результат: {result}"
    except Exception as e:
        return f"Помилка обчислення: {str(e)}"

# Інструмент 3: Збереження нотаток
notes_storage = []

@tool
def save_note(content: str) -> str:
    """Зберігає важливу інформацію для подальшого використання. Використовуй коли знайшов корисний факт який може знадобитись далі."""
    notes_storage.append(content)
    return f"Збережено нотатку #{len(notes_storage)}: {content}"

tools = [search_tool, calculator, save_note]

Зверни увагу: docstring для calculator містить конкретний приклад вхідних даних — це різко підвищує точність вибору інструменту моделлю.

Крок 4: Побудова вузлів графа та логіки переходів

Тепер створи LLM з прив’язаними інструментами та два ключові вузли — «агент» і «виконавець інструментів». Додай цей блок:

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

# Вузол агента — думає і вирішує що робити
def agent_node(state: AgentState) -> AgentState:
    if state["iteration_count"] >= 10:
        # Захист від нескінченних циклів
        return {"messages": [AIMessage(content="Досягнуто ліміт ітерацій.")], "iteration_count": state["iteration_count"]}
    
    response = llm_with_tools.invoke(state["messages"])
    return {
        "messages": [response],
        "iteration_count": state["iteration_count"] + 1
    }

# Вузол інструментів — виконує вибраний інструмент
tool_node = ToolNode(tools)

# Умова переходу: продовжувати чи зупинитись?
def should_continue(state: AgentState) -> str:
    last_message = state["messages"][-1]
    if hasattr(last_message, "tool_calls") and last_message.tool_calls:
        return "use_tools"
    return "end"

Функція should_continue — це і є «мозок» маршрутизації: якщо LLM повернув виклик інструменту, йдемо до tool_node, інакше завершуємо роботу.

Крок 5: Збірка графа та запуск агента

Фінальний крок — з’єднати всі вузли в граф і запустити його. Додай в кінець файлу:

# Будуємо граф
graph = StateGraph(AgentState)
graph.add_node("agent", agent_node)
graph.add_node("tools", tool_node)

# Встановлюємо точку входу
graph.set_entry_point("agent")

# Додаємо умовні переходи
graph.add_conditional_edges(
    "agent",
    should_continue,
    {"use_tools": "tools", "end": END}
)

# Після виконання інструменту — завжди повертаємось до агента
graph.add_edge("tools", "agent")

# Компілюємо
app = graph.compile()

# Запускаємо!
if __name__ == "__main__":
    initial_state = {
        "messages": [HumanMessage(content="Знайди актуальний курс EUR/USD і порахуй скільки коштуватимуть 500 євро в доларах")],
        "current_tool": "",
        "iteration_count": 0
    }
    
    result = app.invoke(initial_state)
    print(result["messages"][-1].content)

Запусти командою python agent.py — агент самостійно вирішить що спочатку потрібен пошук, потім калькулятор, і поверне фінальну відповідь. Якщо все налаштовано правильно, ти побачиш розгорнуту відповідь з поточним курсом та підрахованою сумою.

⚠️ Типові помилки та як їх уникнути

  • Розмиті описи інструментів — якщо docstring написано як «робить корисні речі», модель ніколи не вибере цей інструмент правильно; завжди описуй конкретно КОЛИ і ЧИМ відрізняється інструмент від інших
  • Відсутність захисту від циклів — без лічильника ітерацій агент може нескінченно викликати інструменти і спустошити твій API баланс за хвилини; завжди додавай перевірку iteration_count >= N
  • Перезапис стану замість накопичення — якщо забути анотацію operator.add для поля messages, кожен вузол перетирає попередні повідомлення і агент «забуває» контекст після першого ж кроку
  • Temperature != 0 для агентів — встановлюй temperature=0 обов’язково, бо будь-яка випадковість у виборі інструментів призводить до непередбачуваної поведінки
  • Занадто багато інструментів одразу — більше 8-10 інструментів плутають модель; групуй схожі функції або використовуй підграфи для складних сценаріїв

💡 Поради для кращого результату

По-перше, використовуй app.stream() замість app.invoke() під час розробки — ти будеш бачити кожен крок агента в реальному часі і одразу зрозумієш де він «думає неправильно». По-друге, додай checkpointer від LangGraph (from langgraph.checkpoint.memory import MemorySaver) і передай його в graph.compile(checkpointer=MemorySaver()) — це дасть агенту пам’ять між різними розмовами через параметр thread_id. По-третє, якщо агент постійно вибирає неправильний інструмент, додай в системний промпт явне правило: «Для пошуку ЗАВЖДИ використовуй web_search, а не власні знання» — це простіше і ефективніше ніж переписувати docstring. По-четверте, логуй кожен виклик інструменту в файл через стандартний logging модуль — це безцінно коли агент в продакшені починає поводитись дивно і треба розібратись чому.

❓ Часті запитання (FAQ)

1. Чим LangGraph відрізняється від звичайних LangChain ланцюжків?
LangChain ланцюжки — це лінійна послідовність кроків A→B→C без можливості повернутись або розгалузитись. LangGraph — це направлений граф де агент може повертатись до попередніх вузлів, виконувати паралельні гілки або приймати умовні рішення. Для простих завдань достатньо ланцюжків, але для агентів з кількома інструментами LangGraph є стандартом у 2026 році.

2. Чи можна використовувати безкоштовні LLM замість OpenAI?
Так, заміни ChatOpenAI на ChatGroq з бібліотеки langchain-groq і використовуй модель llama-3.3-70b-versatile — Groq дає безкоштовний план з 14,400 запитів на день. Єдиний нюанс: деякі open-source моделі гірше дотримуються інструкцій щодо вибору інструментів, тому може знадобитись детальніший системний промпт.

3. Як додати пам’ять між сесіями (не тільки в межах одного запуску)?
Використовуй PostgreSQL checkpointer: встанови langgraph-checkpoint-postgres, підключи до своєї БД і передай в compile(). При кожному запуску передавай однаковий thread_id для конкретного користувача — агент автоматично завантажить всю попередню історію розмови.

4. Скільки інструментів оптимально для одного агента?
Практика 2026 року показує: 3-7 інструментів для одного агента — це золота середина. Якщо потрібно більше, будуй мульти-агентну систему де кожен агент спеціалізується на своїй ніші (пошук, аналіз даних, комунікації), а головний агент-оркестратор делегує задачі.

5. Як дебажити агента коли він вибирає неправильний інструмент?
Увімкни детальне логування: додай import langchain; langchain.debug = True на початку файлу — ти побачиш точний промпт який іде до моделі і зрозумієш чому вона обрала певний інструмент. Також дуже помагає LangSmith — безкоштовний трейсинг від LangChain, де кожен запит візуалізується як дерево з усіма проміжними кроками.

🏁 Підсумок

Ти побудував повноцінного AI-агента з графом стану, трьома інструментами та захистом від циклів — це той самий архітектурний паттерн який використовують у продакшені такі компанії як Klarna та Replit для своїх AI-асистентів. Тепер твій агент вміє самостійно вирішувати коли шукати інформацію, коли рахувати і коли зупинятись.

Прямо зараз відкрий термінал, виконай перші три команди з Кроку 1 і запусти агента з тестовим запитом — навіть якщо щось піде не так, повідомлення про помилку одразу покаже що саме треба виправити. Наступний рівень після освоєння цього туторіалу — додати паралельні гілки в граф через Send() API і побудувати першого мульти-агента.

РОЗСИЛКА

📬 Щотижневий AI-дайджест

Найкращі статті про ШІ та автоматизацію — без спаму, лише суть

Без спаму · Відписатись будь-коли

Telegram