MAATRIX / Блог / CrewAI: команда агентов на своём сервере

CrewAI: команда агентов на своём сервере

MAATRIX

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

Зачем делить одного агента на роли

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

CrewAI предлагает другую схему: вместо одного агента — команда (crew) из нескольких, каждый со своей узкой ролью:

  • Исследователь (researcher) — собирает факты по теме, ничего не интерпретирует, просто находит и фиксирует информацию с источниками.
  • Аналитик (analyst) — берёт сырые факты и выделяет из них выводы, на которые можно опереться, отбрасывает лишнее и противоречивое.
  • Писатель (writer) — получает готовые выводы и собирает из них связный текст, не добавляя фактов от себя.

Ключевая практическая выгода — узкий промпт под узкую роль почти всегда даёт более качественный результат для этой конкретной подзадачи, чем один универсальный промпт, пытающийся охватить всё сразу. Промпт исследователя можно жёстко ограничить «не делай выводов, только факты», и модель в этой роли действительно реже скатывается в домыслы — ей не нужно одновременно держать в голове ещё и требования к стилю финального текста. То же с писателем: если ему не нужно самому проверять факты, он лучше следит за структурой и языком.

Второй эффект — разбиение сложной задачи на этапы облегчает отладку. Когда весь процесс — один сплошной поток рассуждений одного агента, понять, где именно результат пошёл не так, тяжело: ошибка размазана по всей цепочке мыслей. Когда задача разбита на роли с явной передачей результата между ними, у вас есть контрольные точки — можно посмотреть, что именно вернул исследователь, что из этого взял аналитик, и на каком именно шаге появилось искажение. Это не делает многоагентную систему умнее исходной модели — та же модель под капотом с теми же ограничениями, — но структурирует процесс так, что разбираться в сбоях проще. Общую теорию таких схем и паттерн «оркестратор-воркеры» мы разбирали отдельно в статье мультиагентные системы: несколько LLM-агентов вместе — здесь сосредоточимся конкретно на CrewAI как инструменте.

Из чего состоит команда в CrewAI

CrewAI строится на трёх понятиях: Agent, Task и Crew.

Agent — это роль. Задаётся через role (кто это), goal (какую цель преследует) и backstory (короткая предыстория, которая задаёт манеру поведения — например, «дотошный аналитик, который не выдаёт мнение за факт»). У агента можно указать модель (llm), набор инструментов (tools) и включить подробный лог рассуждений (verbose=True).

Task — конкретная задача, привязанная к агенту: description (что сделать), expected_output (в каком виде ожидается результат) и, что важно, context — список предыдущих задач, результат которых нужно передать этой. Именно через context реализуется передача данных между ролями: аналитик получает не сырой промпт, а результат задачи исследователя.

Crew — сама команда: список агентов, список задач и process — то, как задачи выполняются относительно друг друга. Здесь два основных варианта:

ПроцессКак передаются задачиКогда использовать
Process.sequentialЖёсткий порядок: задача 2 видит результат задачи 1 через context, задача 3 — результат задачи 2Порядок шагов известен заранее, пайплайн предсказуем (исследователь → аналитик → писатель)
Process.hierarchicalОтдельный агент-менеджер сам решает, какому агенту какую подзадачу отдать и в каком порядкеНабор шагов заранее не фиксирован, нужна гибкость — но это ещё один вызов модели (менеджера) на каждое решение

Для большинства практических задач на старте достаточно Process.sequential — он предсказуем и его проще отлаживать. Process.hierarchical добавляет гибкость ценой ещё одного слоя рассуждений (и вызовов модели), и есть смысл переходить на него, только когда жёсткий порядок реально не подходит под задачу.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Установка CrewAI и подключение локальной модели

Разворачиваем на чистом сервере с Ubuntu. Понадобится Python и виртуальное окружение:

apt update && apt install -y python3-venv python3-pip
python3 -m venv venv && source venv/bin/activate
pip install crewai crewai-tools

Синтаксис фреймворка меняется между версиями быстрее, чем у зрелых библиотек, — после установки сверьтесь с официальной документацией CrewAI на предмет актуальных названий параметров, если что-то из примеров ниже не заработает как ожидается.

Дальше — подключение модели. Если вы хотите держать всё на своём сервере без внешних API, локальная модель через Ollama — рабочий вариант: CrewAI использует LiteLLM под капотом и понимает провайдерную строку вида ollama/<модель>:

from crewai import LLM

llm = LLM(
    model="ollama/llama3.1",
    base_url="http://localhost:11434",
)

Сам сервер под Ollama и требования к GPU/VRAM под конкретный размер модели мы разбирали отдельно в статье как поднять локальный запуск LLM через Ollama на сервере — для CrewAI эти требования не меняются, модель работает так же, просто к ней теперь обращается несколько ролей по очереди вместо одной.

Отдельный честный нюанс: не всякая локальная модель одинаково хорошо держит роль. Небольшие модели (единицы миллиардов параметров) чаще «выпадают» из заданной роли — писатель начинает домысливать факты, аналитик пересказывает сырые данные вместо выводов. Прежде чем строить сложную команду, проверьте на паре ручных запросов, что модель вообще нормально следует системному промпту конкретной роли — если нет, многоагентная схема унаследует эту проблему на каждом шаге, а не решит её.

Практика: три агента собирают обзор

Соберём минимальную команду из трёх ролей на паттерне «исследователь → аналитик → писатель»:

from crewai import Agent, Task, Crew, Process, LLM

llm = LLM(model="ollama/llama3.1", base_url="http://localhost:11434")

researcher = Agent(
    role="Исследователь",
    goal="Собрать проверяемые факты по теме {topic}",
    backstory="Дотошный аналитик, который не выдаёт мнение за факт и указывает источник каждого пункта.",
    llm=llm,
    verbose=True,
)

analyst = Agent(
    role="Аналитик",
    goal="Структурировать факты в выводы, на которые можно опереться",
    backstory="Скептик, который перепроверяет цифры и отбрасывает противоречивые данные.",
    llm=llm,
    verbose=True,
)

writer = Agent(
    role="Писатель",
    goal="Собрать связный текст на основе готовых выводов",
    backstory="Пишет ясно и по делу, не добавляет фактов от себя.",
    llm=llm,
    verbose=True,
)

research_task = Task(
    description="Собери факты по теме: {topic}. Только факты, без интерпретации.",
    expected_output="Список фактов с указанием источника по каждому пункту",
    agent=researcher,
)

analysis_task = Task(
    description="Проанализируй факты из предыдущего шага, выдели ключевые выводы",
    expected_output="3-5 выводов, каждый со ссылкой на исходный факт",
    agent=analyst,
    context=[research_task],
)

writing_task = Task(
    description="Напиши связный текст на основе выводов аналитика",
    expected_output="Готовый текст на 300-500 слов",
    agent=writer,
    context=[analysis_task],
)

crew = Crew(
    agents=[researcher, analyst, writer],
    tasks=[research_task, analysis_task, writing_task],
    process=Process.sequential,
    verbose=True,
)

result = crew.kickoff(inputs={"topic": "рынок GPU-серверов в Великобритании"})
print(result)

При verbose=True в консоль идёт полный лог рассуждений каждого агента — что он получил на входе, какие шаги предпринял, что вернул. На старте обязательно держите этот режим включённым: без него команда работает как чёрный ящик, и при неудачном результате у вас нет зацепок, чтобы понять, на каком шаге он испортился.

Честная сложность: непредсказуемость, стоимость, отладка

Многоагентная схема решает реальную проблему специализации, но у неё есть три цены, о которых стоит говорить прямо, а не мелким шрифтом в конце.

Непредсказуемость. Координация нескольких независимо рассуждающих агентов добавляет дополнительный уровень неопределённости по сравнению с одним агентом. Каждый агент делает свой собственный проход рассуждений с собственной вариативностью, и на выходе команды эти вариации накладываются друг на друга: разброс между запусками на одном и том же входе может быть заметно шире, чем у одного агента с тем же промптом. Это не баг конкретной сборки, а системное свойство — чем больше независимых шагов рассуждения в цепочке, тем больше точек, где результат может уйти в сторону. Снизить это можно уменьшением температуры на ролях, где важна стабильность (аналитик, писатель), и жёсткими требованиями к expected_output, но полностью убрать разброс не получится.

Стоимость. Задача, которую решают три агента последовательно, обычно требует в несколько раз больше вызовов модели, чем решение той же задачи одним агентом, — это ориентир, а не измеренная цифра, и точный множитель зависит от числа ролей, длины промптов и того, сколько раз задача возвращается на доработку. Для облачного API это в первую очередь вопрос счёта. Для локальной модели на своём сервере это вопрос пропускной способности: если модель обслуживает ещё и другие запросы (например, несколько пользователей одновременно), последовательные вызовы трёх-четырёх ролей вместо одного заметно увеличивают время, которое каждый пользовательский запрос проводит в очереди. Как устроена нагрузка на локальную LLM и что смотреть, если ответы стали заметно медленнее, чем раньше, мы разбирали в статье как мониторить нагрузку локальной LLM — с многоагентной схемой к этим метрикам стоит присматриваться внимательнее, чем с одиночным агентом.

Отладка. Понять, какой именно агент или этап внёс ошибку в сложной цепочке взаимодействий, сложнее, чем при одном агенте — особенно если задачи возвращаются на доработку или используется Process.hierarchical, где менеджер сам перераспределяет работу. Без подробного лога каждого промежуточного результата (не только финального ответа команды, а того, что конкретно передал исследователь аналитику и что аналитик передал писателю) разбор инцидента постфактум превращается в гадание. Отдельная категория риска — агент, зацикливающийся на одном и том же неудачном шаге и без остановки повторяющий вызовы модели; в многоагентной схеме такой сбой на одной роли может застопорить всю цепочку. Механику таких зацикливаний и защиту от них мы разбирали в статье ИИ-агент зациклился и сжёг лимиты за ночь — рекомендации оттуда (жёсткие лимиты шагов, таймауты) стоит применять к каждой роли в команде, а не только к системе в целом.

С чего начинать и когда усложнять

Практический совет, который экономит больше времени, чем любая оптимизация промптов: начинайте с простой конфигурации из минимального числа ролей — двух, в крайнем случае трёх, — и Process.sequential. Не проектируйте сложную многоагентную архитектуру заранее «на всякий случай», предполагая, что задаче потребуется пять специализированных ролей и менеджер, который ими руководит.

Добавляйте роль или переходите на Process.hierarchical только тогда, когда реально обнаружили конкретную проблему, которую решает именно разделение — например:

  • Один агент регулярно путает факты с интерпретацией → выделяете отдельную роль исследователя с жёстким запретом на выводы.
  • Финальный текст плывёт по структуре, потому что агент одновременно анализирует и пишет → разводите анализ и написание на разные роли.
  • Порядок шагов реально не фиксирован и зависит от входных данных → тогда, и только тогда, есть смысл в менеджере и Process.hierarchical.

Если ни одной такой конкретной проблемы нет, а есть только общее ощущение «наверное, с несколькими ролями будет надёжнее» — скорее всего, надёжнее не станет, а сложность отладки и число вызовов модели вырастут без ощутимой пользы. Многоагентная система — это ответ на найденную проблему специализации, а не архитектура по умолчанию.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть ИИ на сервере

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Нужен ли GPU для CrewAI?

Самому фреймворку — нет, это оркестрация на CPU. GPU нужен модели, к которой обращаются агенты, если вы используете локальную модель через Ollama, а не облачный API.

Можно ли смешивать локальную и облачную модель в одной команде?

Да, у каждого Agent свой параметр llm, ролям можно назначать разные модели — например, более сильную модель писателю и облачную или локальную попроще исследователю.

Чем Process.hierarchical отличается от простого списка задач по очереди?

В Process.hierarchical появляется отдельный агент-менеджер, который сам решает, какому агенту какую подзадачу отдать, — это гибче, но добавляет ещё один вызов модели на каждое такое решение и усложняет отладку.

Стоит ли начинать сразу с четырёх-пяти ролей, если задача выглядит сложной?

Нет — начните с одной-двух ролей и посмотрите на реальный результат. Дополнительные роли добавляйте под конкретно найденную проблему, а не заранее.

Как понять, что именно сломалось, если результат команды плохой?

Держите verbose=True включённым на старте и логируйте промежуточный вывод каждой задачи, а не только финальный ответ — иначе локализовать проблему в цепочке из нескольких ролей практически невозможно.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →