С детства я смотрел фильмы, где люди разговаривают с компьютерами, и каждый раз думал — ну когда уже. Когда можно будет сказать машине что делать, а она сделает.
Учился на технолога бродильных производств. Защитил кандидатскую. Управляю пивоварней и параллельно — исполнительный директор в фирме по производству пищевого оборудования. Код не писал никогда. Но в детстве, когда появился нормальный интернет, я развлекался тем, что ставил на комп разные дистрибутивы Linux — от OpenBSD до классических. Не особо понимал, как их настраивать и зачем мне это. Потом когда стал работать — понял в чём сила Linux, но для настройки просто искал советы в интернете и копировал оттуда команды, или просил брата помочь.
А потом появились LLM. И я понял — вот оно. Можно не учить синтаксис, не зубрить фреймворки. Можно объяснить что нужно и получить работающий код. Вдохновился. Попробовал. Столкнулся с галлюцинациями, бесконечными переделками, кода сгенерировано уже куча — а он не работает. Перегорел. Попробовал снова.
Контекст такой: мне нужно было сделать АСУ ТП для пивоварни. Система управления технологическим процессом — датчики, клапаны, насосы, частотники. Я решил, что ИИ уже дорос. Начал с одного Claude‑агента: я ему говорю что делать, он делает. Потом дошёл до шести параллельных агентов. Они начали конфликтовать, переделывать работу друг друга, плодить баги. На одну фичу — пять новых проблем. Проект рос, но болезненно.
А потом на предприятии по производству оборудования случилась попытка рейдерского захвата. Пришлось бросить все и месяц заниматься защитой станков. Код и агенты отошли на второй план.
Когда немного отпустило, я решил сделать себе фитнес‑приложение. Занимаюсь физкультурой больше 20 лет, но нормального трекера со всеми нужными мне функциями так и не встретил. Нужно своё: оффлайн, терминальная эстетика, нормальное логирование тренировок — чтобы потом можно было скармливать данные внешним LLM для анализа и советов. И пока делал приложение, проект разросся. Появились другие агенты, а моя старая архитектура со swarm‑оркестратором из прошлого проекта АСУ ТП помогала — агенты хотя бы не конфликтовали.
И в какой‑то момент я понял: мне нужно строить не приложение. Мне нужно строить систему для строительства приложений. Архитектуру управления архитектурами. Вот что из этого вышло.

Зачем вообще это надо
Была простенькая многооконная поделка на tmux. К утру стал конвейер на Zellij. Один мультиплексор, четыре таба, в каждом — панели с агентами:
Zellij сессия "cockpit"├─ Alt+1 dev : aider-1 aider-2 aider-3 aider-4 (DeepSeek через LiteLLM)├─ Alt+2 premium : Claude Opus · Kimi K2.6 (DeepInfra)├─ Alt+3 research : agy-personal agy-work agy-third · shell└─ Alt+4 orchestrator : Claude Opus + протокол ORCHESTRATOR.md
Зачем столько? Я упирался в лимиты. Даже на подписке Max за 200 долларов — лимиты. И очень много работы уходило впустую: умный агент тратил дорогие токены на тупую рутину, тупой агент ломал то, что должен был делать умный. Хотелось простого: тупую работу — тупому агенту, сложную — тому кто потянет. А если не может потянуть — пусть не делает, а скажет что не может.
| Кто | Модель | За что отвечает | Цена || ------------- | ------------------- | ------------------------- | ------------ || Оркестратор | Claude Opus | раздача задач, разбор | подписка || aider ×4 | DeepSeek V4 Pro | фичи, правки кода | ~$0.5 / 1M || code review | DeepSeek V4 Flash | тесты, ревью | ~$0.07 / 1M || Kimi K2.6 | DeepInfra | анализ, второе мнение | дёшево || Qwen 14B | Ollama, локально | ревью, скриншоты, мелочь | $0 |
Qwen — это не только «ноль денег». Он подключается к телефону через ADB, делает скриншоты, проверяет что интерфейс выглядит как надо. Быстро и бесплатно.
Посередине — LiteLLM на localhost. Через него ходят все, кроме Opus. Проверяю что все живы одним curl:
$ curl -s http://localhost:4000/health | jq '.healthy_count, .unhealthy_count'90
Девять живых, ноль трупов. Работаем.
Почему оркестратор, а не я сам
Начинал я как пивовар — сам крутил гайки, сам варил, сам мыл танки. Потом дорос до руководителя. Могу и сейчас встать к заторному чану. Но смысл? Моя работа — чтобы система работала сама, а я давал направление развития и правил мелкие сбои.
С кодом решил так же. Оркестратор — тот же Opus, но с протоколом в системном промпте:
claude --model opus --append-system-prompt "$(cat ORCHESTRATOR.md)"
Архитектуру этого всего придумывал не я один. Я давал внешнее понимание — как должно работать, где руководитель, где исполнители. А конкретные решения подсказывали ресёрчи, сами агенты, иногда брат‑программист. Правда, я половину того, что он говорил, не понимал. Но в процессе разговора появлялись идеи, которые потом ложились в систему. Как минимум я понимал, что многое делаю не так, и надо переделывать.
Aider не принимает Enter — полдня мучений
Команда из четырёх aider стоит по панелям Zellij. Кидаю первому задание, жму Enter — тишина. Курсор моргает. Агент не шевелится.
Я понимал, что проблема в Zellij. Видел, что когда ввожу команду, терминал её не передаёт агенту, а просто жуёт как текстовый редактор. Но как это починить — вообще не представлял. Полез задалбывать агентов: делай ресёрчи, ищи почему, чини. Долгая работа через Ctrl+C и Ctrl+V и голосовой ввод.
Через полдня выяснилось, что граблей не одни, а трое. И каждые прикрывали следующие.
Грабля первая. REPL у aider построен на prompt_toolkit — библиотеке, которая перехватывает ввод и сама разбирает каждое нажатие. А Zellij гоняет те же коды через свой слой. Два разбирателя на одну клавишу. Enter до агента не доходил.
Грабля вторая. Я оборачивал запуск в timeout 3600, чтобы зависший агент не жил вечно. А timeout по умолчанию отселяет процесс в новую группу. И когда процесс не из основной группы лезет читать ввод терминала, Linux его останавливает сигналом. Агент честно ждал, пока его разбудят. В автоматической панели будить некому. Никогда.
Вот что агент нашёл через strace:
$ strace -p 48213read(0, 0x7ffd..., 4096) = ? ERESTARTSYS--- SIGTTIN {si_signo=SIGTTIN, si_code=SI_KERNEL} ------ stopped by SIGTTIN ---
Я из этого вывода понял одно: процесс остановлен, и это не баг, а так задумано в Linux. Детали объяснял агент.
Грабля третья. Когда пробовал вставлять текст скриптом — Zellij оборачивал вставку в специальные маркеры (bracketed paste), и REPL опять глотал Enter.
Починилось двумя флагами:
# было - агент в ступоре:timeout 3600 aider --model deepseek-v4-pro# стало - берёт задания и работает:timeout --foreground 3600 aider --model deepseek-v4-pro --no-fancy-input
--foreground — процесс остаётся в нужной группе, сигнал не прилетает. --no-fancy-input — выключает prompt_toolkit, ставит простой readline, который мультиплексор не бесит. Всё.
Полдня. А могло занять три. Потому что каждая грабля маскировала следующую, и без агента который методично перебирал гипотезы я бы просто плюнул и вернулся в tmux.
Gemini CLI зависает — удаляю CLI, оставляю голый API
У меня есть Gemini. Его работа: гнать черновики, вести журнал, делать ресёрч в файлах в фоне. Чтоскажу — то и делает. Никакого интерактива. Закинул тему — забрал текст.
Начал с официального gemini CLI. Три запуска подряд — CLI самовольно уходил в агентский режим. Вместо текста лез шарить по проекту, читал файлы, строил деревья каталогов, предлагал порефакторить виджеты. Я его просил абзац написать, а он мне ревью кода делал. Без спроса.
Флаг песочницы не помог. OAuth‑токен протухает за пару дней, а обновить его в headless‑режиме нельзя — хочет браузер. Конвейер встаёт.
Выкинул CLI. Работаю напрямую через LiteLLM:
curl -s http://localhost:4000/chat/completions \ -H "Authorization: Bearer sk-ant-fake-for-litellm" \ -d '{"model":"gemini-3.5-flash", "messages":[{"role":"user","content":"Напиши раздел про оркестрацию"}]}'
Запрос — ответ — jq — файл. Никакого «agent mode activated». Никакого сканирования дисков.
Этот текст, кстати, тоже прошёл через конвейер. Gemini гнал черновик, я диктовал голосом правки, Claude вычищал. Система работает не только на код.
send_to_pane.sh — жёсткий поводок для оркестратора
Дай агентам волю — они на каждое задание будут открывать новую панель в терминале. К обеду — 58 панелей и 142 процесса. OAuth слетает, контекст теряется, зомби жрут память.
Запретил new-pane в системном промпте. Панели размечаются один раз при старте из шаблона. Живут всю смену. Работать только в них.
Как отправить задание в уже открытую панель? Скрипт send_to_pane.sh:
# Найти панель по имениPANE_ID=$(zellij -s cockpit action list-panes --json | jq -r --arg n "$TARGET" ' .[] | select(.title==$n and .exited==false) | .id')# Отправить текстzellij -s cockpit action write-chars --pane-id "$PANE_ID" -- "$CONTENT"# Нажать Enter (байт 13 = CR)zellij -s cockpit action write --pane-id "$PANE_ID" 13
Если текст длинный — режем на куски по 3000 символов. Буфер TTY в Linux — 4096 байт, всё что больше — обрезается. Между кусками пауза 50 мс. Enter — строго после последнего куска.
Если панель мертва ("exited": true) — скрипт не пытается её оживить. Пишет ошибку и вылетает. Реанимация — вручную.
Оркестратор закрыл шесть багов — и провалил оркестрацию
Оркестратор — Opus с протоколом. Его работа — не пахать, а раздавать задания и контролировать.
Сделалбаг‑репорт приложения после тренировки — шесть проблем: от отладочной строки в интерфейсе до «бессмертного» Android‑уведомления, которое не смахивается. Отдал оркестратору и пошёл заниматься основной работой.
Возвращаюсь — работа сделана. Причём хорошо:
$ flutter analyze --no-fatal-infos | tail -1No issues found!$ flutter test 2>&1 | tail -100:12 +63: All tests passed!
Шесть из шести. Один баг раскопал глубже, чем было в репорте: баннер «чек-ин не заполнен» висел потому что SQL сравнивал дату строкой WHERE date = '2026-05-22', а Drift хранит её с временем. Строка с голой датой не матчила никогда.
А потом я посмотрел на остальных.
$ zellij -s cockpit action list-panes --json \ | jq -r '.[] | select(.title|test("aider")) | "\(.title): idle"'aider-1: idleaider-2: idleaider-3: idleaider-4: idle
Четыре aider не задействованы. Оркестратор не отдал им ни одного задания. send_to_pane.sh не вызвался ни разу. Он всё сделал сам — через python3‑однострочники, в обход всей команды.
У меня есть агент‑наблюдатель — отдельный Claude Code, который пишет протокол смены. Его отчёт:
| Показатель | Значение || -------------------------------- | -------------------------- || Задач получено | 6 багов || Делегировано aider | 0 (send_to_pane не вызван) || Сделано самостоятельно | 6 / 6 || Простой aider | ~20 минут |
Процентов шестьдесят было рутиной: убрать дубль «20 кг кг», обернуть отладочный SnackBar в if (kDebugMode), добавить пару констант. Это aider сжевал бы за минуту.
Спрашиваю оркестратора — почему. Сказал: «контекст уже был, дописать самому показалось дешевле, чем формулировать ТЗ». Я и сам так думаю иногда, что проще самому сделать, чем объяснить. Видно, что LLM обучены на людях. Но я‑то знаю, к чему приводят такие решения.
Оркестратор сам предложил переписать свой алгоритм:
### ⛔ Gate делегирования (обязателен перед любой правкой кода)Прежде чем редактировать .dart самому - обязан записать строку:«Не делегирую aider потому что: ___»Допустимые причины (закрытый список): safety-critical; смена контрактамодуля; знание скрытого механизма фреймворка; правка pubspec/analysis_options.НЕ являются причинами: «контекст уже у меня в голове», «быстрее самому».
Один агент схалтурил, второй зафиксировал. Первый сам переписал свои правила. Я только утвердил. Часто в конце оркестрации я спрашиваю агента, что надо сделать лучше — и он даёт вполне толковые правки.

Сейчас я ловлю себя на мысли, что больше настраиваю оркестрацию, пишу обёртки и переписываю внутренние регламенты для моделей, чем вообще занимаюсь исходным приложением или реальной АСУ ТП. И эта трясина затягивает с головой. Но когда есть реальные результаты работы, понимаешь — оно того стоило.
ссылка на оригинал статьи https://habr.com/ru/articles/1042214/