LangChain create_agent и цикл агента | Курс LangChain Agents урок 1
Цель урока: после этого урока вы сможете создать агента с инструментами, понять, как он принимает решения и прочитать трейс в LangSmith.
Теория
Чем агент отличается от цепочки
В первом курсе вы строили цепочки: prompt | model | parser. Цепочка выполняется
линейно, шаги заданы заранее и она не принимает решений. Запустили, получили
результат.
Агент устроен иначе. У него есть цель и набор инструментов и он сам решает, что делать на каждом шаге.
Выглядит так:
Запрос → Модель думает → Вызвать инструмент? → Да → Инструмент выполняется
↑ ↓
Результат ←←←←←←←←←←
↓
Нет → Ответ пользователю
Модель получает запрос, решает, нужен ли инструмент, вызывает его, видит результат и снова думает. Цикл продолжается до тех пор, пока модель не решит, что ответ готов.
Это называется циклом ReAct: Reasoning (рассуждение) и Acting (действие).
Почему цепочки перестают справляться
Представьте задачу: "найди последние новости про компанию X и сделай краткое резюме". Цепочка не может её решить, потому что заранее неизвестно:
- нужен ли поиск (может, информация уже в промпте)
- сколько раз надо искать
- какие именно запросы делать
Агент решает это, в этом его смысл.
create_agent
LangChain create_agent - это высокоуровневый API LangChain v1+, который строит агента
поверх LangGraph. Внутри граф состояния с двумя основными узлами: model и tools.
Подробнее граф разберём в уроке 2, сейчас нам важно уметь им пользоваться.
Минимальный вызов:
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4o-mini")
agent = create_agent(
model=model,
tools=[],
)
Три ключевых параметра:
model- экземпляр класса модели или строка в формате"provider:model"tools- список инструментов, доступных агентуprompt- системный промпт (опционально)
Почему ChatOpenAI, а не строка?
create_agent поддерживает строковые имена вида "openai:gpt-4o-mini", но только
для стандартных провайдеров. Если вы используете кастомный эндпоинт через
OPENAI_BASE_URL (прокси, локальная модель), строка не сработает. LangChain
попытается определить провайдера по имени и произойдет ошибка. ChatOpenAI автоматически
подхватывает OPENAI_API_KEY и OPENAI_BASE_URL из окружения и передаёт
имя модели.
Инструменты
Инструмент - это функция Python с декоратором @tool. Описание в docstring важно, именно его читает модель, когда решает, какой инструмент вызвать.
from langchain.tools import tool
@tool
def get_weather(city: str) -> str:
"""Возвращает текущую погоду для указанного города."""
return f"В городе {city} сейчас 18°C, облачно."
Хорошее описание отвечает на вопрос: "когда нужно вызвать этот инструмент?"
Как запустить агента
Агент принимает словарь с ключом messages:
response = agent.invoke({
"messages": [{"role": "user", "content": "Какая погода в Москве?"}]
})
print(response["messages"][-1].content)
response["messages"] - это полная история: запрос пользователя, решение
о вызове инструмента, результат инструмента, финальный ответ. Последний
элемент это ответ агента.
Примеры кода
Минимальный агент
import os
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
load_dotenv()
model = ChatOpenAI(model=os.getenv("MODEL_NAME", "gpt-4o-mini"))
agent = create_agent(
model=model,
tools=[],
)
response = agent.invoke({
"messages": [{"role": "user", "content": "Сколько будет 17 умножить на 43?"}]
})
print(response["messages"][-1].content)
# Вывод: 17 × 43 = 731
Без инструментов агент отвечает только на основе знаний модели. Это вырожденный случай, но полезен для проверки, что всё работает.
Агент с инструментом
import os
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_openai import ChatOpenAI
load_dotenv()
@tool
def multiply(a: int, b: int) -> int:
"""Умножает два числа. Используй, когда нужно посчитать произведение."""
return a * b
model = ChatOpenAI(model=os.getenv("MODEL_NAME", "gpt-4o-mini"))
agent = create_agent(
model=model,
tools=[multiply],
)
response = agent.invoke({
"messages": [{"role": "user", "content": "Сколько будет 17 умножить на 43?"}]
})
print(response["messages"][-1].content)
# Вывод: 17 × 43 = 731
На первый взгляд результат тот же. Разница видна в LangSmith: в первом случае один узел (model), во втором - model → tools → model.
Сквозной проект: базовый агент-аналитик
Создаём агента с двумя инструментами: поиск информации и чтение файла. Пока инструменты заглушки, в уроке 3 подключим реальные через MCP.
import os
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.tools import tool
from langchain_openai import ChatOpenAI
load_dotenv()
@tool
def search_web(query: str) -> str:
"""Ищет информацию в интернете по запросу. Используй для поиска актуальных
данных, новостей, фактов о компаниях, событиях и людях."""
# Заглушка. В уроке 3 заменим на реальный MCP.
return f"[Результаты поиска по запросу '{query}']: найдено 5 источников."
@tool
def read_file(path: str) -> str:
"""Читает содержимое текстового файла по указанному пути. Используй, когда
нужно проанализировать локальный документ."""
try:
with open(path, "r", encoding="utf-8") as f:
return f.read()
except FileNotFoundError:
return f"Файл '{path}' не найден."
SYSTEM_PROMPT = """Ты аналитик-исследователь. Твоя задача - собирать информацию
по запросу пользователя, используя доступные инструменты, и давать структурированный
ответ с выводами.
Если информации недостаточно, сделай несколько поисковых запросов, уточняя каждый
следующий на основе предыдущих результатов."""
model = ChatOpenAI(model=os.getenv("MODEL_NAME", "gpt-4o-mini"))
agent = create_agent(
model=model,
tools=[search_web, read_file],
system_prompt=SYSTEM_PROMPT,
)
response = agent.invoke({
"messages": [{
"role": "user",
"content": "Найди информацию о компании Anthropic: чем занимается и когда основана."
}]
})
print(response["messages"][-1].content)
Запустите и откройте LangSmith. Вы увидите каждый шаг: какой инструмент агент решил вызвать, с какими аргументами, что получил в ответ.
Частые ошибки
Агент отвечает без вызова инструмента, хотя должен был его вызвать
# Плохое описание
@tool
def search(q: str) -> str:
"""Поиск.""" # слишком коротко
...
# Хорошее описание
@tool
def search(query: str) -> str:
"""Ищет актуальную информацию в интернете по текстовому запросу.
Используй для получения фактов, новостей, данных о компаниях и событиях."""
...
Модель выбирает инструмент по описанию. Если описание слишком короткое или неясное, модель решит ответить из собственных знаний.
Ответ агента не там, где ищете
response = agent.invoke({"messages": [...]})
# Неправильно: response - это словарь, не строка
print(response) # {'messages': [HumanMessage(...), AIMessage(...), ...]}
# Правильно: берём последнее сообщение
print(response["messages"][-1].content)
response - словарь с историей сообщений.
Финальный ответ всегда последний
элемент в списке messages.
Модель не поддерживает tool calling
BadRequestError: This model does not support tool use.
Агенты требуют модели с поддержкой tool calling. Большинство современных моделей
поддерживают это, но старые или маленькие модели могут не поддерживать. Используйте
gpt-4o-mini, claude-haiku-4-5 или аналоги.
Агент зациклился
Если агент попал в петлю (вызывает инструменты снова и снова), в LangSmith
вы увидите длинную цепочку повторяющихся вызовов. По умолчанию create_agent
ограничивает количество итераций. Если лимит достигнут, агент вернёт последнее
состояние с сообщением об ошибке.
Причина обычно в системном промпте или инструментах: агент не понимает, когда задача выполнена. Добавьте в промпт явное условие завершения.
Задание
Создайте агента для конвертации валют. У агента должны быть два инструмента:
get_rate(from_currency: str, to_currency: str) -> float- возвращает курс обмена (можно использовать фиксированные значения как заглушку)convert(amount: float, rate: float) -> float- умножает сумму на курс
Задайте системный промпт, объясняющий агенту его роль.
Запросите агента: "Сколько рублей я получу за 100 долларов?".
Ожидаемое поведение: агент вызовет get_rate("USD", "RUB"), затем convert(100, <курс>),
затем ответит конкретной суммой.
Откройте трейс в LangSmith и проверьте, что оба инструмента были вызваны в правильном порядке.
Подписывайтесь на мой Telegram канал
Если вам нужен ментор и вы хотите научиться разрабатывать AI агентов, пишите, обсудим условия
Авторизуйтесь, чтобы оставить комментарий.
Нет комментариев.
Тут может быть ваша реклама
Пишите info@aisferaic.ru