Симптом и ошибочный диагноз
Инцидент в рое редко приходит с пометкой «проблема планирования». Он приходит как проблема рассуждений. Агент зацикливается, два агента противоречат друг другу, три агента порождают один и тот же артефакт из слегка различающихся промптов — и постмортем дрейфует в сторону модели: планировщик был слишком расплывчатым, субагент неверно понял инструкции, критик был недостаточно критичен.
Разбор трейсов обычно рассказывает другую историю. Цикл находится ниже по потоку от очереди. Один вызов инструмента — медленный поиск, API с ограничением частоты, база данных, решившая пофилософствовать — занимает больше времени, чем таймаут вызывающего. Вызывающий повторяет попытку. Поскольку повтор — это новая задача, а не повторный захват той же единицы работы, он снова ветвится. Агенты-соседи, ожидавшие того же вышестоящего результата, теперь тоже упираются в таймаут и повторяют попытку. Каждая повторная попытка несёт тот же контекст, поэтому стоимость инцидента в токенах растёт сверхлинейно, тогда как объём реальной работы не растёт вовсе.
Качество рассуждений в таких трейсах зачастую достаточное. Агенты выдают разумный промежуточный результат; они просто выдают его несколько раз, в неверном порядке, против устаревших допущений. Не хватает не лучшего планировщика. Не хватает механизма, позволяющего сбросить или отложить нагрузку.
Это различие важно, потому что два диагноза подразумевают противоположные исправления. Если проблема в рассуждениях, исправление — это работа с промптами и выбор модели. Если проблема в очередях, исправление архитектурное: admission control, backpressure, идемпотентность и планировщик, который знает свои пределы.
Admission control как первое проектное решение
Каждое ребро ветвления в графе задач требует двух объявленных чисел: максимальной ширины и максимальной глубины. Ширина — сколько дочерних задач может выполняться одновременно. Глубина — сколько поколений делегирования допускается, прежде чем граф обязан вернуть результат. Обе — константы времени проектирования, объявленные в спецификации графа, а не обнаруженные в продакшене при взгляде на счёт.
Полезное правило допуска конъюнктивно: задача допускается только тогда, когда доступны и рабочий слот, и бюджетный срез. Рабочие слоты ограничивают параллелизм. Бюджетные срезы ограничивают стоимость и время выполнения. Если исчерпано любое из двух, задача не запускается. Она ставится в очередь с дедлайном или отбрасывается с зафиксированной причиной.

Отбрасывание — законный исход. Диспетчер, который не может отказать в работе, — не диспетчер; это воронка. Молчаливое неограниченное расширение — это режим отказа, и оно молчаливо именно потому, что ничто в системе не имеет права сказать «нет».
Конкретный механизм: представляйте состояние оркестратора как реестр, а не как разговор. Каждая допущенная задача держит лиз — (task_id, worker_slot, budget_slice, deadline). Лиз освобождается при завершении, при явном сбое или по истечении срока. Задача планировщика на каждом тике — сопоставить задачи в очереди со свободными лизами. Это неэффектно, и в этом вся суть.
Backpressure между агентами
Субагенты должны иметь возможность сигнализировать «не сейчас», а не поглощать работу и падать поздно. Поздний сбой дорог: работа уже потребила контекст, токены и время, а сбой всплывает в точке, где родитель потерял информацию, необходимую для дешёвого восстановления.
Два механизма делают ранний отказ безопасным.
Первый — общая очередь с таймаутами видимости. Задача захватывается ровно одним воркером на ограниченный период. Если воркер не завершает или не продлевает захват в течение этого периода, захват истекает, и задача снова становится видимой. Это не даёт двум агентам захватить одну и ту же единицу работы — самому частому источнику дублированного вывода в роях, которые выглядят так, будто противоречат друг другу. Они не спорят; они оба делают одну и ту же работу.
Второй — ключи идемпотентности на каждой операции с побочными эффектами. Когда повторная попытка несёт тот же ключ, что и исходная, нижестоящая система может дедуплицировать вместо двойного выполнения. Именно это позволяет backpressure быть агрессивным. Без идемпотентности агрессивный отказ и повтор опасны, потому что повтор может записать дважды. С идемпотентностью отказ в работе дёшев и безопасен, и систему можно настроить на ранний сброс нагрузки вместо её поглощения и коллапса.
Компромисс реален: идемпотентность требует содействия от каждого инструмента и каждой внешней службы в графе, а некоторые его не предоставят. Там, где не предоставят, диспетчер должен либо сериализовать доступ к этому инструменту, либо принять семантику at-most-once и явно обрабатывать пробелы. Притворяться, что проблемы не существует, — так рой приобретает класс багов, которые проявляются
Четыре измерения на каждый тип задачи покрывают большую часть диагностического поля:

- Глубина очереди — сколько работы ждёт, с выборкой во времени.
- Время ожидания — задержка допуска, от постановки в очередь до выдачи лиза.
- Время от захвата до завершения — задержка выполнения, отделённая от времени ожидания, чтобы их можно было атрибутировать.
- Коэффициент усиления повторов — общее число попыток, делённое на число различных единиц работы.
Коэффициент усиления — самый полезный сигнал. Когда он близок к единице, система выполняет каждую часть работы примерно один раз. Когда он растёт, рой тратит свою пропускную способность на повторное выведение результатов, которые у него уже были, и никакая доработка промптов это не снизит.
Запуск должен реконструироваться как таймлайн допусков — задача поставлена в очередь, лиз выдан, лиз продлён, лиз истёк, задача завершена, задача отправлена в dead-letter — а не как список сообщений. Логи сообщений говорят, что агенты сказали. Таймлайны допусков говорят, что система сделала, и только второе объясняет инцидент.
Алертите по коэффициенту усиления, а не по числу агентов. Число агентов — тщеславная метрика, которая плавно растёт и при здоровом всплеске, и при каскадном сбое. Коэффициент усиления их различает.
Проектное правило
Относитесь к оркестратору как к диспетчеру с тремя компонентами: планировщик, бюджетный реестр и путь dead-letter. Планировщик владеет допуском. Реестр владеет учётом стоимости и параллелизма. Путь dead-letter владеет всем, что исчерпало свои повторы, чтобы сбои были видимы и инспектируемы, а не молча переставлялись в очередь навсегда.
Вывод планировщика должен быть графом задач с объявленными ширинами и глубинами, а не свободной формой делегирования. Планировщик, выдающий прозу вроде «исследуй рынок и синтезируй выводы», породил желание, а не граф. Планировщик, выдающий узлы с ограниченным ветвлением, явными зависимостями и потолками бюджета на узел, породил нечто, что диспетчер может исполнить, а бюджетный реестр — обеспечить.
Измеряйте рой по пропускной способности и завершению под нагрузкой, а не по элегантности его диалога. Качество диалога — это прокси, который коррелирует с успехом в демо и отвязывается от него в продакшене. Пропускная способность при фиксированном бюджете параллелизма, доля завершений к фиксированному дедлайну и коэффициент усиления — это числа, предсказывающие, выживет ли система при контакте с реальным трафиком.
Неудобное следствие: рой с посредственными рассуждениями и превосходным планированием обойдёт рой с превосходными рассуждениями и без admission control, потому что второй тратит свою пропускную способность на переделку уже сделанной работы. Планирование — не неинтересная часть системы. Это та часть, которая определяет, получит ли интересная часть вообще шанс выполниться.
