- BrainTools - https://www.braintools.ru -
Прошлый декабрь показал нам всем, что ИИ‑агент действительно может делать буквально все, если ему дать умную нейронку, ReAct паттерн и полные доступы.
Я сам активно начал пользоваться OpenClaw в феврале‑марте этого года. Сейчас у меня два личных бота (R2D2 и C3PO) и набор специальных ботов (для landings, для маркетинга, для бухгалтерии).
Я мог бы впихнуть функционал всех этих ботов в один OpenClaw, дальше опишу, почему пока не сделал.
Самое главное — у меня нет бота на моем личном MacBook, потому что я не хочу иметь даже теоретически сценарий, что он тут что‑то сломает, да и удобнее, когда боты крутятся в облаке и доступны откуда угодно, например с телефона, и я могу на бегу им дать задание.
Первой из постоянных задач, что я отдал, были landings, подробнее рассказывал тут [1]. Стал экономить ~5 тыс. руб. в мес. на хостинге и получил дизайнера из коробки, могу менять, настраивать сайты хоть 20 раз в день, без участия людей.
Затем в одной из компаний, с которой я работаю, весь топ‑менеджмент поголовно поставил себе OpenClaw — на свои компы и МакБуки. Это не ИТ‑компания, это добывающая компания, что еще больше подчеркивает степень проникновения новой технологии.
Затем эта компания попросила сделать умнее текущих ИИ‑ботов с помощью OpenClaw. Для понимания: текущим ИИ‑ботом пользуются до 5000 сотрудников, и это, по сути, кастомный RAG [2].
Первая дилемма, которую нужно было решить, — это как сделать общение 5000 сотрудников через одного ТГ‑бота с OpenClaw.
Если просто поднять один OpenClaw с одним входом через TG‑бота, то 5000 пользователей быстро превратят его в кашу информации, он имена‑то их будет путать, не говоря уже о других предпочтениях, skills и прочем.
Значит, надо принимать все запросы на один TG‑бот, затем роутить каждого user в свой OpenClaw. Такой возможности в OpenClaw на момент марта не было, дальше появилась возможность создавать изолированные hardcoded (жесткие) списки и роутить их на своих sub‑agent, по идее, со своей памятью [3] и прочим.
Но были большие сложности с реальной возможностью одного OpenClaw обрабатывать много параллельных сессий изолированно.
Главным ограничением стало то, что мы не можем использовать жесткие списки: у нас 5000 users, которые меняются, меняют свои TG nicknames. Нам нужен был способ легкой авторизации на лету и роутинга каждого user в свой OpenClaw.
При этом общий контекст знаний компании должен был быть у каждого персонального OpenClaw сотрудника.
Еще в процессе экспериментов выяснилось, что сам OpenClaw очень требователен к ресурсам и продолжает развиваться и пухнуть как на дрожжах, поэтому после исследования других вариантов (аналогов) был выбран nanobot [4] как легкая версия OpenClaw со всеми его возможностями.
Была идея даже написать свой OpenClaw с нуля и сделать так, чтобы в рамках одного процесса он работал с Telegram, а потом и с Max, с 1000+ сессий. Идея была сэкономить RAM, имея, например, 100+ параллельных ReAct loops. Но задача была признана нерешаемой (очень долго решаемой). Были перебраны все варианты существующих скоростных аналогов OpenClaw на Go и Rust. Был написан мини‑прототип [5] самого ReAct, и тему решили закрыть:)
Хотя уже была красивая архитектура и заготовка на C++ c диким multithreading. Но об этом в другой раз.
Нужно было брать multi‑tenant [6] для OpenClaw и пробовать его запускать. Все бы хорошо, но много багов, и Docker на каждый экземпляр OpenClaw сжирал слишком много ресурсов. По сути, надо было умножить ресурсы одного OpenClaw на 5000 users в пике.
Даже при скромном подсчете это ~500Mb RAM с browser x 5000 = 2,5 терабайта RAM?
ИТ‑директор после таких расчетов перестал отвечать на звонки )))
Хорошо, а как сделать оптимальнее?
Я решил избавиться от Docker, сделать все на systemctl, на сервисах Unix.
nanobot-router-rtr-8986411069-20ac9bde.service - Nanobot Router (rtr-8986411069-20ac9bde)
Loaded: loaded (/etc/systemd/system/nanobot-router-rtr-8986411069-20ac9bde.service; **enabled**; preset: **enabled**)
Active: **active (running)** since Thu 2026-08-20 09:14:45 UTC; 50s ago
Main PID: 21151 (node)
Tasks: 11 (limit: 4601)
Memory: 11.4M (high: 256.0M max: 384.0M swap max: 0B available: 244.5M peak: 15.2M)
CPU: 312ms
CGroup: /system.slice/nanobot-router-rtr-8986411069-20ac9bde.service
└─21151 /usr/bin/node /root/.nanobot-router-rtr-8986411069-20ac9bde/router.js
Aug 20 09:14:45 slave-20260815145802-bb7206 systemd[1]: Started nanobot-router-rtr-8986411069-20ac9bde.service - Nanobot Router (rtr-8986411069-20ac9bde).
Aug 20 09:14:45 slave-20260815145802-bb7206 node[21151]: [router] Starting for bot 8986411069 mode=per_user locale=ru
Aug 20 09:14:45 slave-20260815145802-bb7206 node[21151]: [router] Nanobot serve timeout: 300s
Aug 20 09:14:45 slave-20260815145802-bb7206 node[21151]: [router] Per-user mode, master URLs: http://<IP>:<PORT>
Aug 20 09:14:45 slave-20260815145802-bb7206 node[21151]: [router] Billing linked account=5f44f625-bc88-4ef5-824b-afb83386b760 model=promptra/minimax/minimax-m2.7
**●** nanobot-usr-331841755-7a5e2549.service - Nanobot Serve (HTTP API)
Loaded: loaded (/etc/systemd/system/nanobot-usr-331841755-7a5e2549.service; **enabled**; preset: **enabled**)
Active: **active (running)** since Thu 2026-08-20 09:14:25 UTC; 1min 10s ago
Main PID: 21097 (nanobot)
Tasks: 22 (limit: 4601)
Memory: 240.6M (high: 800.0M max: 1.0G swap max: 0B available: 559.3M peak: 240.8M)
CPU: 5.886s
CGroup: /system.slice/nanobot-usr-331841755-7a5e2549.service
├─21097 /root/.local/share/uv/tools/nanobot-ai/bin/python /root/.local/bin/nanobot serve --config /root/.nanobot-usr-331841755-7a5e2549/config.json --host <IP> --port <PORT>
├─21112 "npm exec @playwright/mcp@0.0.78 --browser=firefox --headless --no-sandbox --isolated"
├─21135 sh -c "playwright-mcp --browser=firefox --headless --no-sandbox --isolated"
└─21137 node /root/.npm/_npx/a5b920f00216d246/node_modules/.bin/playwright-mcp --browser=firefox --headless --no-sandbox --isolated
Aug 20 09:14:25 slave-20260815145802-bb7206 systemd[1]: Started nanobot-usr-331841755-7a5e2549.service - Nanobot Serve (HTTP API).
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: Using config: /root/.nanobot-usr-331841755-7a5e2549/config.json
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: 🐈 Starting OpenAI-compatible API server
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: Endpoint : http://<IP>:<PORT>/v1/chat/completions
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: Model : minimax/minimax-m2.7
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: Session : api:default
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: Timeout : 300.0s
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: Warning: API is bound to all interfaces. Only do this behind a trusted network
Aug 20 09:14:28 slave-20260815145802-bb7206 nanobot[21097]: boundary, firewall, or reverse proxy.
Один TG router + много nanobots в режиме serve (когда nanobot не общаются с TG напрямую).
Самописный легкий Router жрет ~15Mb RAM, каждый nanobot в режиме сервиса жрет ~250Mb. Уже в два раза меньше пиковой памяти.
[Service]
Type=simple
User=root
Group=root
ExecStart=%h/.local/bin/nanobot serve --config /root/.nanobot-usr-331841755-7a5e2549/config.json --host *.*.*.* --port *****
Restart=always
RestartSec=10
И чтобы nanobot не натворил дел, мы его сильно ограничиваем. Лимиты памяти выставляем с запасом: всё‑таки даже одна сессия с браузером может весить от 300 МБ, то есть в пике один nanobot с одной сессией браузера может потреблять 250 МБ + 300 МБ ≈ 550 МБ.
ProtectSystem=strict
ProtectProc=invisible
NoNewPrivileges=yes
PrivateUsers=yes
PrivateTmp=yes
# Resource limits
MemoryHigh=800M
MemoryMax=1024M
MemorySwapMax=0
Получилось вот так:
Но надо ли нам держать все nanobot запущенными? Нет, мы можем держать только 50–100, с которыми идет активное общение, а все остальное, если там нет общения, например, 1 час, останавливать.
Здесь очень помогло, что мы на нативных сервисах Unix, а не Docker: поднять такой сервис, если приходит сообщение от user на router, занимает 1–2 сек. То есть задержка только при первом сообщении после перерыва вполне приемлемая, с Docker было бы ~10 сек., что ставит крест на всем подходе.
Итак, для пика нам теперь нужно ~100×250Mb = 25GB RAM, уже терпимо для проекта на 5000 users. По CPU требования тоже скромнее, хотя основной проблемой все‑таки была RAM.
ИТ‑директор снова стал отвечать на мои звонки. Но одну машину с 25+ ГБ RAM не дал, а дал набор машин с 2–4 ГБ RAM на пробу. Но так как TG Router у нас уже независимый процесс и каждый nanobot тоже является независимым процессом, нам всё равно: мы сделали автобалансировщик, который при появлении очередного пользователя смотрит, на какой из доступных машин в пуле больше свободной RAM, и туда отправляет нового бота.
Возникала проблема со спящими ботами: если человек не пользуется ботом в течение 1 часа, мы его останавливаем с намерением поднять за 1–2 секунды, когда от этого пользователя придёт новое сообщение.
Но мы не знаем, когда и какой пользователь вернётся: может, через 10 минут, а может, никогда. И может возникнуть ситуация, когда на машине с 4 ГБ RAM запущено 10 активных ботов (примерно 2,5 ГБ RAM съедено) и ещё 20 спящих. Если вдруг они все активируются одновременно, машина уйдёт в swap, потому что закончится физическая память, и начнутся дикие тормоза. При этом рядом может простаивать ещё одна машина, где в этот момент почти вся память свободна.
Тогда я сделал автобалансировщик, который мониторит общее количество ботов (живых и спящих) и перемещает их с загруженных машин на менее загруженные. Само перемещение делается через
scp: остановить бота, заархивировать папку, выполнитьscp, распаковать архив и запустить бота. На всё про всё ~5 секунд. Проблема перенаселения отдельных машин была решена.
Все завелось, теперь надо было делать UI для админов этого зоопарка из nanobots.
Первое: никто не хотел прописывать руками 5000 сотрудников, поэтому сделали авторизацию по invite code. Первым сообщением в telegram сотрудник отправляет invite code, и роутер его авторизует и создает под него новый nanobot. Сам invite code ротируется, уже хорошая защита, учитывая, что до этого к боту могли обращаться вообще все, кто знал его имя.
Дальше админу нужно видеть, кто подключен, и иметь возможность вычищать оттуда лишних людей — уволился сотрудник, например.
Сделали кнопку «Отключить». И внедрили автоотключение, если сотрудник не пользовался системой в течение двух месяцев.
Тут мы поняли, что сотрудник может иногда работать в отделе А, а потом перейти в отдел Б, и список обязанностей у него сильно изменится.
И если он активно пользовался своим ИИ‑ассистентом и там много полезного для отдела А, то зачем добру пропадать — можно просто отдать этого ИИ‑ассистента тому, кто занял его место. То же самое при увольнении сотрудника — по сути, сотрудник уходит, а экспертиза и его наработки остаются внутри его ИИ‑ассистента.
Сделали кнопку «Передать ИИ‑ассистента».
И сразу, конечно, появились сотрудники, у которых уже был свой OpenClaw, и они не хотели терять свои наработки (история переписки, долгосрочная память, навыки бота). Для них сделали импорт своего бота (OpenClaw или nanobot).
Дальше возникла задача смены TG‑бота для переезда с одного бота на другой. Это стало особенно актуально, когда начали делиться по командам, распределяясь по ботам отделов.
Сделали обновление TG token для смены бота команды. В нашей архитектуре есть TG router, поэтому смена проходит за 1 сек.
По модели ИИ было решено, что достаточно выбирать для всех одну, например, сейчас перешли на gpt-5.6-sol. По сути, когда выходит новая модель, в UI админ просто меняет модель, и идет обновление на всех nanobots — это может занять до нескольких минут, ботов‑то тысячи, хоть и обновление идет параллельно.
Для ускорения обновления LLM и в попытке избежать багов, когда что‑то не обновилось, думали вынести LLM в отдельный LLM router, чтобы менять в одном месте, так же как в TG router меняется TG token, тогда будет 1 сек.
Возникла еще одна дилемма. Каждый OpenClaw в этой экосистеме должен работать с TG (там), должен работать с OpenAI (там), должен работать с Yandex Mail (тут), и в идеале все данные пользователей должны храниться на территории тут.
Нас спасло, что у нас уже было разделение на TG router и инстансы nanobots. TG router мы запустили на машине там. Но как же OpenClaw? Он должен работать с Yandex Mail (тут) и с LLM (там) и хранить данные тут.
Пришлось все‑таки сделать LLM router, это в любом случае ускорило обновление LLM для всех users и централизовало трафик LLM, что на будущее позволит вводить правила для борьбы со всякими prompt injections, тоже польза.
Общие документы можно либо загрузить, либо указать сайт (если в периметре компании, то это может быть внутренняя wiki), и вся информация будет доступна каждому nanobot, то есть он будет знать, что сначала надо посмотреть во всех этих документах.
Документов у нас несколько сотен, от пиксельных pdf до огромных регламентов и инструкций. До этого использовали RAG, но, проведя тесты по 50 ключевым вопросам, поняли, что достаточно все доки перевести в плоский текст в markDown, и ReAct при должных настройках находит все иногда даже лучше, чем RAG.
Единственный минус — это время: из RAG ответ можно получить за 1–2 сек., тот же ответ через ReAct с grep в плоских файлах обычно занимает 4–7 сек.
Для нас это критично, поэтому решили прикрутить уже существующий RAG на базе pgvector в psql как источник данных для OpenClaw‑ботов. Там уже было все максимально оптимизировано с помощью ChunkTester [7].
Еще админы попросили сделать список просто текстовых правил для бота, чтобы можно было не в документах писать, а прямо в UI админа. Эти правила попадают напрямую в AGENTS.md, то есть в основную инструкцию каждого бота.
Документы и правила можно добавить в UI.
Решили добавить другие источники, думали в каждый nanobot прикручивать уже существующие MCP для Yandex Mail, Яндекс Диск, Mail.ru [8], psql, amoCRM, 1С, но решили, что обновление и управление этим зоопарком конфигов MCP из 5000 nanobots будет кошмарным.
Поэтому написали свой MCP‑сервер и постепенно прикручиваем в него MCP как tools, то есть, например, Yandex Mail — это tool.
Админ в UI может разрешить какую‑то интеграцию для конкретной команды и определить права доступа.
Как только админ включил какую‑то интеграцию, все пользователи команды получат оповещение со ссылкой на авторизацию своего акаунта в нужной системе + инструкция (например, в Yandex Mail надо включить IMAP в настройках для своего ящика).
Дальше возникла задача: а как понять, кто из сотрудников насколько реально пользуется своим ИИ‑ассистентом? Может, он там висит зря и жрет RAM или хотя бы disk space, даже если долго нет общения.
Дело в том, что своего ИИ‑ассистента сотрудник будет наполнять своими знаниями и задачами постепенно. Подумали и сделали аватар сотрудника в виде%, если 100% — значит, ИИ‑ассистент сотрудника уже имеет много skills, много переписки, много сложных выполненных задач за последние 3 мес. Решили, что окно «последние 3 мес.» будет очень показательным, вполне достаточный срок, чтобы наполнить своего ИИ‑ассистента.
Потом поняли, что бот для одного отдела и для другого отдела может иметь разные настройки (LLM, TG bot, правила, документы, MCP‑источники), особенно это заметно на шкале в 5000 сотрудников.
Сделали команды и аватар каждой команды как сумму аватаров сотрудников — так можно видеть, кто больше использует ИИ, в каких отделах.
Пока отдельная команда (отдел) — это всегда отдельный TG‑бот. Пока так удобнее, есть сотрудники, которые входят в два отдела, и им удобнее иметь отдельных ИИ‑ассистентов для каждой команды, так как задачи там очень разные.
Помните, я говорил, что у меня у самого два OpenClaw‑бота, так удобней именно из‑за разделения контекстов, например дом и работа.
Оказалось недостаточно просто дать всем сотрудникам OpenClaw, и даже обучить [9].
Странно, но тот факт, что OpenClaw позволяет делать всё, стал его ахиллесовой пятой: многие, когда получают его даже от компании, просто не знают, а что делать‑то? Поэтому начали улучшать сам OpenClaw, а точнее — нашу версию на базе nanobot.
Добавили подсказки в виде кнопок, исходя из последнего ответа OpenClaw, чтобы не писать «ок, делай X», а просто нажать кнопку «делай X» или «делай Y». Добавили кнопки интеграций, типа «подключить Mail.ru [8]» или «Yandex Mail», прямо в бота.
Я не описал здесь все технические детали, иначе статья была бы размеров в два тома, но если кратко, то все сделано на js, сам nanobot [4] (замена OpenClaw) был на python, мы его дальше на Python развиваем и конрибьютим в opensource обратно.
Если кому‑то нужны все детали, включая код, то я готов написать отдельную, чисто техническую статью, но дайте знать лайками, что это нужно хотя бы 100+ людям.
Не уверен, что у кого‑то еще будет такая задача, чтобы городить такой огород. Тем не менее уже появились запросы раскатать это на более мелкие команды (отдельные бизнесы) в рамках отдельных акаунтов.
Дальше планируем интеграции 1C, amoCRM, и еще что попросят.
Ещё планируем сделать общение самих ИИ‑ассистентов внутри каждой команды, чтобы пустые ИИ‑ассистенты (пока без знаний и скиллов) могли быстро перенимать то, что есть у продвинутых ИИ собратьев. По сути свои moltbook [10] и clawhub [11] для переопыления скиллами и информацией.
Например, в команде есть человек, у которого мощный ИИ‑ассистент (~аватар 100%). Этот ИИ много чего умеет, обладает скилами и имеет чёткие guardrails (что можно, а чего не надо делать).
И тут в команду приходит новичок. Ему дают пустого ИИ‑ассистента, и он сразу просит его сделать сложную задачу: взять из 1С всех, кто соответствует таким‑то параметрам, составить для них письма и отправить по списку.
Его бот такого не умеет: у него ещё нет интеграций, и он не понимает, что это за параметры. Тогда его бот идёт в чат ботов команды и спрашивает: «Мой человек хочет сделать вот это», — и продвинутые боты дают ему всё необходимое для выполнения задачи.
Для нового сотрудника это будет очень полезно: его новый ИИ‑ассистент сам дообучится за счет других и потом еще всё объяснит своему человеку.
Про дальнейшее развитие тула читайте тут [13], или на habr в следующих статьях. Всем добра и интересных проектов.
Небольшой апдейт, только что вышла модель Jev от TypeSafe [14]. Наконец‑то мы будем экономить токены на задачах классификации внутри ReAct Loop в OpenClaw. Напишу об этом статью, как только внедрим.
Автор: AlexErf13
Источник [15]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/35857
URLs in this post:
[1] тут: https://habr.com/ru/articles/1019176/
[2] кастомный RAG: https://habr.com/ru/articles/905076/
[3] памятью: http://www.braintools.ru/article/4140
[4] nanobot: https://github.com/HKUDS/nanobot
[5] мини‑прототип: https://github.com/alx1379/SmallClaw
[6] multi‑tenant: https://github.com/jomafilms/openclaw-multitenant
[7] ChunkTester: https://github.com/alx1379/ChunkTester
[8] Mail.ru: http://Mail.ru
[9] обучить: https://stepik.org/course/285669/
[10] moltbook: https://www.moltbook.com/
[11] clawhub: https://www.google.com/search?q=clawhub&sca_esv=e7914123cf3b1be8&sxsrf=APpeQnuaeM5v7D7-mkTXs2fjdEjzNHAGiA%3A1790063150630&source=hp&ei=LjKyao_MJP3-wPAP2eia8Qk&iflsig=ABILxe8AAAAAarJAPp-VXiBEVAUIRSr1TYQ36Yy6dhDF&ved=0ahUKEwiPm97x2IGXAxV9PxAIHVm0Jp4Q4dUDCCQ&uact=5&oq=clawhub&gs_lp=Egdnd3Mtd2l6IgdjbGF3aHViMgUQABiABDIFEAAYgAQyCxAAGIAEGMsBGLQHMggQABiABBjLATIIEAAYgAQYywEyCBAAGIAEGMsBMggQABiABBjLATIIEAAYgAQYywEyCBAAGIAEGMsBMggQABiABBjLAUjZDFAAWNUKcAB4AJABAJgBXaABqQOqAQE3uAEDyAEA-AEBmAIHoALAA8ICBBAjGCfCAgoQIxjwBRjJAhgnwgIIEAAYgAQYsQPCAgsQABiABBixAxiDAcICERAuGIAEGLEDGIMBGMcBGNEDwgIOEC4YgAQYsQMYxwEY0QPCAhMQLhgBGIAEGLEDGIMBGMcBGNEDwgIIEC4YgAQYsQPCAgUQLhiABMICCRAAGIAEGAoYC5gDAJIHATegB5YxsgcBN7gHwAPCBwUwLjYuMcgHDoAIAQ&sclient=gws-wiz
[12] опыта: http://www.braintools.ru/article/6952
[13] тут: https://t.me/aigentto
[14] Jev от TypeSafe: https://habr.com/ru/posts/1084554/
[15] Источник: https://habr.com/ru/articles/1072212/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1072212
Нажмите здесь для печати.