# Создаем своего мультиагента

> [HTML-версия](https://learnvibecoding.ru/publiclessons/sozdaem-svoego-multiagenta) · [Индекс для LLM](https://learnvibecoding.ru/llms.txt) · [Политика использования материалов](https://learnvibecoding.ru/politika-materialov)
> Материалы защищены. Обучение LLM без согласия запрещено. При разрешённом использовании — обязательна прямая ссылка на страницу-источник.
> Мультиагентная архитектура — это уже не один “ассистент”, а система нескольких агентов.

**Курс:** Создание своего агента

> Когда начинаешь — нормально не понимать весь код с первого раза. Этот урок ведёт тебя за руку: чтобы читать код стало привычкой и можно было бы в нем начать ориентироваться.
> 

## Что такое **мультиагенты (multi-agent systems)**

Мультиагентная архитектура — это **уже не один “ассистент”, а система нескольких агентов**, каждый из которых:

- имеет свою **роль и набор инструментов**,
- может **взаимодействовать** с другими (через код, API, контекст или память),
- координируется **“менеджером”** (или оркестратором).

Например:

- один агент ищет данные,
- другой делает расчёты,
- третий визуализирует,
- четвёртый пишет отчёт,
- а менеджер решает, кто когда вступает в игру.

Эта логика пишется на Python (в smolagents, LangGraph, AutoGen и др.), и ты сам управляешь контекстом, вызовами, планами и памятью.

Недавно Open AI выпустила своего Agent Builder, рассмотрим их отличия с мультиагнетами, чтобы лучше понимать в чем разница:

![Снимок экрана 2025-10-21 в 22.13.05.png](attachment:7fc315d6-f736-4d6c-9f9b-b5be6463f328:Снимок_экрана_2025-10-21_в_22.13.05.png)

Это последовательность узлов в **OpenAI Workflow**, где:

- “Agent” — это твой основной ассистент (аналог *менеджера*),
- “File Search” — встроенный инструмент (LLM вызывает поиск по файлам),
- “MCP” — Model Context Protocol (интеграция с внешними источниками, например Notion, API, GitHub и т.д.).

То есть агент как бы сам умеет “ходить” в базу (через MCP) и “искать в файлах”, а также использовать встроенные Guardrails, циклы (`While`), условия (`If/else`) и шаги (`Transform`, `Set state`).

💬 Это **очень близко к идее мультиагентов**, но внутри одного замкнутого “контекста”.

## 3. Рассмотрим их отличия с мультиагнетами, чтобы лучше понимать в чем разница:

| Что | OpenAI Agent Builder | Multi-Agent (smolagents, LangGraph, AutoGen) |
| --- | --- | --- |
| **Количество агентов** | Один (но может использовать встроенные “инструменты”) | Несколько, каждый со своей ролью |
| **Где работает** | Внутри OpenAI (облачный UI, sandbox окружение) | В твоём коде / на сервере (полный контроль) |
| **Настройки** | Через интерфейс (инструкции, аплоад файлов, API keys) | Через код (Python, system prompts, memory, tools) |
| **Гибкость** | Прост в настройке, но ограничен фичами OpenAI | Максимальная свобода, но больше кода |
| **Тип задач** | Быстро сделать “одного умного ассистента” | Построить целую систему, где агенты общаются между собой |
| **Примеры** | ChatGPT с Retrieval + Code Interpreter | smolagents / LangGraph / AutoGen сценарий с Web + RAG + Plotter агентами |

---

## 4. Можно ли сделать “мультиагентов” на OpenAI?

👉 **Частично — да.**

Ты можешь:

- создать **несколько Assistants через API**,
- прописать их роли (“исследователь”, “анализатор”, “автор отчёта”),
- и **оркестрировать** их через Python-код — например, один вызывает ответ другого.

Это будет похоже на multi-agent setup, но **оркестрация всё равно лежит на тебе**, а не внутри OpenAI-интерфейса.

---

## 5. Если упростить до одной фразы

> 🔸 OpenAI Agent Builder = один агент без кода, всё внутри OpenAI.
> 
> 
> 🔹 **Multi-agent system = несколько агентов с разными ролями, логикой и обменом данными, ты сам их связываешь в коде.**
> 

## **Мы построим** Мини-систему из 2 агентов на **smolagents**:

• **Web-агент** — ищет в вебе, открывает страницы.
• **Manager-агент** — планирует, делегирует веб-агенту, считает время доставки (своим инструментом) и делает финальный отчёт/карту.
Задача (сюжет):
**Найти места съёмок «Бэтмена» в мире, прикинуть время перелёта грузовым бортом из «Готэма» (возьмём координаты Нью-Йорка) и показать точки на карте с цветом по времени перелёта.**
*Это учебный пример: цель — понять, как разложить задачу на агентов, инструменты и шаги, а не точность кино-географии.*
**0) Структура проекта**

```
multi-agents-demo/
 ├─ tools.py                 # инструменты (функции) — наш «калькулятор» времени перелёта
 ├─ agents.py                # определение web-агента и manager-агента
 ├─ run_demo.py              # запускаем задачу и печатаем результат
 ├─ requirements.txt         # зависимости
 ├─ .env                     # ключи (если нужны), не коммитим
 └─ .venv/                   # виртуальное окружение

```

# 1) Установка (минимум, чтобы всё взлетело)

Открой проект в VS Code/ Cursor, создай и активируй виртуальное окружение и поставь зависимости:

```bash
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS / Linux
source .venv/bin/activate

# зависимости
pip install "smolagents[litellm]" duckduckgo-search requests plotly kaleido

```

**Зачем эти пакеты:**

- `smolagents[litellm]` — фреймворк агентов + коннектор к любым LLM через LiteLLM (OpenAI, Together, пр.).
- `duckduckgo-search` — простой веб-поиск без ключа (на старте ок; есть лимиты).
- `requests` — утилиты HTTP, если понадобятся.
- `plotly` + `kaleido` — построим и сохраним картинку карты.

> 💡 Если хочешь высокое качество ответа — добавь доступ к мощной модели (OpenAI, Together, пр.). Для старта можно без ключей, но будет проще и «хрупче».
> 

---

# 2) Инструменты: считаем время перелёта

Создай **`tools.py`**:

```python
# tools.py
import math
from typing import Optional, Tuple
from smolagents import tool

@tool
def calculate_cargo_travel_time(
    origin_coords: Tuple[float, float],
    destination_coords: Tuple[float, float],
    cruising_speed_kmh: Optional[float] = 750.0,  # средняя скорость грузовых бортов
) -> float:
    """
    Рассчитать время полёта между двумя точками по сфере (велика окружность).
    Возвращает часы (float), с поправкой +10% и +1 час на взлёты/посадки.
    """
    def to_rad(deg: float) -> float:
        return deg * (math.pi / 180)

    lat1, lon1 = map(to_rad, origin_coords)
    lat2, lon2 = map(to_rad, destination_coords)

    R = 6371.0  # км, радиус Земли
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = (math.sin(dlat/2)**2
         + math.cos(lat1) * math.cos(lat2) * (math.sin(dlon/2)**2))
    c = 2 * math.asin(math.sqrt(a))
    distance_km = R * c

    actual_distance = distance_km * 1.1  # неидеальные маршруты
    flight_time_h = (actual_distance / cruising_speed_kmh) + 1.0  # +1h на процедуры
    return round(flight_time_h, 2)

```

**На что смотреть:**

декоратор `@tool` превращает функцию в «инструмент» для агента. Описание из докстринга и типы — это «контракт», по которому LLM поймёт, **когда и как** вызывать инструмент.

---

# 3) Агент Web и агент Manager

Создай **`agents.py`**. Мы покажем **две опции подключений модели**:

- **Вариант А (без ключей):** `InferenceClientModel` c провайдером *“together”* и любой открытой моделью на Hugging Face Inference (нужен аккаунт провайдера/организация, но для чтения кода это ок).
- **Вариант B (OpenAI):** `OpenAIServerModel` c переменной `OPENAI_API_KEY`.

> Начни с Варианта А (проще), если ключей нет. Если есть ключ OpenAI — включи Вариант B.
> 

```python
# agents.py
import os
from typing import List, Dict, Any

from smolagents import (
    CodeAgent,
    InferenceClientModel,   # Вариант А (Hugging Face / Together / и др. провайдеры)
    OpenAIServerModel,      # Вариант B (OpenAI-совместимые API)
    GoogleSearchTool,       # если позже подключишь Serper/SerpAPI
    VisitWebpageTool,
)
from smolagents import DuckDuckGoSearchTool  # веб-поиск без ключа
from tools import calculate_cargo_travel_time

# ---------- 0) Выбор модели ----------
USE_OPENAI = bool(os.getenv("OPENAI_API_KEY"))

def build_model():
    """
    Возвращает абстракцию модели для smolagents.
    Вариант А (по умолчанию): Together через InferenceClientModel (пример).
    Вариант B: OpenAI при наличии OPENAI_API_KEY.
    """
    if USE_OPENAI:
        # Вариант B: OpenAI
        model_id = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
        return OpenAIServerModel(
            model_id=model_id,
            temperature=0.2,
            max_tokens=2000,
        )
    else:
        # Вариант А: Together / другой провайдер, модель из HF Hub
        # Пример: Qwen кодер; можно заменить на более простую чат-модель
        return InferenceClientModel(
            model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
            provider="together",
            max_tokens=2000,
        )

# ---------- 1) Web-агент ----------
def build_web_agent():
    """
    Агент «умеет гуглить и читать страницы».
    Если нет ключей для Serper/SerpAPI — используем DuckDuckGoSearchTool.
    """
    model = build_model()

    # Если позже настроишь SERPER_API_KEY или SERPAPI_API_KEY — можно заменить на GoogleSearchTool
    search_tool = DuckDuckGoSearchTool()  # просто и без ключей
    browse_tool = VisitWebpageTool()

    web_agent = CodeAgent(
        model=model,
        tools=[search_tool, browse_tool, calculate_cargo_travel_time],
        name="web_agent",
        description="Browses the web to find information and can compute travel time.",
        verbosity_level=1,
        max_steps=8,
    )
    return web_agent

# ---------- 2) Manager-агент ----------
SYSTEM_PROMPT_MANAGER = """You are a manager agent.
- Decompose the user's task into steps.
- Use the web_agent to search and open pages when needed.
- Use the tool calculate_cargo_travel_time to compute transfer time from Gotham (40.7128, -74.0060) to each location.
- When you have data, prepare a small table and generate a Plotly map (scatter_geo) with points colored by travel time.
- Save the image to 'saved_map.png'. Then return a short textual summary.
"""

def build_manager_agent(web_agent):
    model = build_model()

    manager_agent = CodeAgent(
        model=model,
        tools=[calculate_cargo_travel_time],
        managed_agents=[web_agent],  # <- главное: менеджер «управляет» web_agent
        system_prompt=SYSTEM_PROMPT_MANAGER,
        additional_authorized_imports=[
            "plotly", "plotly.express", "pandas"
        ],
        planning_interval=3,  # каждые N шагов — мини-план
        verbosity_level=2,    # видно мысли/шаги
        max_steps=15,
    )
    return manager_agent

```

**Что важно в этом файле:**

- `managed_agents=[web_agent]` — ключевая строчка: у менеджера появляется «подчинённый» агент.
- `tools=[...]` — **только** те функции, которыми может пользоваться именно этот агент.
- `additional_authorized_imports` — белый список импортов, которые агент сможет использовать при генерации кода.
- `system_prompt` — правила: *как думать*, *когда вызывать инструменты*, *что сохранить*.

---

# 4) Запуск сценария и «куда смотреть в выводе»

Создай **`run_demo.py`**:

```python
# run_demo.py
from agents import build_web_agent, build_manager_agent

if __name__ == "__main__":
    web_agent = build_web_agent()
    manager = build_manager_agent(web_agent)

    # Задача (можно менять)
    task = (
        "Find several Batman filming locations around the world. "
        "For each location, compute cargo flight time from Gotham (40.7128, -74.0060). "
        "Return a concise table (location, hours). "
        "Then create a Plotly scatter_geo world map colored by travel time and save to 'saved_map.png'. "
        "Finally, give me a short textual summary."
    )

    result = manager.run(task)
    print("\n=== FINAL SUMMARY ===")
    print(result)
    print("\nIf everything worked, check saved_map.png in the project folder.")

```

Запускаем:

```bash
python run_demo.py

```

**На что смотреть в логах:**
• `Thought:` — агент планирует следующий шаг.
• `Action:` — вызывает инструмент (поиск/просмотр/наш калькулятор).
• `Observation:` — подставляется фактический результат инструмента.
• Если шагов много — поиграйся с `max_steps` и `planning_interval`.⚠️ **Важно**: DuckDuckGoSearchTool без ключей прост и ограничен. Результаты будут разными и не всегда «сказочно точными». Для стабильности позже подключай Serper/SerpAPI или заранее подай список локаций как вход.

### **5) Упрощение: если поиск «шумит»**

Если на старте слишком «шумно», дай менеджеру **готовый список** 3–6 локаций (строкой внутри задания), чтобы он сразу перешёл к расчётам и карте. Так лучше видно механику «менеджер → инструмент → карта», без веб-шума.

### **6) Как это «мульти» и «зачем» (коротко)**

Один **Web-агент** держит контекст веб-поиска (историю браузинга).
• **Manager** не «засоряет» свой контекст сайтами, он планирует и агрегирует.
• Отделение памяти = меньше токенов на шаг → быстрее/дешевле и надёжнее.
• Легко добавлять новых «спецов»: **Retriever-агент** (RAG), **Код-агент для расчётов**, **Визуал-агент** и т.п.

### **7) Частые проблемы и как чинить**

- **«Ничего не нашёл» / странные результаты поиска.**
Попробуй переформулировать задание проще, добавь несколько известных локаций прямо в prompt, или подключи Serper/SerpAPI.
- **Не создался `saved_map.png`.**
Проверь `additional_authorized_imports` (нужны `plotly`, `plotly.express`, `pandas`) и что установлен `kaleido`.
- **Модель «теряется»/«галлюцинирует».**
Снизь `temperature`, увеличь `verbosity_level` (увидишь шаги), накрути системный промпт — чётче опиши формат.
- **Шагов не хватает.**
Увеличь `max_steps`, добавь `planning_interval=2..5`.

---

### Основные выводы:

1. **Агент = Модель + Инструменты + Правила (system prompt).**
2. **Multi-agent = разделяй роли и память.** Менеджер делегирует, спец-агенты делают свою часть.
3. **Смотри в Thought/Action/Observation** — это твой дебаг.
4. Сначала добейся **рабочей механики** (пусть даже на 3 вручную заданных точках), потом усложняй поиск, RAG, карты и пр.

### **Куда развивать дальше**

• Подключить **GoogleSearchTool** (нужен `SERPER_API_KEY` или `SERPAPI_API_KEY`) для стабильного поиска.
• Добавить **Retriever-агента (RAG)**: вытаскивать координаты из локальной векторной базы и смешивать с веб-поиском.
• Вынести всё в **API (FastAPI)** и сделать простую страницу «вопрос → ответ → картинка».
• Заменить модель на более сильную (OpenAI / Together) и сравнить поведение.
Готово! Теперь у тебя есть минимальная, но настоящая **мультиагентная** система: менеджер + веб-агент + собственный инструмент + визуализация.

[Все уроки](https://learnvibecoding.ru/publiclessons.md) · HTML: https://learnvibecoding.ru/publiclessons