Привет! ИИ-агенты — главная горячая тема этого года, но все наверняка видели как их ради хайпа пытаются затащить куда угодно, совсем не глядя на эффективность и какой-либо здравый смысл.

В этой статье я расскажу о действительно полезном применении концепции агентов и попробую доказать, почему любой боксерский поединок является мультиагентной системой. И да, сходу со старта: это, конечно же, легкая и ироничная статья, к которой не нужно относиться серьезно — это чистый сарказм и попытка натянуть мультиагентную сову на мультиагентный боксерский глобус, а все приведенные аналогии между боксом и агентами — лишь художественный вымысел. ツ

Итак, поговорим про system design бокса, про reinforcement learning, адаптивные алгоритмы, всевозможный вызов tools типа джебов или клинча, очереди сообщений и гарантию их доставки, graceful degradation агентов и многое другое.

Архитектура системы

Боксерский ринг в стандартном варианте представляет собой ограниченную вычислительную среду (bounded execution context) размером 6.1×6.1 метра, что соответствует примерно 37.21 м² доступного адресного пространства. Система работает большую часть времени в режиме peer-to-peer с двумя активными агентами (Agent_A) и Agent_B), одним арбитром (Referee_Node) и множественными Support Agents в угловых кластерах, ключевыми из которых являются тренер и катмен.

┌───────────────────────────────────────────┐
│                                           │
│                  [Referee]      ──────────│────── [Judges_Node](3)
│                /           \              │
│        [Agent_A] ←──P2P──→ [Agent_B]      │
│               │               │           │
└───────────────│───────────────│───────────┘
                │               │
   ┌─────────────────┐   ┌─────────────────┐
   │ Corner [Red]    │   │ Corner [Blue]   │
   │ - Тренер        │   │ - Тренер        │
   │ - Катмен        │   │ - Катмен        │
   │ - Support       │   │ - Support       │
   └─────────────────┘   └─────────────────┘
  • Agent_Red & Agent_Blue — активные агенты (p2p)

  • Referee_Node — координатор, контролирует правила и circuit breakers

  • Red/Blue Corners — кластеры support-агентов (тренер = RLHF middleware, cutman = hotfix & recovery).

  • Judges_Node — внешние валидаторы, отвечающий за метрики и scoring

Для нашей системы наиболее важными являются два активных агента в ринге, но при схожей функциональности и схожих tools они могут быть написаны на разных фреймворках и запромчены по разному, поэтому детально разберем именно их способ взаимодействия.

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

Инструментарий (Tools) агентов

  • Jab() — легковесный инструмент для разведывательных атак

  • Cross() — мощный инструмент с высокой полезной нагрузкой

  • Hook() — обходной инструмент для преодоления защитных механизмов

  • Uppercut() — тяжелый инструмент с критической нагрузкой

  • Block() — defensive middleware для фильтрации входящих запросов, может быть в виде сбивания удара или принятия его в прямой блок

  • Slip() — алгоритм уклонения с небольшим потреблением энергии

  • Footwork() — вызов службы перемещений для оптимизации топологии

  • Clinch() — процедура экстренного сброса соединения, фактически выступает рестартом сессии

Протокол вызова инструментов

В нашем случае каждый вызов инструмента представляет собой пакет данных с заголовком (setup), полезной нагрузкой (impact) и контрольной суммой (follow-through).

Представим каждый удар как отдельный REST/gRPC-эндпойнт с контрактом:

POST /tools/jab
{
  "setup": {
    "agent_id": "A123",
    "stance": "orthodox",
    "cost": 0.1,
    "timestamp": 1699999999
  },
  "impact": {
    "power": 7,
    "target": "head", 
    "angle": 15,
    "distance": 0.2,
    "latency_ms": 42
  },
  "follow_through": {
    "ready_for_next": true,
    "recovery_time_ms": 180
  }
}
Ответ
{
  "status": "executed",
  "execution_result": {
    "hit": false,
    "damage": 0,
    "actual_latency_ms": 45
  },
  "system_state": {
    "ready_for_next": true,
    "cooldown_ms": 250,
    "energy_remaining": 0.85
  }
}

Эффективность вызова инструментов

Ключевой метрикой является Energy-per-Operation (EPO). Jab имеет низкий EPO (~0.2 энергоединицы) но и низкую эффективность, тогда как Uppercut требует высоких энергозатрат (EPO ~0.65) при потенциально критическом impact. При этом EPO очень сильно зависит от environment (окружающей среды в виде расстояния, угла, части тела и тд) — например, бить заряженный джеб в корпус гораздо сложнее, чем легко выбрасывать его отвлекающим в голову.

Но нельзя просто «нанести удар» (=вызвать инструмент) — нужно оптимально управлять вызовами с учётом latency, cooldown и контекста.

Определим метрику:
IE (Invocation Efficiency) = (успешные_попадания / попытки_вызовов) × (средний_урон / 10) × (1 - avg_latency_ms / Tmax)

H — успешные хиты, N — попытки, {d} — средний damage (0..10), {l} — среднее латенси, Tmax​ — допустимое окно реакции (например 300 ms).

Пример расчёта на ситуации стабильных достаточно точных несильных джебов, 8 из 10 которых попали по цели, но огромного урона не нанесли:

  • H = 8, N = 10 → H/N = 0.8

  • {d} = 6 → {d}/10 = 0.6

  • {l} = 80 ms, Tmax​ = 300 ms → 1 - 80/300 = 1 - 0.2666... = 0.7333...

0.8 × 0.6 × 0.7333... = 0.352 ≈ 35.2% IE

Получается что инструмент работает неплохо, но его стоит скорректировать: либо повысить damage (добавить акцент и силу удара), либо снизить latency (ускорить исполнение через более резкий тайминг и footwork).

С тем, как устроены инструменты, мы поверхностно разобрались, давайте посмотрим на то, как регулируется их обмен.

Agent-to-Agent (A2A) Communication

Агентам нужно как-то взаимодействовать между собой, поэтому для них придумывают протоколы взаимодействия (самые популярные на слуху это MCP и A2A). Если все упростить, то это правила и регламенты: нельзя вызывать инструмент в затылок, нужно слушаться судью, общение с тренером ограничено между раундами и так далее.

В нашем же случае инструменты могут взаимодействовать синхронно и асинхронно.

Синхронная коммуникация

Прямые инструменты (jab, cross) реализуют синхронную модель взаимодействия из-за их сверхнизкого latency доставки сообщения — фактически агент отправляет блокирующий запрос и ожидает немедленного ответа в виде блока, контратаки или успешного попадания.

Асинхронная коммуникация

Хуки и апперкоты демонстрируют принципиально иную парадигму — они требуют более длительной подготовки (setup phase), но позволяют обойти прямую защиту противника или же нанести ощутимый урон при доставке сообщения. В отличие от синхронных прямых ударов, эти tools не блокируют execution thread — пока агент готовит любой из этих инструментов, оппонирующий агент может параллельно выполнять свои операции. Многие инструменты типа footwork тоже асинхронны.

Но самая мощь вызова инструментов в наших агентах заключается в их комбинациях.

Message Queue и Buffer Management

Комбинации ударов представляют собой message queue с последовательной обработкой. Именно поэтому в контракте каждого tools у нас есть «ready_for_next», потому что часто очередь может быть прервана ответными действиями агента-соперника, что вызывает фолбек на полное прекращение выполнения или же на вызов защитных инструментов. Рассмотрим классическую четырехударную комбинацию (1-1-3-5: джеб—кросс—правый хук—левый апперкот):

class CombinationQueue:
    def execute_power_combo(self):
        self.message_queue.put(Jab(target='head', power=0.2))           # делаем discovery
        self.message_queue.put(Cross(target='head', power=0.5))         # наносим весомый ущерб
        self.message_queue.put(RightHook(target='head', power=0.85))    # эскалируем ущерб до критического
        self.message_queue.put(LeftUppercut(target='body', power=0.95)) # финишируем
        
        while not self.message_queue.empty():
            punch = self.message_queue.get()
            response = self.opponent_agent.process(punch)
            
            if response.type == "COUNTER_INCOMING":
                self.message_queue.clear()  # Прерываем всю серию
                self.execute_defensive_protocol()
            else:
                self.handle_response(response)

Работа с контекстом и память

Одна из самых больших проблема сложных мультиагентных систем — это контекст и работа с памятью. В нашей ситуации контекст огромный и его можно разбить на несколько важных групп:

  • Historical context — предыдущие поединки каждого из агентов, потенциальная неудобность оппонентов, их опыт и привычные паттерны поведения

  • Temporal context — текущий раунд, оставшееся время, фазовое состояние боя (начало, середина, концовка)

  • Spatial context — позиция в ринге, дистанция до противника, угол атаки, футворк

  • Performance context — текущий уровень энергии, накопленный урон, скорость реакции и осознанность

  • Strategic context — счет по очкам, агрессивность противника, приоритеты на раунд или бой в целом

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

Что класть в память? Самое важное для принятия решения, например, «не лезь рубиться, на дистанции работай» или «еще раунд надо забирать для победы». Содержимое памяти очень специфично для решаемой задачи, а сама память помогает постоянно корректировать предыдущий план: например, падение агента в нокдаун в первых раундах может оказать весомое влияние на вообще весь последующий контекст межагентного взаимодействия.

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

Fault Tolerance и Recovery

Интересной особенностью нашей системы являются механизмы отказа от обслуживания и восстановления.

Graceful Degradation

При получении критического урона агенты демонстрируют классическое поведение graceful degradation — они переходят в defensive mode, резко снижая свою функциональность ради остатков стабильности. Вызов классического инструмента clinch является хорошим примером controlled degradation — агент временно прекращает свою основную задачу в виде нанесение урона другому агенту, но при этом сохраняет все другие базовые сервисы.

def handle_critical_damage(self, total_damage_level):
    if total_damage_level > 0.8:
        self.switch_to_survival_mode()
        self.disable_aggressive_tools()
        self.enable_only(['Block', 'Clinch', 'Footwork'])
        self.log("Entering graceful degradation mode")

Complete System Failure

При превышении критического порога происходит отказ от обслуживания, который может быть временным (с таймаутом до 10 секунд — нокдаун), либо же полным (нокаут) с финальным завершением межагентного взаимодействия. В обоих случаях один из агентов полностью прекращает обработку запросов.

Circuit Breaker Pattern

Вы еще не забыли про нашего Referee-агента? Его участие в межагентном взаимодействии не такое большое, но часто при детектировании критических ошибок этот агент может временно прерывать execution и запускать процесс recovery процесса.

Так же этот агент фактически является сразу и рейт-лимитером (по достижению критического урона, либо по превышению количество вызовов инструмента clinch) и отвечает за валидацию вызванных инструментов (например, не пропускает illegal punches).

Load Balancing и Resource Management

Energy Distribution

Каждый агент управляет ограниченным energy pool с различными стратегиями распределения:

Burst mode: высокая активность в начале раунда. Conservative mode: равномерное распределение энергии по раундам и Last-mile optimization: резерв энергии для финальных раундов, которые зачастую становятся решающими.

Adaptive Algorithms

Успешные боксеры демонстрируют adaptive behavior patterns — фактически машинное обучение в реальном времени на основе обратной связи. Система постоянно анализирует response patterns противника и корректирует свою стратегию, оптимизируя свои гиперпараметры.

И здесь важно вспомнить про других агентов нашей системы, которые играют важную роль, но про которых мы еще не говорили. Это Agent_Trainer и Agent_Cutman.

Agent Trainer и Cutman

Агент-тренер выступает в роли intelligent middleware с ML capabilities, так как занимается глубочайшим анализом происходящего в реальном времени, быстро дообучает сетку, а затем фактически накатывает оптимизированные гиперпараметры на прод своего подопечного агента. Это приводит к глубокой персонализации происходящего и сильным корректировкам поведения.

Такой агент всячески старается сделать finetune и накатить различные hot fixes на прод во время поединка и фактически работает в двух протоколах: когда идет раунд, то делает это в UDP (быстрые non-blocking observation без какой-либо гарантии доставки), а между раундами протокол меняется на надежный TCP.

Кстати, этот агент может делать A/B тесты через подопечного агента и всегда напоминает нам о важности промптинга: вспомните типичные команды подопечному: «двигайся!», «подними руки», «левой дорабатывай» — все это напоминает нам как важны контекст, подсчет токенов и минимально достаточный промпт. Не должно быть избыточность токенов при однозначности смысла передаваемого сообщения.

Роль агента-катмена заключается не только в hot-swapping сразу на проде, но и сбору обратной связи о состоянии подопечного агента для постоянного обновления контекста.

Фреймворки

Framework в нашей мультиагентной системе — это архитектурный стиль разной реализации одних и тех же инструментов, их паттерны, стандарты и best practices, накопленные поколениями. Вот несколько самых удачных:

  • Cuban — лёгкий и быстрый, с асинхронным footwork и акцентом на силу

  • Mexican — high-throughput для ближнего боя: бесконечные хук–апперкоты с феноменальной fault tolerance, но отсутствием защитного rate-limiter

  • Post-СССР — высокотехнологичный и строгий: всё оптимизировано под дисциплину и выносливость

  • Classic British — академически выдержанный с хорошим предсказуемым кодом, в котором очень много legacy

Но, как и везде в разработке, идеальных фреймворков под все ситуации не существует, поэтому очень важно соблюдать важные паттерны проектирование и все best practices для агентных систем. Давайте кратко обсудим именно их и уже будем подходить к выводам.

Подводя итоги и Best Practices

Как и в любой распределённой системе, есть набор практик, которые повышают надёжность и предсказуемость мультиагентных систем. Чему научит наших агентов бокс?

  • Strategy Design Pattern — делим пространство на сектора (дальний, средний, ближний бой). Каждый сектор имеет свой profile и набор наиболее эффективных инструментов в нем

  • Monitoring & Logging — агенты в углу обязаны постоянно снимать разные метрики и наблюдать за дашбордом состояния, без объемной телеметрии ни одна агентная система работать хорошо не будет

  • Tool Selection Policy — агенты не должны вызывать тяжёлые инструменты (типа uppercut) просто так и без предварительной подготовки, нужен механизм оптимального выбора tools в зависимости от контекста, энергии и позиции

  • Fallback Strategies — при сбое доставки сообщений или вызова инструментов нам необходимо иметь запасной план: просто прервать выполнение или же активировать другие инструменты типа clinch или footwork

  • Rate Limiting & Reasoning — постоянно кидать бесконечные джебы или делать сложные комбо без подготовки — плохая идея, гораздо чаще лучше потратить время на более качественное планирование и его обоснование

  • Context Window Management — агент не может держать в памяти всю историю поединка, поэтому важно работать с контекстным окном и запоминать только последние действие и особенные моменты, а не весь лог событий

Выводы

Как мы видим, бокс — это по настоящему про агентов и полноценная мультиагентная система! ツ

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

А реальная жизнь, конечно, гораздо сложнее. И в реальной жизни работа над агентами требует хорошего понимания, технической базы, глубокого погружения в специфику и копания в данных и процессах.

Я решил написать этот пост по нескольким причинам: мне очень нравятся агенты и те возможности, которые они открывают. Мне нравится объяснять сложное простым языком, но иногда это вызывает непонимание — нуу, раз нет формулок или кода, то тогда все как-то несерьезно. Поэтому мне было интересно попробовать натянуть агентную сову на агентный глобус и, надеюсь, вы получили удовольствие в этом процессе.

Подписывайтесь на мой небольшой канальчик Agentic World, который посвящен агентам, LLM, AI и просто людям. Буду очень рад вашей подписке ?

Мои другие статьи:

Порулить браузером через LLM: пишем AI-агента в стиле «browser-use» на ванильной LLM без фреймворков

Бенчмарк качества распознавания речи (ASR) в телефонии: как мы сравниваемся с Whisper, GigaAM и T-One

Переизобретая аналитику будущего: как и почему LLM-агенты меняют анализ продуктов, но все не так просто

Как я автоматизировал мониторинг цен своей корзины на маркетплейсах и при чем тут LLM

Спасибо!

Комментарии (0)