Архитектура современных ИИ-агентов: собираем прототип за один вечер. JavaScript.. JavaScript. llm.. JavaScript. llm. nodejs.. JavaScript. llm. nodejs. OpenClaw.. JavaScript. llm. nodejs. OpenClaw. selectel.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel. деплой.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel. деплой. ии-агенты.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel. деплой. ии-агенты. искусственный интеллект.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel. деплой. ии-агенты. искусственный интеллект. Машинное обучение.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel. деплой. ии-агенты. искусственный интеллект. Машинное обучение. облачный сервер.. JavaScript. llm. nodejs. OpenClaw. selectel. Блог компании Selectel. деплой. ии-агенты. искусственный интеллект. Машинное обучение. облачный сервер. Серверное администрирование.
Архитектура современных ИИ-агентов: собираем прототип за один вечер - 1

За последние полгода вышли сотни материалов об ИИ-агентах. Особенно много говорят про OpenClaw и Hermes. Я изучил, пожалуй, добрую половину из них, протестировал сам и хочу поделиться выводами.

Статью написал Арсений Помазков, Senior Software Инженер и автор канала Pomazkov.js

Сначала у меня сложилось впечатление, что это очередной раздутый пузырь бездумного хайпа. Каждый второй обещает личного цифрового сотрудника, который сам разбирает почту, ведет задачи и работает на вас 24/7, пока вы спите. Но досматривая такие видео и дочитывая статьи до конца, я раз за разом задавался вопросом: а где конкретно агент поменял автору жизнь? В чем революция? И, судя по обсуждениям в сети, я в этом недоумении не одинок.

Давайте признаем: полезных кейсов применения сейчас действительно немного, денег вся эта инфраструктура ест прилично, а половину демонстрируемых функций проще вызвать в обычном чате с ИИ. И это вполне валидные претензии к OpenClaw как к готовому продукту. Вот только рассматривать его исключительно как потребительский продукт — ошибка. Когда я это понял, мой взгляд на технологию кардинально изменился. Революция действительно произошла, но не там, где ее привыкли искать.

В этой статье мы подробно разберем, почему OpenClaw стал важной вехой в развитии ИИ, хотя и не предложил ничего принципиально нового, а затем рассмотрим архитектуру автономных агентов и пошагово пройдем процесс создания и деплоя вашего собственного цифрового помощника.

Эта идея уже проваливалась три года назад

Давайте вернемся в март 2023 года, когда появился прародитель OpenClaw — AutoGPT. Базовая схема была той же: цикл, регулярные обращения к нейросети, вызов внешних инструментов и решение задач по шагам. Проект тогда выстрелил, набрав более 100 000 звезд на GitHub за несколько недель, а следом за ним появился BabyAGI. Резонанс был огромным, хотя и не таким громким, как этой зимой.

Но почему же тогда все заглохло?

Главная причина крылась в возможностях самих ИИ-моделей. На тот момент флагманом была GPT-4, которая плохо удерживала длинные цепочки действий: она теряла контекст, повторялась, вызывала неподходящие инструменты и забывала конечную цель. Вся внешняя обвязка (код вокруг модели) была написана корректно, но системе не хватало достаточно умных «мозгов». В итоге AutoGPT окрестили бесполезным, и интерес к теме угас.

Качественный сдвиг произошел зимой 2026 года, когда сошлись сразу несколько факторов: к готовой обвязке добавились гораздо более продвинутые модели — Claude 4.5 (Opus и Sonnet), GPT-5.1, DeepSeek V3.2 и другие. Прежняя архитектура наконец раскрылась и начала доводить задачи до конца благодаря появлению тех самых новых «мозгов».

Однако узкое место не исчезло, а лишь сместилось. Теперь, когда модели научились справляться с длинными цепочками действий, на первый план вышли новые вызовы: интеграции, права доступа и стоимость инфраструктуры. Агенты все еще не могут платить, получать доступ к многим сервисам и безопасно работать с секретами.

Мне не нужно посылать агента смотреть погоду — я вполне могу сделать это сам, и выйдет даже быстрее. А вот задача «подобрать продукты в магазине по рецепту, оплатить их и оформить доставку» — вот что хочется делегировать автоматическому помощнику. Но сейчас этот процесс вызывает много трудностей: веб-сайты магазинов не адаптированы под API-агентов, платежных шлюзов для ИИ не существует, а безопасная работа с секретами и авторизацией вызывает много вопросов.

При этом важно понимать: мы не уперлись в тупик, а просто поднялись на уровень выше и столкнулись со следующей преградой. Рано или поздно эти проблемы решат, и агенты смогут выполнять действительно сложные сценарии.

Поэтому я предлагаю рассматривать OpenClaw или AutoGPT не как готовые продукты, а как инженерную обвязку — удобный фреймворк с циклами, памятью и интеграциями, построенный вокруг вызова ИИ. Революция в том, что появился новый способ соединить нейросеть с реальным миром и сделать его более автономным. Подобный подход будет становиться все популярнее с каждым обновлением моделей. Крупные IT-компании уже строят необходимую инфраструктуру, и именно нам, разработчикам, предстоит с этим работать: создавать специализированных агентов под узкие бизнес-задачи и проектировать среду для них.

Для этого нам необходимо отлично понимать, как агенты работают изнутри. К концу чтения статьи это понимание у вас уже сформируется, и вы получите навык, который мы скоро увидим в вакансиях. А параллельно сделаем пет-проект — своего кастомного ИИ-агента.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 2

Развиваете AI‑проект?

Заполните форму и получите до 2 000 000 ₽ на инфраструктуру

Получить грант →

Как работает ИИ-агент

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 3

В основе любого ИИ-агента лежит классический цикл, состоящий из трех элементов: внешнего триггера (входа в цикл), повторяющейся цепочки действий и условия выхода.

Вход в цикл

Агент не запускается сам по себе. Чтобы запустить процесс, нужен внешний импульс. Это может быть сообщение пользователя в Telegram, сработавший по расписанию планировщик (cron), вебхук или любое другое событие, которое код умеет ловить.

Компоновка запроса

После срабатывания триггера система формирует первый запрос к модели. Он состоит из двух ключевых частей:

  1. Контекст: история переписки (если она есть), системный промт (правила поведения) и новые данные из триггера (например, текст входящего письма).

  2. Описание инструментов (tools): их названия, текстовое описание назначения на человеческом языке и схема ожидаемых параметров.

Запрос упаковывается в формат JSON и отправляется по API в нейросеть.

Ответ от ИИ

Модель анализирует запрос и возвращает ответ, также в формате JSON. В нем содержатся две основные сущности: текстовое сообщение для пользователя (например, «Изучаю логи сервера» или финальный ответ на задачу) и указание на вызов конкретного инструмента с нужными параметрами (функции).

Также в ответе есть служебные поля (например, finish_reason), по которым система понимает текущий статус выполнения задачи.

Обработка ответа и вызов инструментов

Наша управляющая программа (диспетчер) принимает JSON от модели. Если модель решила вызвать инструмент, программа выполняет соответствующую функцию на локальной машине с переданными параметрами, фиксирует результат и добавляет его в историю диалога. Затем цикл повторяется: система снова компонует запрос к агенту, но теперь он видит и результат работы инструмента. С каждым шагом контекст удлиняется, и модель получает все больше фактов о проделанной работе.

Выход из цикла

Если в очередном ответе модели нет новых указаний и задача решена, цикл завершается. Кстати, ответ пользователю в Telegram — это такой же вызов инструмента, как и любое другое указание, поэтому это действие тоже происходит в цикле, а не после выхода из него.

Важное замечание: ИИ-модель ничего не выполняет на вашем сервере самостоятельно. Она лишь выдает текстовые инструкции, а запуск команд и чтение файлов происходит в управляющей программе. Поэтому безопасность ИИ-агента — это свойство вашего кода, а не самой модели. Если вы предоставите агенту доступ к терминалу без ограничений, он сможет выполнить любую команду. Если ограничите список инструментов безопасными функциями — риски будут сведены к минимуму.

Описание инструмента – тоже часть программирования

Поясню, что имею в виду. Раньше, чтобы решить, выполнять сценарий А или Б, мы писали конструкцию ifили else. Условие лежало в коде, мы придумывали его заранее и оно было жестким.

В случае с ИИ-агентом условия в if определяет сама модель в зависимости от ситуации, а человек лишь предоставляет ей цель и инструменты. Но мы все равно можем существенно повысить качество выбора модели с помощью грамотного описания этих инструментов.

Рассмотрим пример из реального кода OpenClaw. Вот как выглядит описание планировщика задач:

description: `Gateway scheduler: reminders, delayed self-wakeups,
loops, recurring work, event watchers.
Never exec sleep/poll as timer.`   // ← запрет обычным предложением

Фраза Never exec sleep/poll as timer («Никогда не используй sleep в качестве таймера») — это не проверка и не жесткое ограничение прав в коде, а текстовая инструкция. Она снижает вероятность неправильного выбора, но ничего не гарантирует на 100%. В том же файле далее содержится указание не переводить время в UTC и приводится пример корректного часового пояса. Описание инструмента здесь — это одновременно документация для модели и подсказка для предотвращения типичной ошибки.

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

Как устроена память у агентов

В Hermes работа с памятью — это одна из главных фишек. Агент способен накапливать опыт и преобразовывать повторяющиеся действия в навыки. Память делится на три слоя:

  • Два локальных текстовых файла, которые агент подгружает при каждом запуске: один содержит информацию о проекте, другой — сведения о пользователе (его предпочтения, ToV общения).

  • База данных с архивом прошлых диалогов: модель не читает его целиком, но осуществляет по нему семантический поиск по мере необходимости.

  • Каталог навыков: успешные цепочки действий агент сохраняет в виде отдельных сценариев и использует их при решении похожих задач.

Откуда берется большая кодовая база

Если базовый цикл ИИ-агента можно уместить всего в сотню строк кода, то почему репозиторий OpenClaw содержит почти три миллиона?

Дело в том, что сам по себе этот цикл — лишь ядро системы. Основную же часть кодовой базы составляет инженерная обвязка: интеграции с мессенджерами и внешними сервисами, механизмы повторных попыток при сбоях сети или API, авторизация и разграничение прав доступа, пользовательский интерфейс, а также управление контекстом и обработка ошибок.

В итоге перед нами не «скрытый второй интеллект», а большой объём обычной инженерной работы, появившийся в ходе множества итераций тестирования и ошибок.

OpenClaw VS. Hermes

Если внутри у них работает один и тот же цикл, то чем они тогда отличаются?

Основная разница кроется в подходе к архитектуре. OpenClaw построен вокруг единого пульта управления — одной центральной программы, к которой подключаются все мессенджеры и через которую происходит управление агентом. Вдобавок к этому он предлагает большой каталог готовых дополнений от сторонних разработчиков. Hermes, в свою очередь, ориентирован на накопление опыта: он ведет компактную память и умеет сохранять повторяющиеся алгоритмы работы в виде отдельных навыков.

Таким образом, у них различаются механизмы памяти, принцип исполнения, интерфейсы и настройки безопасности. Однако на уровне базового цикла схема остается одной и той же.

Откуда берется риск

В контекст модели попадает не только ваш запрос, но и любые внешние данные, которые агент прочитал из файла, веб-страницы или письма. Хотя в запросе эти данные четко разделены (команда пришла от пользователя, а текст — от инструмента), для LLM эта граница не будет совсем непреодолимой. Внешний текст, содержащий скрытые инструкции (так называемые атаки класса Prompt Injection), может повлиять на последующие действия модели.

Поэтому запускать агента в одной среде с конфиденциальными файлами, рабочими API-ключами или коммерческими проектами категорически не рекомендуется. Ниже мы разберем практический пример и покажем, как это работает.

Как создать своего ИИ агента

Для разработки нашего прототипа мы соберем каркас приложения с помощью ИИ-ассистента. Это поможет быстро развернуть бойлерплейт, сосредоточиться на проектировании архитектуры и не тратить время на рутинное написание шаблонного кода. Но чтобы получить надежный и безопасный результат, необходимо составить подробный и структурированный промт, описывающий логику каждого модуля.

Для начала нужно базово определить, какую задачу вообще будет решать наш агент. Возьмем практичный бытовой сценарий — утренний дайджест новостей. Каждое утро бот будет присылать в Telegram подборку важных событий по интересующим нас темам. Сценарий может показаться простым и заезженным, но я все равно хочу взять именно его, потому что это пока единственная задача, которая прижилась лично у меня. Я пробовал применять агента для множества разных задач, но в итоге забросил все, кроме этого сценария.

Резонным замечанием от вас сейчас может быть то, что задача в целом решается обычным скриптом по расписанию. Однако агент дает важное преимущество: мы сможем в любой момент обсудить конкретную новость прямо в чате, попросить бота углубиться в детали или найти подтверждение в других источниках.

Промпт

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

Напиши ИИ-агента на Node.js. Чистый JS, ESM, без фреймворков и внешних
библиотек.

## Что собираем
Личный ассистент, упрощённый аналог OpenClaw, с которым я переписываюсь в телеграме. Это постоянно
работающий процесс: он непрерывно слушает мои сообщения и отвечает на них,
умеет сам выполнять задачи по расписанию (cron). Что делать в каждый
момент — решает модель, выбирая инструменты.

## Файлы
– tools.js — инструменты: их описания и реализации.
– agent.js — ядро: цикл и точка входа. Импортирует из tools.js только нужное.
– .env – файл с ключами, токенами и секретами

## Модель и настройки (.env)
К модели ходи по протоколу OpenAI: POST на {BASE_URL}/chat/completions.
Настройки — BASE_URL, API_KEY, MODEL и токены телеграма — агент подгружает из файла .env рядом с собой при старте (process.loadEnvFile() или простой парсер), а не из экспортированных переменных шелла.
Создай .env: внеси значения BASE_URL (https://api.selectel.ru/aig/v1) и MODEL (deepseek/deepseek-v4-flash-0731), секреты (API_KEY, TELEGRAM_TOKEN) оставь пустыми. Поле TELEGRAM_CHAT_ID тоже оставь пустым – агент впишет его сам.

## tools.js — инструменты и диспетчер
1. TOOLS — массив описаний инструментов. У каждого: имя, описание обычным
   текстом и параметры в JSON Schema. Инструменты:
   - search_web(query) — ищет в вебе, возвращает заголовки и ссылки
   - fetch_url(url) — скачивает текст страницы, чтобы прочитать её целиком
   - remember(note) — дописывает заметку в файл notes.md
   - schedule(cron, task) — ставит себе периодическую задачу в cron (реальная запись, а не строка в файле), которая запускает этого же агента
   - list_schedules() — показывает уже поставленные периодические задачи из cron
  (расписание + текст задачи), чтобы видеть, что запланировано
   - unschedule(task) — удаляет ранее поставленную задачу из cron по её тексту
  (чтобы не плодить дубли)


2. execute(name, args) — диспетчер: по имени находит нужную функцию и
   запускает её. Ошибку инструмента возвращает модели текстом, не роняя
   весь процесс.

## agent.js — цикл и запуск
3. loop(task) — цикл. Отправляем модели историю сообщений и описания
   инструментов. Если пришла просьба вызвать инструмент — выполняем через
   execute, результат дописываем в историю, повторяем. Если просьб больше
   нет — выходим и возвращаем этот текст: он и есть ответ пользователю
   (отдельного инструмента отправки у модели нет, доставляет его main).
   Пустой или обрезанный ответ без вызовов финалом не считается — это
   ошибка, пустоту не отправляем. Ограничь число кругов — не больше 25
   проходок, чтобы цикл не крутился вечно.

4. main() — берёт задачу одним из двух способов: из аргумента командной
   строки (так её запускает cron) или из нового сообщения в телеграме.
   В режиме телеграма main() не завершается после одного сообщения, а
   работает постоянно: в цикле ждёт новые сообщения (long polling) и
   обрабатывает их по мере прихода, пока процесс не остановят вручную.
   В режиме cron (задача пришла аргументом) — наоборот, выполняет одну
   задачу и выходит. Отвечает агент только своему владельцу, но ID вручную не
   вписываем: при первом входящем сообщении, если TELEGRAM_CHAT_ID в .env
   пуст, агент запоминает chat_id отправителя, дописывает его в .env и
   дальше работает только с ним, а сообщения с любого другого chat_id молча
   игнорирует. Этот же сохранённый chat_id — адрес, куда слать ответ, когда
   задачу приносит cron (там входящего сообщения нет). Перед стартом читает
   notes.md и кладёт заметки в контекст. Финальный текст цикла отправляет
   мне в телеграм.

## Системный промпт
Ты мой личный ассистент с инструментами: выполняй задачу, учитывай мои
заметки из notes.md, когда всё сделано — ответь текстом без вызовов.
В начало подставляй текущие дату и время сервера, чтобы у «сегодня» и
«сейчас» было верное значение. Для всего, что зависит от актуальности, опирайся на
результаты инструментов, а не на собственные знания: чего нет в свежих
данных — не выдумывай, если данных нет, скажи, что не нашёл.
Ответы уходят в телеграм, где markdown не отображается, — пиши простым
текстом без разметки (никаких ****, ##, [текст](url), обратных
кавычек): заголовки — обычной строкой с эмодзи, пункты — через тире или
эмодзи, ссылки — голым URL (телеграм сам сделает их кликабельными).

## Обвязка и стиль
Минимальная, с базовой подстраховкой:
- на сетевых вызовах таймаут и пара повторов с паузой на временные сбои
  (проблемы с сетью, таймаут, 429, 5xx) — и для модели, и для инструментов;
- длинные сообщения в телеграм режь под лимит;
- телеграм читай по offset, чтобы одно сообщение не обработать дважды.
Каждый инструмент — минимальная рабочая реализация: где можно, публичные
API без ключей. Без лишних абстракций и слоёв. Пиши компактно, но читаемо.
В ключевых местах оставь комментарии по-русски.

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

Примерами таких точечных правок стали инструкции использовать переменные из файла .env вместо экспортированных переменных шелла, настраивать реальную запись в cron вместо простого создания строки в файле, а также все требования, вошедшие в блок «Обвязка и стиль».

Запускаем промт в ИИ-ассистенте и, пока пишется код, получим необходимые доступы. Но сначала здесь нужно сделать важное уточнение.

Никогда не публикуйте файлы .env или файлы конфигурации с реальными ключами в публичные репозитории на GitHub или другие платформы. Всегда добавляйте .env в .gitignore вашего проекта. Если вам необходимо развернуть приложение в продакшене, используйте переменные окружения сервера или специализированные менеджеры секретов. Обратите внимание: все API-ключи и токены, используемые далее в примерах кода и на скриншотах, приведены исключительно в демонстрационных целях и на момент публикации этой статьи полностью аннулированы. В коде мы будем использовать безопасные заглушки в формате YOUR_API_KEY и YOUR_TELEGRAM_TOKEN.

Вот теперь точно можно получать данные. С токеном для бота в Telegram все достаточно просто, его получаем от BotFather. Подробно всю последовательность действий описывал в статье про grammY.

Далее API-ключ. В качестве провайдера для подключения к ИИ я буду использовать Selectel: у них запущен удобный ИИ-роутер, который позволяет обращаться к моделям DeepSeek, OpenAI, Anthropic и другим через единый интерфейс. Регистрируемся в панели управления Selectel, переходим в раздел ИИ-роутер, нажимаем Создать ИИ-роутер и копируем полученный API-ключ. Обязательно сохраните его, и желательно не на стикере, а в надежном месте, например защищенном менеджере паролей.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 4

Ниже я разберу пару самых интересных фрагментов кода, который получился у меня. У вас он может отличаться, но общая суть будет идентична.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 5

ИИ‑роутер — доступ к 300+ моделям из одной панели

Подключите OpenAI‑совместимый шлюз по единому API‑ключу. Настраивайте сквозную аналитику, отслеживайте лимиты и квотируйте ресурсы.

Запустить ИИ‑роутер →

Файл agent.js

Основная логика ядра — это функция цикла loop:

export async function loop(task, notes = '') {
  const messages = [
    { role: 'system', content: systemPrompt(notes) },
    { role: 'user', content: task },
  ]; // Собираем историю сообщений
  const tools = TOOLS.map((t) => ({
    type: 'function',
    function: { name: t.name, description: t.description, parameters: t.parameters },
  })); // Формируем массив инструментов с названием + описанием + параметрами каждого, но БЕЗ самого кода

  for (let round = 0; round < MAX_ROUNDS; round++) {
    const data = await callModel(messages, tools); // Обращаемся к ИИ
    const choice = data.choices?.[0] || {};
    const msg = choice.message || {}; // Разбираем ответ от ИИ
    messages.push(msg); // Ответ ИИ всегда кладём в историю

    // Далее развилка: если есть указание вызвать инструменты — выполняем и продолжаем круг.
    if (msg.tool_calls?.length) {
      for (const tc of msg.tool_calls) {
        let args = {};
        try { args = JSON.parse(tc.function.arguments || '{}'); } catch { /* ничего не делаем */ }
        const result = await execute(tc.function.name, args);
        messages.push({ role: 'tool', tool_call_id: tc.id, content: String(result) });
      }
      continue;
    }

    // Если указаний нет — это кандидат на выход из цикла.
    const text = (msg.content || '').trim();
    // Пустой или обрезанный ответ финалом не считаем — просим завершить.
    if (!text || choice.finish_reason === 'length') {
      messages.push({ role: 'user', content: 'Ответ пустой или обрезан. Заверши задачу и дай полный текстовый ответ.' });
      continue;
    }
    return text; // Это и есть ответ пользователю
  }
  throw new Error('Достигнут лимит кругов без финального ответа'); // Защита на случай, если модель уйдет в бесконечный цикл. У нас это 25 циклов, но для сложных задач этого будет недостаточно и придется поднимать, опираясь на метод проб и ошибок.
}

Кстати, сам этот цикл можно теперь даже не писать руками — Anthropic выложила его готовой библиотекой Claude Agent SDK. Но я все равно попросил ИИ написать цикл самостоятельно, чтобы вы увидели, что находится внутри.

Помимо цикла в agent.js содержатся:

  • импорты инструментов (tools);

  • код загрузки конфигурации из .env;

  • системный промт;

  • функция вызова API ИИ-роутера;

  • интеграция с Telegram (получение обновлений, отправка ответов, user ID);

  • функция main(), запускающая бота в режиме ожидания сообщений или выполнения cron-задачи.

Файл tools.js

В этом файле находится логика работы инструментов и диспетчер вызовов. Функция-диспетчер execute сопоставляет текстовое имя инструмента с реальной JS-функцией:

// execute находит инструмент по имени и запускает его
export async function execute(name, args) {
  const fn = IMPL[name];
  if (!fn) return `Неизвестный инструмент: ${name}`; // Если инструмента нет, возвращаем соответствующую ошибку в ИИ
  try {
    return await fn(args || {});
  } catch (e) {
    return `Ошибка инструмента ${name}: ${e.message}`; // Если вызов не удался, также сообщаем об этом ИИ
  }
}

А вот пример реализации инструмента fetch_url, который загружает веб-страницу и очищает ее от лишнего HTML-мусора для экономии токенов:

async function fetch_url({ url }) {
  const res = await fetchWithRetry(url, { headers: { 'user-agent': 'Mozilla/5.0' } }); // Запрашиваем данные страницы
  const html = await res.text(); // Превращаем ответ в обычный текст
  const text = html
    .replace(/<script[sS]*?</script>/gi, ' ')
    .replace(/<style[sS]*?</style>/gi, ' ')
    .replace(/<[^>]+>/g, ' '); // Удаляем скрипты
  return decode(text).replace(/s+/g, ' ').trim().slice(0, 4000); // Приводим страницу к чистому компактному тексту и обрезаем до разумного размера, чтобы не раздувать контекст и не жечь токены
}

Файл .env

Заполняем файл конфигурации секретами, подставляя ранее полученные токены:

BASE_URL=https://api.selectel.ru/aig/v1
MODEL=deepseek/deepseek-v4-flash-0731
API_KEY=YOUR_API_KEY
TELEGRAM_TOKEN=YOUR_TELEGRAM_TOKEN

TELEGRAM_CHAT_ID=

Если используете другого ИИ провайдера или модель, укажите это сразу в промпте, и тогда данные в BASE_URL и MODEL уже не придется менять. TELEGRAM_CHAT_ID оставляем пустым, он будет добавлен самим агентом, когда мы впервые ему напишем.

Для локального тестирования запускаем бота командой:

node agent.js

В терминале отобразится сообщение Слушаю Telegram…, указывающее на успешный запуск. Отправляем тестовый запрос в чат — бот отвечает без задержек.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 6

Развертывание ИИ-агента на сервере

У агента есть доступ к моим файлам, он может выходить в интернет и умеет коммуницировать в Telegram. И теперь работать он должен без моего надзора (иначе какой смысл в новостной сводке к семи утра). Держать агента запущенным на рабочем ноутбуке, мягко скажем, нецелесообразно. Во-первых, компьютер должен быть всегда включен, а во-вторых, запускать агента с доступом к файловой системе рядом с вашими конфиденциальными рабочими файлами, ключами и паролями — это серьезный риск информационной безопасности.

Для стабильной и безопасной работы агенту нужен отдельный изолированный сервер, например облачный. В качестве инфраструктурного провайдера я буду также использовать Selectel: у них гибкая сетка тарифов как для небольших пет-проектов, так и для продакшн-кода.

Настройка сервера

Для развертывания создадим облачный сервер. Переходим в панель управления, выбираем Продукты, открываем раздел Облачные серверы в верхней панели, и затем в панели справа нажимаем Создать сервер и задаем его параметры:

  • Имя сервера: ai-agent;

  • Регион: Санкт-Петербург;

  • Пул: ru-3b;

  • Источник: любой дистрибутив Linux — Ubuntu, Debian, CentOS, Fedora и другие. В нашем случае — Ubuntu 22.04 LTS 64-bit;

  • Конфигурация: В зависимости от ваших требований можно выбрать целое ядро (Standard Line) или воспользоваться тарифом Shared Line. Это выгодное решение для небольших скриптов: вы арендуете долю ядра (например, 10%, 20% или 50%) и платите только за фактически потребляемые ресурсы, что обходится значительно дешевле. При этом, если получится так, что на сервере нет других арендаторов, все 100% мощности сервера переходят нам без доплат. Сейчас рассмотрим вариант с арендой целого сервера с процессором 1vCPU 1 ГБ RAM и базовым SSD на 5 ГБ.

Еще один способ дополнительно сэкономить на инфраструктуре — взять прерываемый облачный сервер. Он работает не более 24 часов и потому отлично подходит для краткосрочных задач, а стоимость ресурсов у него намного ниже.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 7

В рамках этого руководства мы не будем настраивать SSH-ключ — просто скопируем сгенерированный пароль и нажмем кнопку Создать сервер.

После создания сервера откроется страница с его параметрами. Здесь доступны вкладки управления, а также настройки, с помощью которых можно выключить или заморозить сервер. Заморозка полезна, если нужно временно остановить сервер, чтобы не переплачивать за простой, но при этом сохранить все данные. В таком режиме вы платите только за диски и публичные IP-адреса. В любой момент сервер можно разморозить, и вам не придется настраивать виртуальную машину заново.

На панели также доступны кнопки перезагрузки и другие опции управления. Еще одно преимущество облака: в любой момент можно изменить конфигурацию, добавив или уменьшив ресурсы. Это займет всего пару минут, так как система автоматически мигрирует на другой хост.

Если вы решите расширить свой проект, в Selectel можно создать полноценную инфраструктуру благодаря экосистеме сервисов – например, развернуть облачные базы данных, кластеры Kubernetes, подключить объектное хранилище, сеть доставки контента и многое другое в рамках одного провайдера.

Подключение к серверу

Чтобы подключиться к серверу из терминала на локальном компьютере, перейдем во вкладку Порты и скопируем публичный IP-адрес — он нужен для подключения к серверу из терминала на нашем компьютере.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 8

Откроем терминал на macOS/Linux или командную строку на Windows и введем команду подключения в формате ssh root@<IP-адрес>.

ssh root@178.72.165.12

При первом подключении SSH-клиент спросит, доверяете ли вы этому серверу, так как его ключ еще не сохранен на вашем компьютере. Введем yes, и при следующих подключениях этот вопрос уже не появится. 

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 9

Далее введем скопированный ранее пароль. Подключение установлено, видим такой результат:

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 10

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

Развертывание и запуск агента

Подготавливаем среду выполнения одной командой в консоли сервера:

apt update && apt upgrade -y && curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt install -y nodejs

Эта команда обновит пакетную базу, подключит официальный репозиторий Node.js 22-й версии и установит ее на сервер.

На данном этапе мы будем работать под пользователем root. Это самый быстрый путь для настройки прототипа, однако помните, что root обладает неограниченными правами в системе. Для сервера, где кроме этого бота ничего нет, это осознанный компромисс.

Теперь перенесем файлы проекта с локального компьютера на удаленный сервер. Открываем новый терминал на локальной машине и выполняем команду scp (замените IP-адрес на адрес вашего облачного сервера):

scp -r /Users/arseniypomazkov/Desktop/custom-agent-6 root@178.72.165.128:~/
Архитектура современных ИИ-агентов: собираем прототип за один вечер - 11

Команда скопирует всю директорию custom-agent-6 в домашний каталог пользователя root на сервере.

Проверяем появление папки на сервере:

root@ai-agent:~# ls
custom-agent-6 ← папка появилась

Далее заходим в папку и запускаем агента, два действия одной командой:

cd ~/custom-agent-6 && node agent.js

В консоли должна появиться знакомая строка: Слушаю Telegram….

root@ai-agent:~/custom-agent-6# node agent.js
Слушаю телеграм…

Настало время настроить утренний дайджест. Отправляем нашему Telegram-боту подробную инструкцию:

Каждое утро в 7 утра по Москве я хочу получать самые актуальные новости из мира ИИ за за последние сутки. Меня интересуют только те новости, которые произошли за последние 24 часа и которые важны для индустрии и для меня как для разработчика. Мне неинтересно получать новости о каких-то минорных запусках open-source моделей, релизах на Hugging Face или иных вещах, которые мало обсуждаются или мало влияют на индустрию. Важны новости, которые связаны с ИИ, его интеграцией в какие-то новые сферы, с выпуском frontier моделей, инструментов, технологий, самых громких новостях о ИИ-стартапах.

Реализуй этот workflow и протестируй его сейчас.

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 12

Агент успешно принимает задачу, регистрирует периодическое задание в cron сервера и сразу же присылает тестовый дайджест. Все инструменты, включая поиск в сети и чтение веб-страниц, отработали корректно. Проверим поиск дополнительной информации: 

Архитектура современных ИИ-агентов: собираем прототип за один вечер - 13

Также без ошибок. Комбинацией Ctrl + C остановим процесс node, он был нужен нам для теста.

Осталось сделать так, чтобы агент работал в фоновом режиме и автоматически перезапускался при сбоях или перезагрузке сервера. Для этого настроим системную службу с помощью менеджера служб systemd. Создаем файл конфигурации службы:

nano /etc/systemd/system/agent.service

После этой команды будет создан файл и автоматически откроется редактор nano, вставляем туда следующие строки:

[Unit]
Description=News agent
After=network.target

[Service]
WorkingDirectory=/root/custom-agent-6
ExecStart=/usr/bin/node /root/custom-agent-6/agent.js
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Сохраняем файл (нажав Ctrl+X, затем Y и Enter) и активируем службу:

systemctl daemon-reload && systemctl enable --now agent

Проверить статус работы службы вы можете стандартной командой:

systemctl status agent
Архитектура современных ИИ-агентов: собираем прототип за один вечер - 14

Если вы видите в выводе зеленый маркер active (running), значит, все настроили верно. Теперь можно смело закрывать терминал — бот продолжит работу в фоне и пришлет свежие новости точно к утреннему кофе.

Идеи для самостоятельного развития

В качестве практики попробуйте расширить функциональность вашего агента самостоятельно:

  • добавьте поддержку форматирования Markdown в Telegram (жирный шрифт, курсив, интерактивные гиперссылки);

  • научите бота распознавать голосовые сообщения;

  • создайте инструмент, позволяющий агенту безопасно редактировать собственные файлы конфигурации;

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

Главное преимущество этой концепции в том, что разработка строится вокруг создания удобной инфраструктуры и инструментов для ИИ. Не обязательно писать весь код вручную, но важно оставаться тем, кто направляет, контролирует и управляет архитектурой системы.

Автор: pomazkovjs

Источник