Суть
CrewAI смотрит на MAS как на команду, а не граф (MAS Frameworks): вы «нанимаете» спец-агентов под одну бизнес-цель. Базовые объекты:
- Agent —
role(«Senior Research Analyst»),goal,backstory,tools,llm. - Task —
description,expected_output,agent(кому назначить),context(что подать на вход — обычно output другой задачи). - Crew — команда агентов + список задач + Process;
manager_llmдобавляется только к иерархическому процессу. - Process —
sequentialилиhierarchical. Третьего значения нет: в перечислении лежит закомментированныйconsensual, но он не реализован. Параллельности как режима процесса в CrewAI не существует вовсе — задачи внутри процесса идут по порядку, а параллелизм достигается асинхронным запуском самих команд.
Три классические роли — PM/Planner (декомпозирует, назначает), Developer (исполняет), QA/Critic (ищет дефекты).
Как работает
- Память (
memory=True) — векторное хранилище: short-term (сессия), long-term (постоянная), entity memory (извлечённые сущности: люди, места, концепции). Для production-памяти между сессиями подключают Mem0. - Planning (
planning=True) — доп. фаза: отдельный LLM-запрос анализирует все задачи и строит execution plan до запуска. - allow_delegation — может ли агент делегировать подзадачи другим (в простом пайплайне выключают:
allow_delegation=False). - Дифференцированные модели: «умная» на планирование/критику, дешёвая на исполнение (см. Agent CostControl, Agent Routing).
- Минусы: токен-стоимость высокая (context передаётся между задачами); cycles с feedback-loop дебажить сложно — для жёсткого контроля берут LangGraph; streaming ограничен.
Пример
Эволюция на учебном примере (CRM follow-up для лидов): Stage 1 — один Writer-агент; Stage 2 — crew {Researcher, Planner, Writer, Critic}; Stage 3 — тот же crew + Mem0 (память между сессиями, scoped по user_id=lead_id).
from crewai import Agent, Task, Crew, Process, LLM
llm_strong = LLM(model="openrouter/anthropic/claude-haiku-4.5", # через OpenRouter
api_key=os.environ["OPENROUTER_API_KEY"],
base_url="https://openrouter.ai/api/v1", temperature=0.3)
writer = Agent(
role="B2B Sales Follow-up Writer",
goal="Написать персонализированное follow-up письмо лиду по истории взаимодействий.",
backstory="Опытный B2B sales-копирайтер EdTech-платформы…",
llm=llm_strong, verbose=True, allow_delegation=False,
)
crew = Crew(
agents=[researcher, planner, writer, critic],
tasks=build_tasks(lead_id),
process=Process.hierarchical, # manager_llm работает только здесь
manager_llm=supervisor_llm,
memory=True,
)
result = await crew.kickoff_async()
Три места, где учебный код разошёлся с текущим API
Заметка собрана по материалу, который с тех пор устарел: CrewAI переехал. Расхождения перечислены отдельно, потому что каждое ломается по-своему: одно падает валидацией, второе молчит, третье молча ничего не делает.
| Что в учебном коде | Что на самом деле |
|---|---|
Process.parallel |
Значения нет в перечислении — AttributeError |
manager_llm при Process.sequential |
Параметр читается только на иерархическом пути. Валидация ругается лишь на обратное — отсутствие manager_llm при hierarchical. Здесь же supervisor просто никогда не вызывается, и это не видно ни по ошибке, ни по логу |
memory_config={"provider": "mem0", …} |
Параметра нет. Поле memory принимает bool либо объект Memory / MemoryScope / MemorySlice, и внешняя память подключается через него |
Второй случай стоит отдельного внимания: это не сломанный код, а инертный параметр. Команда работает, результат приходит, стоимость растёт на ровном месте только если supervisor всё-таки где-то дёргается, — а его нет. Ошибку такого рода не ловит ни запуск, ни тест на результат; ловит только чтение того, при каком процессе параметр вообще читается.
Встроенная память или внешний слой
Встроенная память фреймворка привязана к нему и к жизненному циклу запуска: она удобна, пока память нужна одной команде агентов внутри одного процесса и не переживает смену инструмента. Внешний слой (Mem0) нужен, когда выполняется хотя бы одно из трёх: память переживает фреймворк (сегодня CrewAI, завтра граф — переписывать хранилище не хочется); память общая для нескольких систем, а не для одной команды; нужны операции, которых у встроенной нет — извлечение фактов из диалога, разрешение противоречий, дедупликация.
Если ни одно не выполняется, внешний слой добавляет зависимость и сетевой вызов, ничего не покупая. Практический порядок обратный привычному: начинать со встроенной и выносить наружу по первому из трёх признаков, а не проектировать «правильно» сразу.
Связано с
- MAS Frameworks — место CrewAI среди AutoGen/LangGraph/Mastra
- Multi Agent Systems — когда вообще нужна «команда»
- Multi Agent Patterns — роли исполнитель/критик, параллелизм
- Mem0 — память между сессиями для crew
- Agent CostControl — дорогая токен-стоимость как главный минус