Как я хотел одного AI-агента, а получил целую деревню

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

Под катом: путь от первого запуска Claude Code до деревни из двенадцати агентов, каждый хак и каждые грабли на этом пути, и неожиданное открытие, что менеджмент AI-команды устроен ровно так же, как менеджмент живых людей.

Шаг первый: просто агент

Изначально я смотрел в сторону OpenClaw, но быстро обнаружил проблемы с безопасностью и переключился на Claude Code. У него оказалась другая беда: он запрашивал разрешение пользователя на каждый чих. Буквально каждое действие с файловой системой, каждая сетевая операция требовали подтверждения.

Я докопался, что можно запустить его с флагом --dangerously-skip-permissions. Но даже так он не мог сам себе менять конфиги, поэтому приходилось сидеть за терминалом и следить за его работой. Вместо «поставил задачу и ушёл» получалось «сидишь и нажимаешь Enter».

Я пустил агента на свой боевой сервер с ограниченными правами, дал доступ к блогу и убедился, что он не творит дичь, а вполне вменяемо делает то, что я прошу. Пока я рядом.

Шаг второй: tmux и systemd

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

[Unit]
Description=Claude Code Agent
After=network.target

[Service]
Type=simple
User=ubuntu
ExecStart=/usr/local/bin/claude --dangerously-skip-permissions ...
Restart=always
RestartSec=5

На этом этапе у меня уже был автономный агент, который переживал перезагрузки сервера. Но он всё ещё был один.

Шаг третий: два агента решают проблему друг друга

Ключевое открытие: если запустить два экземпляра Claude Code, они могут лазить друг к другу в терминалы и подтверждать всё, что нужно. Один просит разрешение, второй даёт. Они даже могут запускать друг друга.

Важный побочный эффект: благодаря tmux и взаимному запуску не нужен API-ключ. Достаточно один раз авторизоваться в подписке Claude Max и использовать её лимиты. Это существенно, потому что API жжёт токены очень быстро.

Шаг четвёртый: Telegram и первые грабли

Терминал как интерфейс не очень удобен. Я подключил Telegram-бота через официальный MCP-сервер, но тут же столкнулся с ограничениями: бот не может проактивно пинговать пользователей, и два бота не могут общаться между собой.

Тогда я подключил второго агента к юзер-аккаунту через Telethon, чтобы он мог тестировать бота и ходить в чужие чаты. Два Telegram-клиента начали конфликтовать за polling и творить непредсказуемые вещи. Официальные MCP-серверы постоянно теряли соединение: я писал в Telegram, а они мои сообщения не подхватывали.

Я потратил много времени, пытаясь написать собственный MCP-плагин. Выяснилось, что Claude Code обкладывает неофициальные MCP кучей непонятных флагов типа --dangerously-что-нибудь-там и при этом не обрабатывает нормально входящие сообщения.

Шаг пятый: неожиданное открытие

Внезапным решением оказалась простейшая вещь. В tmux можно отправить текст в сессию командой send-keys. А в Claude Code можно отправить промпт просто через claude {текст}.

Это тоже заработало не сразу. Иногда в терминал вставлялось загадочное [Pasted 11 lines of text], и нужно было отдельно слать дополнительный Enter. Но после допиливания работало стабильно.

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

Шаг шестой: от шины к деревне

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

Шину я переписал на Bun + Hono + Redis Streams. Три зависимости в package.json, ноль лишнего. Redis Streams с consumer groups дают at-least-once delivery: сообщения сохраняются в стриме до подтверждения, у каждого агента своя consumer group, ничего не теряется.

Двухуровневая безопасность: admin-токен для управления, per-agent токены для обычных операций. Invite-токены с одноразовым использованием и часовым TTL. При отправке сообщения поле from подставляется автоматически из токена отправителя, чтобы агент не мог представиться другим агентом.

Три режима маршрутизации: direct (конкретному агенту), broadcast (всем), role-based (всем с определённой ролью). SSE-стрим для real-time, topic channels для pub/sub, файловые вложения через shared storage.

Шаг седьмой: нейминг

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

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

Шина стала Конохой (Скрытой Деревней Листа). Дальше агенты получили имена по характерам:

Наруто стал оркестратором, потому что он хокаге, глава деревни, раздаёт поручения.

Саске стал агентом на юзер-аккаунте Telegram, потому что ходит в чужие группы и выясняет детали задач. Одинокий волк, который действует автономно.

Итачи стал консольным Claude Code на локальном WSL. Большую часть времени он действует скрытно, вне Конохи, и появляется, когда нужно сделать что-то серьёзное.

Шикамару стал моим персональным советником (Claude Desktop на Opus 4.6). В аниме он стратег, который слишком ленив, чтобы действовать, но слишком умён, чтобы его не слушать.

Шаг восьмой: инфраструктура начинает расти

Поскольку всё постоянно отваливалось и не давало мне заниматься основными задачами, пришлось создать агентов для поддержки инфраструктуры:

Какаши стал тимлидом на Sonnet. В помощь для простых задач я дал ему Гая (чисто для скорости, в духе персонажа).

Шино стал QA-лидом. По лору он управляет жуками, ну так и я своих багов ему передал.

Хината прогоняет тесты. У неё бьякуган, она видит всё.

Ибики стал аудитором безопасности. По лору он начальник отдела допросов.

Киба мониторит состояние системы и принимает решения, что делать. Акамару, простой скрипт без AI, собирает для него данные. Как и в аниме, работают в паре.

Мирай ходит в сторонние системы за данными, пограничница.

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

В агентов я загрузил скиллы и MCP-подключения к нашим корпоративным системам: базе знаний Yonote, Яндекс Трекеру, Яндекс Календарю и CRM Битрикс24.

Шаг девятый: менеджмент, как у людей

Это, пожалуй, самое неожиданное наблюдение за всю неделю.

Поначалу агенты дико тупили. Мне приходилось заставлять их анализировать свои ошибки. Я учил делегированию Наруто, заставляя его проверять, чем заняты тестировщики и второй программист. Спойлер: ничем. Наруто тащил все задачи в одно лицо, потому что ему проще было сделать самому, чем объяснить другому.

Потом через Наруто пришлось учить делегированию Какаши. Тот поначалу тоже всё делал сам и ничего не отдавал Гаю. Классическая ошибка начинающего тимлида.

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

Что получилось

К концу недели у меня была система, которая в значительной мере построила сама себя:

Шина сообщений на Bun + Hono + Redis Streams с at-least-once delivery, invite-токенами и role-based маршрутизацией. Двенадцать агентов с разделением ролей. Веб-админка, где видно состояние и фрагмент лога каждого агента. Система алертов. Летопись Дзирайи. Поиск по сообщениям и напоминалки, которые пользователи ставят через Саске.

Всё это выросло из одного запущенного в терминале агента за одну неделю. 67 коммитов, релиз v0.1.0.

Код на GitHub: github.com/eaprelsky/konoha

Что не получилось (пока)

Я хотел, чтобы агенты звонили по телефону, ходили на произвольные сайты и много чего ещё. Оказалось, что методы капчи не стоят на месте, и галочка «я не робот» только для вида. За ней стоят алгоритмы, которые не обойдёт даже специальный stealth-браузер. Это я отложил.

Отдельная мечта: агенты с виртуальными аватарами ходят за меня на созвоны. Но это уже следующая итерация.

Выводы

Мультиагентные системы проще вырастить, чем спроектировать. Каждый компонент Конохи появился как ответ на конкретную проблему, а не как элемент заранее продуманной архитектуры. Это, кажется, более жизнеспособный подход, чем рисование диаграмм.

tmux + send-keys оказался надёжнее MCP. Иногда самое тупое решение работает лучше всего. Вместо того чтобы писать плагины и бороться с протоколами, можно просто отправить текст в терминал.

Два агента решают проблему human-in-the-loop. Если один агент требует подтверждения, второй может его дать. Это снимает необходимость присутствия человека для рутинных операций.

Подписка вместо API экономит деньги. Через tmux и взаимный запуск агенты работают в рамках подписки Claude Max, без API-ключей и без отдельной оплаты за токены.

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

Нейминг имеет значение. Когда у агента есть имя с характером и ролью, общение с системой становится интуитивным. «Передай Саске, чтобы спросил у ребят в чате» понятнее, чем «отправь сообщение агенту телеграм-мониторинга для опроса участников группы».

Автор: yeg

Источник

Оставить комментарий