# Swarm — Event-Driven Оркестрация Агентов

**Swarm** — это легковесная event-driven оркестрация агентов на основе шины событий (EventBus). В отличие от Graph и Pipeline, Swarm работает асинхронно и обрабатывает события из очереди.

## 📋 Обзор

Swarm предназначен для:
- **Асинхронной обработки** событий
- **Масштабируемой оркестрации** множества агентов
- **Слабой связанности** между компонентами
- **Фоновой обработки** задач

## 🔄 Архитектура

```
┌─────────────┐     publish      ┌─────────────┐
│   Graph     │ ────────────────> │  EventBus   │
│  Pipeline   │                  │  (Queue)    │
│   Agent     │ <──────────────── │             │
└─────────────┘      claim       └──────┬──────┘
                                        │
                                        │ subscribe
                                        ▼
                                 ┌─────────────┐
                                 │    Swarm    │
                                 │             │
                                 │ - drain()   │
                                 │ - dispatch()│
                                 └─────────────┘
```

## 🚀 Быстрый старт

### Базовый пример

```python
from logos_adk import Agent
from logos_adk.swarm import Swarm
from logos_adk.event_bus import InMemoryEventBus

# Создаём шину событий
bus = InMemoryEventBus()

# Создаём Swarm
swarm = Swarm("seo-swarm", event_bus=bus)

# Создаём агента
agent = Agent("seo_expert", model="gpt-4o", system="Ты SEO эксперт")

# Подписываем агента на тему
swarm.subscribe(
    "need_seo",           # Тема для подписки
    agent,                # Агент или функция
    publish_to="seo_done" # Публиковать результат в тему
)

# Публикуем событие
bus.publish(
    "need_seo",
    {"prompt": "Оптимизируй заголовок: Летняя распродажа"},
    correlation_id="task-123"
)

# Обрабатываем события
processed = await swarm.drain()
print(f"Обработано событий: {processed}")
```

## 📖 API

### Создание Swarm

```python
from logos_adk.swarm import Swarm
from logos_adk.event_bus import InMemoryEventBus, SQLiteEventBus

# In-memory шина (development)
bus = InMemoryEventBus()

# SQLite шина (production, persistent)
bus = SQLiteEventBus("events.db")

# Swarm
swarm = Swarm(
    "my-swarm",
    event_bus=bus,
    retry_delay_seconds=5.0,  # Задержка перед повторной попыткой
    lease_seconds=60.0        # Время блокировки события
)
```

### Подписка на события

```python
# Подписка агента
swarm.subscribe(
    "need_seo",                    # Тема
    agent,                         # Runnable (Agent, Team, Graph)
    name="seo_handler",           # Имя обработчика
    publish_to="seo_done"         # Публиковать результат
)

# Подписка функции
async def my_handler(event):
    return {"result": "done"}

swarm.subscribe(
    "need_copy",
    my_handler,
    publish_to=lambda event, payload: f"{event.topic}_done"
)
```

### Обработчики событий

#### Агент как обработчик

```python
agent = Agent("writer", model="gpt-4o")
swarm.subscribe("need_text", agent, publish_to="text_done")

# Агент автоматически получит prompt из event.payload["prompt"]
```

#### Функция как обработчик

```python
async def transform(event: EventRecord) -> dict:
    """Обработка события.
    
    Args:
        event: EventRecord с полями:
            - id: str
            - topic: str
            - payload: dict
            - correlation_id: str
            - run_id: str
            - publisher: str
    """
    prompt = event.payload.get("prompt", "")
    result = f"Обработано: {prompt}"
    return {"content": result}

swarm.subscribe("process", transform, publish_to="processed")
```

#### Runnable как обработчик

```python
from logos_adk import Graph

graph = Graph("workflow")
# ... настройка графа

swarm.subscribe("complex_task", graph, publish_to="done")
```

### Публикация событий

```python
# Базовая публикация
event = bus.publish(
    "topic_name",
    {"prompt": "Задача", "extra": "data"},
    correlation_id="corr-123",
    run_id="run-456",
    publisher="my-service"
)

# Пубикация с кампанией
event = bus.publish(
    "topic_name",
    payload,
    campaign_id="campaign-789"
)
```

### Обработка событий

#### drain() — обработка всех событий

```python
# Обработать все доступные события
processed = await swarm.drain()

# Обработать максимум N событий
processed = await swarm.drain(max_events=10)
```

#### drain_once() — одно событие

```python
processed = await swarm.drain_once()
```

#### dispatch() — публикация и обработка

```python
response = await swarm.dispatch(
    prompt="Оптимизируй заголовок",
    request_topic="need_seo",
    response_topic="seo_done",  # Опционально
    payload={"extra": "data"},
    session_id="session-123",
    correlation_id="corr-456",
    max_events=10
)

print(response.content)
print(response.raw["swarm_dispatch"])
```

## 🎛️ Паттерны использования

### 1. Последовательная обработка

```python
swarm = Swarm("pipeline-swarm", event_bus=bus)

# Цепочка обработчиков
swarm.subscribe("step1", agent1, publish_to="step2")
swarm.subscribe("step2", agent2, publish_to="step3")
swarm.subscribe("step3", agent3, publish_to="done")

# Запуск
await swarm.dispatch(
    prompt="Начать обработку",
    request_topic="step1",
    response_topic="done"
)
```

### 2. Параллельная обработка

```python
swarm = Swarm("parallel-swarm", event_bus=bus)

# Несколько обработчиков на одну тему
swarm.subscribe("analyze", agent1, publish_to="results")
swarm.subscribe("analyze", agent2, publish_to="results")
swarm.subscribe("analyze", agent3, publish_to="results")

# Агрегатор
async def aggregate(event):
    results = bus.list_events(
        topic="results",
        correlation_id=event.correlation_id
    )
    return {"aggregated": [r.payload for r in results]}

swarm.subscribe("aggregate", aggregate, publish_to="done")
```

### 3. Fan-out / Fan-in

```python
swarm = Swarm("fan-swarm", event_bus=bus)

# Fan-out: одно событие → много обработчиков
swarm.subscribe("start", agent1, publish_to="branch_a")
swarm.subscribe("start", agent2, publish_to="branch_b")
swarm.subscribe("start", agent3, publish_to="branch_c")

# Fan-in: много событий → один агрегатор
async def fan_in(event):
    # Ждём все ветки
    branches = ["branch_a", "branch_b", "branch_c"]
    results = []
    for branch in branches:
        events = bus.list_events(
            topic=branch,
            correlation_id=event.correlation_id
        )
        results.extend(events)
    return {"results": results}

swarm.subscribe("finalize", fan_in, publish_to="done")
```

### 4. Retry и Error Handling

```python
swarm = Swarm(
    "reliable-swarm",
    event_bus=bus,
    retry_delay_seconds=10.0,  # 10 секунд между попытками
    lease_seconds=120.0         # 2 минуты на обработку
)

# При ошибке событие будет requeue с задержкой
```

### 5. Conditional Routing

```python
async def router(event):
    payload = event.payload
    if "urgent" in payload.get("priority", ""):
        return {"route": "urgent_queue"}
    return {"route": "normal_queue"}

swarm.subscribe("incoming", router, publish_to=lambda e, p: p.get("route", "default"))
```

## 🔧 Конфигурация в YAML

### Swarm в Team Config

```yaml
name: seo_team
agents:
  - name: seo_expert
    role: seo
    model: gpt-4o
  - name: copywriter
    role: writer
    model: claude-sonnet-4

event_bus:
  backend: sqlite
  path: .logos_adk/events.db

subscriptions:
  - agent_name: seo_expert
    topic: need_seo
    publish_to: seo_done
  
  - agent_name: copywriter
    topic: need_copy
    publish_to: copy_done

# Swarm департамент
departments:
  - name: seo_swarm
    kind: swarm
    description: Event-driven swarm для SEO
    topics:
      - need_seo
    handler:
      name: seo_handler
      publish_to: seo_done
```

### Программная настройка

```python
from logos_adk import Team
from logos_adk.swarm import Swarm
from logos_adk.event_bus import SQLiteEventBus

# Шина событий
bus = SQLiteEventBus("events.db")

# Swarm
swarm = Swarm("seo-swarm", event_bus=bus)
swarm.subscribe("need_seo", agent1, publish_to="seo_done")
swarm.subscribe("need_copy", agent2, publish_to="copy_done")

# Team с event_bus
team = Team(
    "content_team",
    agents=[agent1, agent2],
    event_bus=bus
)

# Департамент с swarm
from logos_adk.runtime import Supervisor

supervisor = Supervisor()
supervisor.add_department(
    "seo_swarm",
    swarm,
    description="SEO swarm для оптимизации"
)
```

## 📊 Мониторинг

### Статус событий

```python
# Получить событие
event = bus.get_event(event_id)
print(event.status)  # queued, processing, completed, failed

# Список событий по теме
events = bus.list_events(topic="need_seo")

# Список по correlation_id
events = bus.list_events(correlation_id="corr-123")
```

### Метрики

```python
# Количество обработанных событий
processed = await swarm.drain()

# Статистика по теме
stats = bus.get_stats(topic="need_seo")
```

## 🏗️ Производственный пример: Marketplace SEO Swarm

```python
from logos_adk import Agent, Team
from logos_adk.swarm import Swarm
from logos_adk.event_bus import SQLiteEventBus

# Шина событий
bus = SQLiteEventBus("marketplace_events.db")

# Агенты
seo_agent = Agent(
    "seo_expert",
    model="minimax/minimax-m2.5",
    system="Ты SEO эксперт для маркетплейса"
)

copy_agent = Agent(
    "copywriter",
    model="minimax/minimax-m2.5",
    system="Ты копирайтер для маркетплейса"
)

quality_agent = Agent(
    "quality_analyst",
    model="minimax/minimax-m2.5",
    system="Ты контролёр качества"
)

# Swarm для SEO оптимизации
seo_swarm = Swarm("seo-swarm", event_bus=bus)

# Цепочка обработки
seo_swarm.subscribe("need_seo", seo_agent, publish_to="need_copy")
seo_swarm.subscribe("need_copy", copy_agent, publish_to="need_quality")
seo_swarm.subscribe("need_quality", quality_agent, publish_to="publish_ready")

# Запуск обработки
async def process_listing(prompt: str):
    response = await seo_swarm.dispatch(
        prompt=prompt,
        request_topic="need_seo",
        response_topic="publish_ready",
        max_events=3  # 3 шага в цепочке
    )
    return response.content

# Пример использования
result = await process_listing("Продать iPhone 15 Pro")
print(result)
```

## 🆚 Сравнение с другими оркестраторами

| Характеристика | Swarm | Graph | Pipeline |
|----------------|-------|-------|----------|
| **Модель** | Event-driven | Stateful graph | Linear steps |
| **Синхронность** | Асинхронный | Синхронный | Синхронный |
| **Масштабирование** | Высокое | Среднее | Низкое |
| **Сложность** | Низкая | Средняя | Низкая |
| **Use case** | Фоновые задачи | Workflow с условиями | Последовательные шаги |

## 🎯 Best Practices

### 1. Именование тем

```python
# Хорошо
"need_seo" → "seo_done"
"step1" → "step2" → "step3"

# Плохо
"process" → "result"  # Слишком общее
```

### 2. Корреляция событий

```python
# Всегда используйте correlation_id
bus.publish(
    "topic",
    payload,
    correlation_id=session_id or uuid4().hex
)
```

### 3. Обработка ошибок

```python
swarm = Swarm(
    "reliable-swarm",
    event_bus=bus,
    retry_delay_seconds=30.0,  # 30 секунд между попытками
    lease_seconds=300.0         # 5 минут на обработку
)
```

### 4. Мониторинг

```python
# Логирование
async def logged_handler(event):
    print(f"Processing {event.id} from {event.publisher}")
    result = await handler(event)
    print(f"Completed {event.id}")
    return result
```

## 📚 Ресурсы

- [Event Bus Package](../logos_adk/event_bus/__init__.py)
- [Swarm Implementation](../logos_adk/swarm.py)
- [Tests](../tests/test_swarm.py)
- [Team Config](../logos_adk/team_config.py)
