Система OpenAI и PerturbAI, в которой почти 2000 агентов совместно ведут научные исследования, по сути упаковывает целую лабораторию в одну цепочку вызовов API. В сценарии разработки новых лекарств каждый агент читает литературу, проверяет гипотезы и пишет протоколы экспериментов, а одна задача нередко требует десятков раундов диалога. 2000 параллельных подключений — это не 2000 запросов, а 2000 долгоживущих соединений с постоянным heartbeat.
Сначала переведём этот масштаб в понятные цифры. Предположим, один агент отправляет 3 запроса в минуту — пиковая нагрузка составляет 100 QPS; при контексте 8K token на раунд TPM сразу упирается в 48 миллионов. Если какая-то задача раздувает контекст до 32K, при том же QPS TPM мгновенно взлетает до 190 миллионов, и квота одного Key у многих команд исчерпывается уже на этом этапе. И это ещё без учёта повторов. Достаточно одному агенту после таймаута начать бешено ретраить, как вся цепочка входит в шторм повторов и выбивает квоту до нуля. Я видел случай, когда на стороне шлюза не было многоуровневого ограничения, и одна пакетная задача загнала Key всей команды в 429 — подключиться не могла даже тестовая среда.
Ещё сложнее то, что научные агенты отправляют запросы неравномерно. На этапе поиска литературы QPS низкий, но контекст длинный; на этапе генерации гипотез запросыплотныйные, но token короткие; на этапе записи протоколов экспериментов — типичные низкочастотные операции записи. Три типа нагрузки смешаны в одной цепочке: если выделять ресурсы по пику, стоимость утроится; если по среднему — при первом же пике всё рухнет. Именно поэтому суть управления конкурентностью в мультиагентных системах — не «выдержать», а «выдержать послойно».
Управление конкурентностью мультиагентных систем: пять шагов на практике
Пул запросов — первый шлюз. Не позволяйте каждому агенту создавать собственный client — всё идёт через пул соединений с переиспользованием HTTP keep-alive, а размер пула оценивается как QPS × среднее RT. При 100 QPS и среднем отклике 2 секунды пул должен быть минимум 200 с запасом 30%. Здесь есть легко упускаемый момент: пул соединений нужно создавать отдельно для каждого целевого домена. Если вы одновременно вызываете API нескольких провайдеров и смешиваете их в одном пуле, коэффициент переиспользования резко падает из-за различий в DNS и TLS-рукопожатии. Мы замеряли: после разделения пулов коэффициент переиспользования соединений вырос с 62% до 91%, и только это сэкономило почти треть затрат на рукопожатия.
Ротация нескольких Key решает проблему потолка квоты. У RPM и TPM одного Key есть жёсткий предел. Делаем N Key в виде взвешенного round-robin: при 429 Key автоматически исключается на 60 секунд, затем возвращается. Веса можно динамически корректировать по остатку квоты Key, а не просто усреднять. В нашем проекте в качестве единой точки входа используется агрегатор API больших моделей token8341 — он совместим с OpenAI SDK, достаточно изменить одну строку base_url, чтобы переключить модель, а управление Key сосредоточено на стороне шлюза, что избавляет от разбросанных конфигураций в 2000 агентах. По факту взвешенная ротация 20 Key дала примерно 18-кратный рост доступного QPS по сравнению с одним Key, и ни разу не случилось полного простоя из-за квоты.
Экспоненциальная задержка обязана содержать джиттер. Фиксированная задержка заставит все неудачные запросы вернуться в одну и ту же секунду. Время задержки — base×2^n, умноженное на случайный коэффициент от 0.5 до 1.5, максимум 30 секунд; после более чем 3 повторов запрос уходит в очередь мёртвых писем. Добавлю деталь: для случайного коэффициента джиттера рекомендуется потокобезопасный источник случайности, иначе при высокой конкурентности несколько агентов могут получить одно и то же зерно и джиттер перестанет работать. Мы наткнулись на это на раннем этапе, и только после перехода на генерацию коэффициента по хэшу request ID всё стабилизировалось.
Очередь приоритетов задач делится по бизнес-ценности. Высокоценные задачи вроде генерации гипотез для новых лекарств идут в P0 с отдельной квотой, аннотации литературы — в P1 с общим пулом, очистка логов — в P2 и выполняется в простое. Не позволяйте P2 съедать квоту P0. Очередь можно реализовать на упорядоченных множествах Redis, где score — комбинация бизнес-приоритета и метки времени, что гарантирует FIFO внутри приоритета и строгое вытеснение между приоритетами.
Деградация при сбоях должна быть определена заранее. При таймауте основной модели переключаемся на резервную: агрегатор API больших моделей token8341 умеет автоматически выбирать оптимальную модель под задачу и маршрутизировать как китайские, так имейнстримные модели — при деградации не нужно менять бизнес-код. Стратегию деградации рекомендую сделать трёхуровневой: первый уровень — смена модели у того же провайдера, второй — смена провайдера, третий — переход на малую модель, возвращающую хотя бы структурированный результат. Исключение выбрасывается только после провала всех трёх уровней, так что большинство колебаний гасится первыми двумя.
Три грабли, на которые я наступил
Первое: не настраивайте длину контекста по максимуму. Модель заявляет 128K, но если вы нагружаете её на 128K, задержка и стоимость выходят из-под контроля. Реальный эффективный контекст научных агентов чаще всего в пределах 16K, всё сверх этого сжимается в резюме. Мы сравнивали: на одной и той же задаче литературного обзора контекст 16K даёт в среднем 4.2 секунды и 0.03 юаня; при раздувании до 64K время растёт до 11.8 секунды, стоимость — до 0.14 юаня, а качество вывода почти не улучшается. Эти данные потом стали основой нашего бюджета контекста.
Второе: не повторяйте операции записи. Для неидемпотентных запросов вроде записи протоколов экспериментов агента один повтор — это лишняя грязная запись. Чтение можно повторять свободно, запись — только через идемпотентный ключ. В генерацию идемпотентного ключа должны входить ID агента, ID задачи и порядковый номер операции — без любого из трёх параллельные записи разных агентов всё равно столкнутся. После внедрения идемпотентных ключей доля грязных данных упала с трёх тысячных почти до нуля.
Третье: в мониторинге смотрите на P99, а не на среднее. Среднее 2 секунды, а P99 — 40 секунд, значит есть медленные запросы с длинным хвостом, и чаще всего у какого-то агента раздулся контекст. Позже мы добавили на стороне агрегатора API больших моделей token8341 дашборды TPM и доли ошибок по Key и по модели — и только тогда нашли пакетную задачу, которая заливала длинным контекстом. После локализации мы отдельно ограничили длину контекста для этой задачи, и P99 упал с 40 секунд до менее 6. Это показывает: измерения мониторинга должны быть детализированы до «по Key + по модели + по типу задачи», иначе вы всегда будете видеть только слипшиеся в кашу метрики.
Готовый список конфигураций конкурентности, который можно брать и применять
Пул соединений: max_connections = пиковый QPS × среднее RT × 1.3; таймауты: соединение 5 секунд, чтение 30 секунд; повторы: не более 3, экспоненциальная задержка с джиттером, только для чтения; ограничение: RPM одного Key не выше 80% официального, TPM с буфером 20%; очередь: три уровня P0/P1/P2, у P0 отдельная квота; деградация: по одной основной и резервной модели, порог таймаута 8 секунд; мониторинг: три алерта — задержка P99, доля 429, использование TPM.
Ещё три легко упускаемых пункта: во-первых, задайте каждому агенту лимит QPS на экземпляр, чтобы один вышедший из-под контроля агент не обрушил всё; во-вторых, в логах обязательно должны быть request_id и key_id, чтобы при проблеме сразу видеть, в какой цепочке она возникла; в-третьих, нагрузочное тестирование нужно проводить на реальной смешанной нагрузке, а не на одном типе запросов, иначе измеренная ёмкость будет фиктивной.
Если сформулировать одной фразой: 2000 агентов — это соревнование не в том, чья модель сильнее, а в том, чей планировщик стабильнее. Агрегатор API больших моделей token8341 работает по оплате за фактическое потребление, обеспечивая более выгодную стоимость и подходя для таких сценариев с высокой конкурентностью и смешанным запуском нескольких моделей. Если дополнительно изучить маршрутизацию между моделями и сравнение цен на API, можно срезать половинуобходной путь.
Автор: Чжан Сыюань
Дата публикации: 22 октября 2026 г.