Все посты

Я собрал маленький AI-агент — вот что наконец щёлкнуло

Опубликовано 29 июня 2026 г. · 9 мин чтения

Короче, на этой неделе я собрал маленький AI-агент

Не чат-бот. Настоящий агент. Даёшь ему вопрос — он сам лезет в интернет, читает что нашёл, решает хватает или надо ещё покопать, и выдаёт ответ со ссылками. Строк двести-триста на Python. Ничего особенного.

Но пока делал, куча buzzword-ов наконец встала на место, и я решил записать что реально понял — с настоящим кодом, потому что именно он всё и прояснил. Весь процесс меня преследовал один занудный вопрос: а почему не собрать это на том, что я уже знаю?

Сначала покажу как штука выглядит в работе, потом разберём по кускам.

Как это выглядит когда запускаешь

Всё приложение — крошечный web-сервер. Кидаешь ему вопрос, он стримит обратно что делает, шаг за шагом. Вот реальный запуск прямо из моего терминала:

Видишь порядок? Сначала поискал, потом прочитал, потом ответил. На сложном вопросе он гоняет поиск → чтение → поиск → чтение → ответ — крутит пока не насытится. Никто это не хардкодил. Вот и весь фокус, и он проще чем звучит.

Честно — агент это просто цикл

Всё. Это и есть секрет. Снимаешь маркетинговую обёртку — агент это цикл с языковой моделью внутри:

  1. Отправляешь модели вопрос и говоришь какими тулами она может пользоваться.
  2. Модель отвечает одним из двух: «запусти вот этот тул с вот этими аргументами» или «ок, вот ответ».
  3. Если попросила тул — запускаешь, возвращаешь результат, идёшь обратно к шагу 1.
  4. Если ответила — всё, готово.

«Умная» часть — это то, что модель каждый раз решает: уже знаю достаточно или надо ещё поискать? Я смотрел как моя работает — на хитром вопросе поискала дважды, на простом один раз — и никто не говорил ей сколько раз искать. Сама дошла. Вот эта маленькая решалка — это и есть весь агент. Остальное — сантехника.

Только гуглить сама она не умеет

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

Поэтому агенту нужен тул чтобы тащить свежие данные. Я взял Tavily — по сути поисковик сделанный для AI. Кидаешь запрос, получаешь чистые результаты (заголовок, сниппет, ссылка) обычным текстом который модель может читать. Обычный Google вернул бы грязную HTML-страницу в рекламе; Tavily отдаёт реальный контент. В коде это почти ничего:

Именно поэтому мой агент смог сказать кто получил Нобелевку по физике 2024 — нашёл, взял свежий текст, подытожил. Поставь вместо него Bing или DuckDuckGo — больше ничего не изменится. Это просто «штука которая идёт и приносит реальность».

Сам граф

Ну вот и то ради чего я сюда пришёл. LangGraph гоняет тот цикл — но моделирует его как граф: ноды (шаги), соединённые рёбрами (что происходит дальше). Весь мой агент — две ноды и одно решение.

Сначала стейт — что течёт через граф. Здесь это просто текущий список сообщений:

Потом решалка — после того как модель ответила, идём искать или всё? Это сердце всей штуки, и это четыре строки:

А потом собираешь всё вместе. Нода agent вызывает модель; нода tools запускает Tavily; conditional edge гоняет их по кругу пока should_continue не скажет стоп:

Прочитай последние три строки вслух: начинаем с агента; после агента — развилка (искать или стоп); после поиска — обратно к агенту. Это и есть цикл, нарисованный как граф. Когда вызываешь graph.astream(...), LangGraph идёт по нему и отдаёт тебе каждый шаг по мере выполнения — это именно то что стримилось в мой терминал выше.

Стримим в браузер

Серверная часть — это просто FastAPI которая превращает каждый шаг графа в одну из тех строк event: (Server-Sent Events). Коротко:

Маленькая HTML-страница слушает этот стрим и рисует таймлайн вживую — пользователь наблюдает как агент думает, а не смотрит на спиннер. Это важнее чем звучит — «показывай как делаешь» это половина того почему штука ощущается надёжной.

Ладно, так зачем тогда LangGraph?

Вот тут надо было честно посмотреть на себя в зеркало. Посмотри снова на тот цикл. Он аккуратный и чистый... но написанный руками, без фреймворка, это строк пятнадцать:

Для одного тула и простого цикла вот этот голый while — genuinely нормал. Ещё и легче. Никакого фреймворка учить. Ну так почему я вообще взял LangGraph?

«А почему не просто Next.js и OpenAI?»

Ну вот, я всё время крутил этот вопрос — и он хороший, но в нём маленькая ловушка. Next.js и LangGraph не конкуренты. Они даже не стоят на одной полке:

  • Next.js — это приложение, UI и сервер. Это замена FastAPI + HTML которые я использовал, а не LangGraph.
  • OpenAI — мозг.
  • Tavily — веб-тул, нужен в любом случае.
  • LangGraph — цикл, та часть которую иначе просто пишешь сам.

Так что «Next.js + OpenAI» значит: Next.js для приложения, OpenAI для мозга, и цикл катаешь руками. Для моего маленького демо? Сработало бы и было бы проще. Не буду делать вид что иначе.

Так когда фреймворк реально стоит того?

LangGraph начинает отрабатывать на второй и третьей фиче, не на первой — когда цикл перестаёт быть аккуратным маленьким while:

  • Куча тулов с ветвлением — «математический вопрос сюда, поиск туда, запрос в базу — вон туда». В графе это одно аккуратное ребро, в своём цикле — растущая куча вложенных if-ов.
  • Память которая переживёт перезапуск — сохранить стейт в базу, поставить на паузу чтобы человек что-то одобрил, потом продолжить. Это большая тема. Катать своё такое — быстро становится страшно.
  • Стриминг каждого шага — прогресс searching → reading → answer получил почти бесплатно.
  • Несколько агентов — researcher передаёт работу writer-у, у каждого свой граф.

Короче: один тул и прямой цикл? Просто пишешь цикл. Как только клиент попросит «агента который юзает пять тулов, помнит весь разговор и консультируется со мной перед любым дорогим действием» — вот тут твой хэнд-роллд превращается в спагетти, а граф остаётся читаемым.

Хочешь попробовать сам?

Всё это реально крошечное. Если есть ключ OpenAI и (бесплатный) ключ Tavily — минут пять настройки:

И структура проекта примерно настолько плоская насколько возможно — никакого лабиринта src/, никаких двенадцати конфиг-файлов:

Открой localhost:8000, спроси что-нибудь из недавних событий и смотри как он ищет. Первый раз когда он сам покрутит цикл дважды и выдаст точный ответ — это перестаёт ощущаться как «OpenAI с лишними шагами» и начинает ощущаться как маленькая штука которая реально соображает что ей нужно.

Зачем я вообще возился с чем-то таким маленьким

Я мог подождать пока какой-нибудь проект не затащит меня в агентов насильно. Не захотел. Выучить вещь на простой задаче — значит когда придёт страшная версия, она уже будет знакома. А на Upwork «напиши AI-агент который делает X, Y и Z» — это запрос который я вижу примерно раз в месяц. Так что когда придёт настоящий — не буду одновременно разбираться и в туле и в задаче.

Вот в чём весь смысл weekend-проектов, если честно. Плати налог на обучение пока ничего не стоит на кону — и сохраняй чек на тот момент когда это будет важно.