はじめに: CrewAI とエージェント チーム パラダイム
CrewAI AI エージェントのチームを調整するために設計されたオープンソースの Python フレームワークです 企業世界に触発されたパラダイムを通じて、各エージェントは、 特定の役割、 明確な目標を持ち、他のチームメンバーと協力して複雑なタスクを完了します。とは異なります フローをグラフとしてモデル化する LangGraph と、エージェント間の自由な会話に基づく AutoGen の、 CrewAI は直感的なメタファーを採用しています。 作業チーム メンバーそれぞれがスキルを持っているところ 明確な専用ツールと明確に定義された責任。
2024年生まれバージョンに到達しました 0.80+ 2026 年、CrewAI は急速な成長を遂げました 使いやすさと学習曲線が非常に低いため、人気があります。他の人がいる場所 フレームワークでは、状態グラフ、非同期メッセージングなどの高度な概念を理解する必要があります。 CrewAI を使用すると、数十の通信プロトコルで機能するマルチエージェント システムを定義できます。 コード行数。これは、限定されたフレームワークであることを意味するものではありません。そのアーキテクチャはプロセスをサポートします。 逐次的、階層的、合意に基づいた長期記憶、数十のツールとの統合、 運用環境への展開。
CrewAI の強みはメンタルモデルの明瞭さにあります。エージェントのチームを設計するとき CrewAI では、私たちは作業チームを編成する必要があるマネージャーとまったく同じように考えます。「人材とは誰なのか」 そうですね、どのようなスキルが必要か、誰が何を、どの順序で、どのツールを使用して行うかです。この自然な類似性 アイデアから実装までにかかる時間を大幅に短縮します。
この記事で学べること
- CrewAI アーキテクチャ: エージェント、タスク、クルー、ツール、およびそれらの接続方法
- 効果的な役割、目的、バックストーリーを持つエージェントを定義する方法
- タスク管理: Expected_output、コンテキスト、委任
- プロセスの種類: 順次、階層、およびそれぞれをいつ使用するか
- デコレータを使用してカスタム ツールを作成する方法
@toolおよび BaseTool クラス - エージェント間のメモリおよびコンテキスト共有システム
- 完全なケーススタディ: 3 人のエージェントを含むコンテンツ作成チーム
- CrewAI、LangGraph、AutoGen の実際的な比較
- 運用環境での使用のベスト プラクティスと制限事項
CrewAI アーキテクチャ
CrewAI のアーキテクチャは、相乗効果を発揮する 4 つの基本概念に基づいています。 エージェント, タスク, クルー e ツール。理解する これらのコンポーネントがどのように接続されるかが、効果的なマルチエージェント システムを設計する鍵となります。
4つの柱
- エージェント: 役割、目標、背景ストーリーを持つ自律的な存在。すべてのエージェント LLM テンプレートと、オプションでツールセットにアクセスできます。エージェントは「誰」、つまり誰が仕事をするのかを表します。
- タスク: 明確な説明、期待される出力、および割り当てられたエージェントを含む作業単位。 タスクとは「何を」、つまり何をする必要があるのかです。
- クルー: エージェントとタスクをまとめ、実行プロセスを定義し、 調整を管理します。スタッフは「方法」、つまり仕事をどのように組織するかに関係します。
- ツール: エージェントが外界と対話するために呼び出すことができる関数 (Web の検索、ファイルの読み取り、API のクエリ)。ツールとは「何を使用するか」、つまりどのツールを使用するかです。
建築計画
Architettura CrewAI:
+-------------------------------------------------+
| CREW |
| (processo: sequential / hierarchical) |
| |
| +-------------+ +-------------+ +-----------+ |
| | AGENT 1 | | AGENT 2 | | AGENT 3 | |
| | role: ... | | role: ... | | role: ... | |
| | goal: ... | | goal: ... | | goal: ... | |
| | tools: [A,B]| | tools: [C] | | tools: [] | |
| +------+------+ +------+------+ +-----+-----+ |
| | | | |
| +------v------+ +------v------+ +-----v-----+ |
| | TASK 1 | | TASK 2 | | TASK 3 | |
| | description | | description | | descript. | |
| | expected_ | | context: | | context: | |
| | output | | [task1] | | [task1,2] | |
| +-------------+ +-------------+ +-----------+ |
+-------------------------------------------------+
フローは明確です。クルーはタスクの実行を調整し、プロセスに基づいてタスクをエージェントに割り当てます。 設定されています。各タスクは次のように受け取ることができます コンテクスト 前のタスクの出力、作成 各エージェントが他のエージェントの作業に基づいて構築される依存関係の連鎖。このコンテキストメカニズムは、 CrewAI におけるコラボレーションの中心です。
エージェントを定義する
CrewAI では、各エージェントは 4 つの基本プロパティによって定義されます。 role, goal,
backstory e tools。これらのプロパティは単なるメタデータではなく、統合されています。
エージェントのシステム プロンプト内で実行され、基礎となる LLM の動作に直接影響します。エージェント
明確に定義されたものは、一般的なプロパティを持つものよりも大幅に優れた結果を生成します。
エージェントのプロパティ
- 役割: エージェントの専門職名。それはそのアイデンティティとタイプを定義します 彼が持つ専門知識。例: 「シニア データ アナリスト」、「コンテンツ マーケティング ストラテジスト」、「QA エンジニア」。
- ゴール: エージェントが達成しようとする目標。それは具体的で測定可能でなければなりません。 LLM は目標を使用して決定を導き、その出力が適切かどうかを評価します。
- バックストーリー: エージェントにコンテキストと動機を提供する物語。裏話 回答の質を向上させる詳細情報をプロンプトに追加します。これまでの経験、 働き方、基本原則。
- ツール: エージェントが使用できるツールのリスト。ツールを持たないエージェントができることは、 理由を考えてテキストを作成します。ツールを備えたエージェントは、Web を検索し、ファイルを読み取り、計算を実行し、 外部システムと対話します。
実践例: エージェントの定義
from crewai import Agent
from crewai_tools import SerperDevTool, ScrapeWebsiteTool
# Tool per la ricerca web
search_tool = SerperDevTool()
scrape_tool = ScrapeWebsiteTool()
# Agente 1: Ricercatore
researcher = Agent(
role="Senior Research Analyst",
goal="Trovare informazioni accurate e aggiornate su un argomento, "
"verificando le fonti e sintetizzando i dati chiave",
backstory="""Sei un analista di ricerca con 15 anni di esperienza nel
settore tecnologico. Hai lavorato per think tank prestigiosi e sei noto
per la tua capacità di trovare dati affidabili e separare i fatti dalle
opinioni. Il tuo approccio è sempre evidence-based: non affermi nulla
che non sia supportato da fonti verificabili.""",
tools=[search_tool, scrape_tool],
verbose=True,
allow_delegation=False,
max_iter=5,
llm="gpt-4o"
)
# Agente 2: Scrittore
writer = Agent(
role="Content Writer",
goal="Scrivere articoli tecnici coinvolgenti, accurati e ottimizzati "
"per la SEO, basati sui dati forniti dal team di ricerca",
backstory="""Sei un technical writer con esperienza nella comunicazione
scientifica e tecnologica. Sai trasformare dati complessi in narrative
accessibili senza sacrificare la precisione tecnica. I tuoi articoli
sono noti per essere sia informativi che piacevoli da leggere. Segui
le best practice SEO per massimizzare la visibilità dei contenuti.""",
tools=[],
verbose=True,
allow_delegation=False,
llm="gpt-4o"
)
# Agente 3: Editor
editor = Agent(
role="Senior Content Editor",
goal="Revisionare i contenuti per garantire qualità, coerenza, "
"correttezza grammaticale e aderenza alle linee guida editoriali",
backstory="""Sei un editor senior con un occhio impeccabile per i
dettagli. Hai revisionato centinaia di articoli tecnici e sai
individuare errori logici, imprecisioni tecniche e problemi di
struttura. Il tuo feedback è sempre costruttivo e orientato al
miglioramento del contenuto finale.""",
tools=[],
verbose=True,
allow_delegation=False,
llm="gpt-4o"
)
効果的なバックストーリーのためのヒント
バックストーリーは、一般的なフレーズを入力するためのオプションのフィールドではありません。それは最も多くのものの一つです エージェントの動作を制御するのに強力です。最適な書き方は次のとおりです。
- 特異性:「15年のフィンテック経験」は「豊富な経験」よりも優れている
- 動作原理: エージェントが従う必要があるルールを含めます (「常にソースを確認する」、「明確さを優先する」)。
- アンチパターン: エージェントがしてはいけないことを明示的に示します (「データをでっち上げない」、「無用な専門用語を使用しない」)
- トーンとスタイル: 通信レジスタを定義します (「形式的だがアクセスしやすい」、「直接的かつ簡潔」)
高度なエージェントパラメータ
基本的なプロパティに加えて、CrewAI は、 エージェントの動作:
advanced_agent = Agent(
role="Data Scientist",
goal="Analizzare dataset e produrre insight statistici",
backstory="Esperto di data science con specializzazione in NLP.",
# Parametri avanzati
verbose=True, # Log dettagliato delle operazioni
allow_delegation=True, # Può delegare task ad altri agenti
max_iter=10, # Massimo numero di iterazioni per task
max_rpm=30, # Rate limit: max richieste al minuto
memory=True, # Abilita la memoria dell'agente
cache=True, # Cache dei risultati dei tool
step_callback=None, # Callback custom dopo ogni step
# Configurazione LLM
llm="gpt-4o", # Modello da utilizzare
function_calling_llm=None, # LLM separato per il function calling
max_tokens=4096, # Limite token per risposta
)
タスクと委任
I タスク CrewAI の基本的な作業単位です。各タスクの定義 特定の目標、期待される出力、担当エージェント、およびオプションでコンテキスト 以前のタスクから来ています。タスク定義の質は正比例する スタッフが生み出す結果の質に影響します。
タスクの構造
from crewai import Task
# Task 1: Ricerca
research_task = Task(
description="""Conduci una ricerca approfondita su {topic}.
Devi trovare:
1. Le ultime novità e sviluppi (ultimi 6 mesi)
2. I principali player e le loro soluzioni
3. Trend emergenti e previsioni degli esperti
4. Dati quantitativi (statistiche, market size, growth rate)
5. Almeno 5 fonti affidabili con URL
Concentrati su fonti autorevoli: paper accademici, report di
analisti, documentazione ufficiale e articoli di esperti riconosciuti.""",
expected_output="""Un report di ricerca strutturato con:
- Executive summary (3-5 righe)
- Sezione 'Stato dell'Arte' con i principali sviluppi
- Sezione 'Player Principali' con confronto
- Sezione 'Trend e Previsioni' con dati quantitativi
- Lista delle fonti con URL
Il report deve essere tra 800 e 1200 parole.""",
agent=researcher
)
# Task 2: Scrittura (dipende dalla ricerca)
writing_task = Task(
description="""Basandoti sul report di ricerca fornito, scrivi un
articolo tecnico completo su {topic}.
L'articolo deve:
1. Avere un titolo accattivante e ottimizzato SEO
2. Iniziare con un'introduzione che catturi l'attenzione
3. Sviluppare ogni sezione con esempi pratici
4. Includere code snippet dove appropriato
5. Concludere con takeaway actionable per il lettore
6. Usare un tono professionale ma accessibile""",
expected_output="""Un articolo tecnico di 1500-2000 parole con:
- Titolo SEO-friendly
- Introduzione coinvolgente
- 4-6 sezioni tematiche con sottotitoli H2/H3
- Almeno 2 code snippet pratici
- Conclusione con call-to-action
- Meta description di 150-160 caratteri""",
agent=writer,
context=[research_task] # Riceve l'output della ricerca
)
# Task 3: Revisione (dipende dalla scrittura)
editing_task = Task(
description="""Revisiona l'articolo prodotto dal writer.
Verifica:
1. Correttezza tecnica di tutte le affermazioni
2. Coerenza logica e strutturale
3. qualità della scrittura (grammatica, stile, leggibilità)
4. Ottimizzazione SEO (keyword density, meta tags)
5. Completezza rispetto al brief iniziale
Fornisci l'articolo finale corretto, non solo il feedback.""",
expected_output="""L'articolo finale revisionato e pronto per la
pubblicazione, con tutte le correzioni applicate. In coda,
includi una sezione 'Note Editoriali' con le modifiche effettuate
e la valutazione complessiva (voto da 1 a 10).""",
agent=editor,
context=[research_task, writing_task]
)
コンテキストパラメータ
パラメータ context これは、タスクが情報を共有するメカニズムです。
タスクに context=[task_precedente]、前のタスクの出力が来ます
現在のタスクを実行しているエージェントのプロンプトに自動的に挿入されます。これにより、
各エージェントが同僚の仕事に基づいて構築される依存関係の連鎖。
タスクは、以前の複数のタスクからコンテキストを受け取ることができます。上の例では、エディターは両方を受け取ります。 元の研究報告書と論文の整合性を検証することができます。 研究は最終的なコンテンツです。このパターンの 累積コンテキスト e 全体的な出力の品質を確保するために不可欠です。
エージェント間の委任
エージェントが持っている場合 allow_delegation=True、委任するかどうかを独自に決定できます
乗組員の他のエージェントに対する彼の仕事の一部。このメカニズムは、次の動作を再現します。
チームマネージャーが、同僚の方が特定のサブタスクに適していると認識した場合。
制御されない委任に注意してください
委任は強力であると同時に危険でもあります。エージェントが多すぎる場合は、
allow_delegation=True、システムは循環委任ループに入る可能性があります
ここで、エージェント A が B に委任し、B が A に再び委任します。これを回避するには:
- 調整の役割を持つエージェントに対してのみ委任を有効にする
- Imposta
max_iter反復回数を制限するには - 実際には、保持します
allow_delegation=Falseほとんどのエージェントにとって
プロセスの種類
CrewAI は、タスク オーケストレーションの 2 つの主要なモードをサポートしています。 一連 e 階層的。プロセスの選択によってタスクの実行方法が決まります そしてエージェントがどのように相互作用するか。
逐次処理
その過程で 一連、タスクは順番に次々に実行されます その中でそれらが定義されています。各タスクの出力は、タスクのコンテキストとして利用可能になります。 後続のもの。これは最も単純で予測可能なプロセスであり、線形パイプラインに最適です。 ここで、各フェーズは前のフェーズに依存します。
from crewai import Crew, Process
# Crew con processo sequenziale
crew = Crew(
agents=[researcher, writer, editor],
tasks=[research_task, writing_task, editing_task],
process=Process.sequential,
verbose=True
)
# Esecuzione
result = crew.kickoff(
inputs={"topic": "AI Agents nel 2026"}
)
print(result.raw) # Output finale come stringa
print(result.token_usage) # Token consumati per agente
Flusso Sequential:
[research_task] --output--> [writing_task] --output--> [editing_task]
| | |
researcher writer editor
| | |
"Report di "Articolo "Articolo
ricerca" bozza" finale"
階層的なプロセス
その過程で 階層的, CrewAI が自動的に導入します。 マネージャーエージェント チームの仕事を調整する人。マネージャーはタスクを分析し、実行順序を決定し、割り当てます。 タスクを最も適切なエージェントに送信し、修正が必要になる場合があります。このプロセスはより柔軟ですが、 マネージャーは状況に基づいて自律的な決定を下すため、予測はさらに困難です。
from crewai import Crew, Process
# Crew con processo gerarchico
crew = Crew(
agents=[researcher, writer, editor],
tasks=[research_task, writing_task, editing_task],
process=Process.hierarchical,
manager_llm="gpt-4o", # LLM per il manager agent
verbose=True
)
result = crew.kickoff(
inputs={"topic": "AI Agents nel 2026"}
)
Flusso Hierarchical:
+-------------------+
| MANAGER AGENT |
| (creato da CrewAI) |
+--------+----------+
|
+--------------+--------------+
| | |
v v v
[researcher] [writer] [editor]
| | |
v v v
"Risultato" "Risultato" "Risultato"
| | |
+--------------+--------------+
|
v
Output Finale
プロセス間の比較
| 特性 | 一連 | 階層的 |
|---|---|---|
| 予測可能性 | 上位 - 固定順序 | 平均 - マネージャーが決定します |
| 柔軟性 | 低剛性パイプライン | 高度な動的適応 |
| トークンコスト | 予測可能 | 変数(追加マネージャー) |
| 複雑 | 最小限 | 平均 |
| 理想的な使用例 | 線形パイプラインとメモ | 複雑な依存関係を持つタスク |
| デバッグ | シンプル - 直線的な流れ | 複雑 - マネージャーの決定 |
実際のプロセスでは、 一連 ほとんどの人に推奨される選択肢です ユースケースの説明。予測可能性が高く、デバッグが容易で、トークンのコストが安くなります。 階層プロセスは、調整ロジックが複雑で調整できない場合に役立ちます。 事前に静的に定義されていますが、変動性と追加コストが発生し、 最も信頼性の低いシステム。
カスタムツール
ツールはエージェントと外部世界との間の架け橋です。 CrewAI は 2 つのアプローチをサポートしています。
カスタム ツールを定義します: デコレータ @tool 単純な機能の場合
そして クラス BaseTool より複雑なツールが必要な場合
内部ステータスまたは詳細設定。
デコレータ付きツール
from crewai.tools import tool
@tool("Search Database")
def search_database(query: str, table: str = "products") -> str:
"""Cerca nel database aziendale informazioni su prodotti,
clienti o ordini.
Args:
query: Termine di ricerca.
table: Tabella da interrogare (products, customers, orders).
Returns:
Risultati della ricerca formattati.
"""
import sqlite3
conn = sqlite3.connect("company.db")
cursor = conn.execute(
f"SELECT * FROM {table} WHERE name LIKE ?",
(f"%{query}%",)
)
results = cursor.fetchall()
conn.close()
if not results:
return f"Nessun risultato trovato per '{query}' nella tabella {table}."
formatted = [str(row) for row in results[:10]]
return f"Trovati {len(results)} risultati:\n" + "\n".join(formatted)
@tool("Calculate Metrics")
def calculate_metrics(data: str, metric_type: str = "mean") -> str:
"""Calcola metriche statistiche sui dati forniti.
Args:
data: Dati numerici separati da virgola (es. '10,20,30,40').
metric_type: Tipo di metrica: mean, median, std, min, max.
Returns:
Il valore della metrica calcolata.
"""
import statistics
values = [float(x.strip()) for x in data.split(",")]
metrics = {
"mean": statistics.mean,
"median": statistics.median,
"std": statistics.stdev if len(values) > 1 else lambda x: 0,
"min": min,
"max": max,
}
if metric_type not in metrics:
return f"Metrica '{metric_type}' non supportata. Usa: {list(metrics.keys())}"
result = metrics[metric_type](values)
return f"{metric_type} di {values}: {result:.4f}"
BaseToolクラスを使用したツール
内部状態、永続的な接続、または初期化ロジックを必要とするツールの場合
複雑なクラスですが、CrewAI が提供します BaseTool:
from crewai.tools import BaseTool
from pydantic import BaseModel, Field
from typing import Type
class APISearchInput(BaseModel):
"""Schema di input per il tool di ricerca API."""
endpoint: str = Field(description="Endpoint API da interrogare")
params: str = Field(
default="",
description="Parametri della query in formato key=value separati da &"
)
class APISearchTool(BaseTool):
name: str = "API Search"
description: str = (
"Interroga un'API REST esterna per recuperare dati. "
"Supporta endpoint GET con parametri di query."
)
args_schema: Type[BaseModel] = APISearchInput
base_url: str = "https://api.example.com"
api_key: str = ""
def _run(self, endpoint: str, params: str = "") -> str:
"""Esegue la richiesta API."""
import requests
url = f"{self.base_url}/{endpoint}"
headers = {"Authorization": f"Bearer {self.api_key}"}
query_params = {}
if params:
for pair in params.split("&"):
key, value = pair.split("=")
query_params[key.strip()] = value.strip()
try:
response = requests.get(
url, headers=headers, params=query_params, timeout=10
)
response.raise_for_status()
return str(response.json())
except requests.RequestException as e:
return f"Errore nella richiesta API: {str(e)}"
# Utilizzo
api_tool = APISearchTool(
base_url="https://api.example.com/v2",
api_key="your-api-key"
)
CrewAI 定義済みツール
CrewAI は、パッケージを通じて事前定義されたツールの豊富なセットを提供します crewai-tools:
from crewai_tools import (
SerperDevTool, # Ricerca web via Serper.dev
ScrapeWebsiteTool, # Web scraping
WebsiteSearchTool, # Ricerca semantica su un sito
FileReadTool, # Lettura file
DirectoryReadTool, # Listing directory
PDFSearchTool, # Ricerca in file PDF
CSVSearchTool, # Ricerca in file CSV
JSONSearchTool, # Ricerca in file JSON
CodeDocsSearchTool, # Ricerca in documentazione codice
YoutubeVideoSearchTool, # Ricerca in video YouTube
)
# Configurazione
search = SerperDevTool()
scraper = ScrapeWebsiteTool()
pdf_reader = PDFSearchTool(pdf="report.pdf")
csv_reader = CSVSearchTool(csv="data.csv")
ツールの説明とエージェントの品質
La description ツールが正しく機能するためには最も重要な部分です
エージェントの。 LLM は、記述のみに基づいてどのツールを呼び出すかを決定します。
「検索」のようなあいまいな説明は、誤った呼び出しにつながります。正確な説明
例: 「検索エンジンを使用して Web 上の情報を検索し、最初の 5 件の結果を返します」
タイトル、URL、スニペット付き」を使用すると、LLM はツールをいつどのように使用するかを正確に決定できます。
メモリとコンテキストの共有
CrewAI は、エージェントが共有できるマルチレベルの記憶システムを実装しています。 情報を収集し、以前のやり取りを記憶し、時間の経過とともに知識を蓄積します。システム メモリは、異なる時間スケールで動作する 3 つの異なるコンポーネントで構成されています。
記憶の 3 つのレベル
-
短期記憶: 現在のパフォーマンスに関する情報を保存します
乗組員の。完了したタスク、エージェントの会話、結果からの出力が含まれます
ツールの。実行の終了時にゼロにリセットされます。そしてパラメータを動かすメカニズム
contextタスクの。 - 長期記憶: 実行間で持続します。学んだ教訓を記憶し、 良い結果をもたらした成功パターンと戦略。データベースを使用する 永続性のためにローカル (SQLite)。これは、同じクルーを繰り返し実行する場合に便利です 同様のタスクについて。
- エンティティメモリ: 実行中に言及されたエンティティのログを維持します。 実行(人、組織、製品、コンセプト)。エージェントが構築できるようにする 彼らが活動する領域についての累積的な理解。
メモリ構成
from crewai import Crew, Process
crew = Crew(
agents=[researcher, writer, editor],
tasks=[research_task, writing_task, editing_task],
process=Process.sequential,
# Configurazione memoria
memory=True, # Abilita il sistema di memoria
embedder={
"provider": "openai",
"config": {
"model": "text-embedding-3-small"
}
},
verbose=True
)
# Prima esecuzione: la crew impara
result1 = crew.kickoff(inputs={"topic": "AI Agents"})
# Seconda esecuzione: la crew ricorda le lezioni apprese
result2 = crew.kickoff(inputs={"topic": "Multi-Agent Systems"})
タスク間でのコンテキストの共有
Il コンテキストの共有 CrewAI の主要なコラボレーション メカニズムです。いつ
タスクはパラメータ内の他のタスクをリストします context、それらのタスクの出力が来ます
現在のタスクを実行しているエージェントのプロンプトに自動的に組み込まれます。これにより、
各エージェントが前任者の作業にアクセスできる情報チェーン。
# Task con contesto multiplo
final_review = Task(
description="Revisione finale del contenuto completo.",
expected_output="Contenuto approvato e pronto per la pubblicazione.",
agent=editor,
context=[research_task, writing_task] # Accede a entrambi gli output
)
# Il prompt dell'editor includera automaticamente:
# 1. L'output del research_task (report di ricerca)
# 2. L'output del writing_task (articolo bozza)
# L'editor può cosi verificare la coerenza tra ricerca e contenuto
コンテキスト共有が内部でどのように機能するか
タスクに context=[task_a, task_b]、CrewAI がプロンプトを構築します
参照されたタスクの出力を含む専用セクションを含むエージェントの内容:
[System Prompt con role, goal, backstory dell'agente]
Contesto dalle attivita precedenti:
---
Output di Task A:
[output completo di task_a]
---
Output di Task B:
[output completo di task_b]
---
Task corrente:
[description del task corrente]
Expected Output:
[expected_output del task corrente]
これは、前のタスクの出力全体がプロンプトに含まれることを意味します。タスク別
出力が非常に長いため、大量のトークンが消費される可能性があります。それは重要です
定義する expected_output そのため、出力は簡潔ですが完全なものになります。
ケーススタディ: コンテンツ制作スタッフ
コンテンツ作成チームの完全で実用的な例を実装してみましょう。 チームは 3 人の専門エージェントで構成されています。 研究者 集めるもの 情報、 ライター アイテムと エディタ 最終コンテンツをレビューする人。このパターンはあらゆるコンテンツ パイプラインに適用できます 作成: ブログ投稿、ニュースレター、企業レポート、技術文書。
セットアップを完了する
import os
from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool, ScrapeWebsiteTool
# Configurazione API keys
os.environ["OPENAI_API_KEY"] = "your-openai-key"
os.environ["SERPER_API_KEY"] = "your-serper-key"
# --- TOOLS ---
search_tool = SerperDevTool()
scrape_tool = ScrapeWebsiteTool()
# --- AGENTS ---
researcher = Agent(
role="Senior Tech Research Analyst",
goal="Raccogliere informazioni complete, accurate e aggiornate "
"sull'argomento assegnato, con dati quantitativi e fonti verificabili",
backstory="""Sei un analista di ricerca con 12 anni di esperienza
nel settore tecnologico. Hai contribuito a report per Gartner e
Forrester. La tua metodologia prevede:
1. Ricerca iniziale ampia per mappare il panorama
2. Deep dive sulle fonti più rilevanti
3. Verifica incrociata dei dati tra almeno 3 fonti
4. Sintesi strutturata con distinzione tra fatti e opinioni""",
tools=[search_tool, scrape_tool],
verbose=True,
allow_delegation=False,
max_iter=7,
llm="gpt-4o"
)
writer = Agent(
role="Technical Content Writer",
goal="Trasformare i dati di ricerca in un articolo tecnico "
"coinvolgente, accurato e ottimizzato per SEO e leggibilità",
backstory="""Sei un technical writer con 8 anni di esperienza.
Hai scritto per pubblicazioni come Towards Data Science, Dev.to
e documentazione ufficiale di framework open-source. Il tuo stile
combina rigore tecnico e accessibilità: usi analogie concrete,
esempi pratici e una struttura chiara. Ogni articolo che scrivi
segue la formula: hook -> contesto -> profondità -> takeaway.""",
tools=[],
verbose=True,
allow_delegation=False,
llm="gpt-4o"
)
editor = Agent(
role="Senior Technical Editor",
goal="Garantire che l'articolo finale sia impeccabile dal punto "
"di vista tecnico, linguistico e strutturale",
backstory="""Sei un editor con background in computer science e
giornalismo tecnico. Hai revisionato oltre 500 articoli tecnici.
Il tuo processo di revisione:
1. Verifica correttezza tecnica (affermazioni, codice, dati)
2. Analisi strutturale (flusso logico, transizioni, coerenza)
3. Revisione linguistica (grammatica, chiarezza, concisione)
4. Check SEO (titolo, meta description, keyword placement)
Non ti limiti a segnalare problemi: correggi direttamente.""",
tools=[],
verbose=True,
allow_delegation=False,
llm="gpt-4o"
)
# --- TASKS ---
research_task = Task(
description="""Conduci una ricerca approfondita su: {topic}
Requisiti:
- Identifica almeno 5 sviluppi chiave degli ultimi 6 mesi
- Trova dati quantitativi (statistiche, benchmark, market data)
- Raccogli opinioni di esperti riconosciuti
- Individua trend emergenti e previsioni
- Documenta tutte le fonti con URL completi""",
expected_output="""Report di ricerca strutturato (800-1000 parole):
1. Executive Summary (5 righe)
2. Sviluppi Chiave (5+ punti con fonti)
3. Dati Quantitativi (statistiche con fonti)
4. Opinioni di Esperti (citazioni attribuite)
5. Trend Emergenti (3+ previsioni)
6. Bibliografia (5+ fonti con URL)""",
agent=researcher
)
writing_task = Task(
description="""Scrivi un articolo tecnico basato sul report di ricerca.
Specifiche:
- Titolo: accattivante, max 60 caratteri, con keyword principale
- Introduzione: hook + contesto + preview del contenuto
- Corpo: 4-6 sezioni con H2, esempi pratici e dati
- Conclusione: sintesi + takeaway actionable + CTA
- Tono: professionale ma accessibile, in italiano
- Lunghezza: 1500-2000 parole""",
expected_output="""Articolo completo in formato Markdown con:
- Titolo SEO-optimized
- Meta description (155 caratteri)
- 5-7 keyword target
- Contenuto strutturato con H2/H3
- Almeno 2 esempi pratici o code snippet
- Conclusione con 3 takeaway numerati""",
agent=writer,
context=[research_task]
)
editing_task = Task(
description="""Revisiona e finalizza l'articolo.
Checklist di revisione:
- [ ] Tutte le affermazioni tecniche sono corrette
- [ ] I dati citati corrispondono alle fonti
- [ ] La struttura è logica e fluida
- [ ] Non ci sono errori grammaticali o di stile
- [ ] Il titolo e la meta description sono efficaci
- [ ] Il SEO è ottimizzato
- [ ] La lunghezza è nei limiti richiesti
Produci la versione finale corretta dell'articolo.""",
expected_output="""Articolo finale revisionato e pronto per la
pubblicazione, con in coda:
- Note editoriali (modifiche effettuate)
- Score di qualità (1-10)
- Checklist completata""",
agent=editor,
context=[research_task, writing_task]
)
# --- CREW ---
content_crew = Crew(
agents=[researcher, writer, editor],
tasks=[research_task, writing_task, editing_task],
process=Process.sequential,
verbose=True,
memory=True,
embedder={
"provider": "openai",
"config": {"model": "text-embedding-3-small"}
}
)
# --- ESECUZIONE ---
result = content_crew.kickoff(
inputs={"topic": "L'impatto degli AI Agents sulla produttività aziendale nel 2026"}
)
# Accesso ai risultati
print("=== RISULTATO FINALE ===")
print(result.raw)
print(f"\n=== TOKEN USAGE ===")
print(f"Token totali: {result.token_usage}")
典型的な乗組員の成果
実行中、CrewAI はプロセスの各ステップをログに記録し、どのエージェントに属しているかについての詳細を記録します。
仕事をしているか、どのツールを使用しているか、どのような成果物を生成したか。最終結果は出力です
改訂された記事を含む最後のタスク (editing_task) は公開の準備ができています。
フィールド token_usage エージェントごとおよびタスクごとのトークン消費の内訳を提供します。
コスト監視に不可欠です。
CrewAI 対 LangGraph 対 AutoGen
適切なフレームワークを選択するには、アーキテクチャの違いを理解することが重要です CrewAI、LangGraph、AutoGen の間の哲学的なもの。各フレームワークは特定のシナリオで優れています そして、シンプルさ、柔軟性、制御の間にはさまざまなトレードオフが存在します。
詳細な比較
| サイズ | CrewAI | ランググラフ | オートジェン/AG2 |
|---|---|---|---|
| パラダイム | 役割ベースのチーム | グラフステートフル | マルチエージェントの会話 |
| 比喩 | ビジネスチーム | フローチャート | グループチャット |
| 学習曲線 | 低い | 高い | 平均 |
| 柔軟性 | 平均 | 最大 | 高い |
| 典型的なコード行 | 30-80 | 80-200+ | 50-150 |
| 永続的な状態 | 記憶システム | ネイティブチェックポイント設定 | チャット履歴 |
| 人間参加型 | 設定可能 | ネイティブ(割り込み) | ネイティブ(4モード) |
| ツールエコシステム | crewai-tools (リッチ) | ラングチェーンツール | 機能登録 |
| コードの実行 | ツール経由 | カスタムノード | ネイティブ (Docker) |
| 理想的な使用例 | コンテンツパイプライン、構造化されたワークフロー | 分岐を伴う複雑なワークフロー | 反復的なコラボレーションとコード生成 |
CrewAI を選択する場合
- ラピッドプロトタイピング: マルチエージェント システムを稼働させる必要がある場合 できるだけ短い時間で。 API のシンプルさにより、アイデアからプロトタイプまで数分で移行できます。
- 線形パイプライン: ワークフローが一連の明確なステップである場合 (調査 -> 処理 -> レビュー -> 出力)。
- 明確な役割を持つチーム: 各エージェントが明確に定義された役割と明確に定義されていない役割を持っている場合 複雑な調整が必要です。
- コンテンツ制作: CrewAI は、多様なコンテンツ作成パイプラインに優れています。 専門家が順次貢献します。
CrewAI を選択すべきではない場合
- 複雑な分岐ワークフロー: フローに条件付きの決定が必要な場合 複数、特定の出力条件を持つループ、またはサブフローの並列実行、 LangGraph が最良の選択です。
- エージェント間の交渉: エージェントが話し合い、交渉し、収束する必要があるかどうか 会話の反復によるソリューションには、AutoGen の方が適しています。
- 粒度の高い流量制御: CrewAI は多くのフローの詳細を抽象化します 実行。状態遷移をすべて確認する必要がある場合は、LangGraph を使用します。
本番環境のベストプラクティス
本番環境で CrewAI を使用するには、以下のようないくつかの側面に注意する必要があります。 エージェントとタスクの単純な定義を超えています。基本的なベストプラクティスに基づいたものは次のとおりです フレームワークで蓄積された経験に基づいて。
1. 迅速な設計
- 一般的ではなく特定の役割: 「経験豊富なシニア Python バックエンド開発者」 FastAPI と PostgreSQL では、「プログラマー」よりもはるかに優れています。
- 測定可能な目標: 「少なくとも 5 つの情報源を含む 800 ~ 1200 ワードのレポートを作成してください」 「検証可能」は「調査を行う」よりも優れています。
- 期待される詳細な出力: 構造、形式、長さを定義します 期待される出力の。 LLM は、何が関係しているかを正確に把握している場合に、より良い結果を生み出します。 待ってください。
- プロンプトのアンチパターン: してはいけないことについての指示を含めます。 「発明しないでください データ」、「2024 年より前のソースは使用しないでください」により、一般的なエラーを防ぐことができます。
2. コスト管理
# Strategia per il controllo dei costi
crew = Crew(
agents=[researcher, writer, editor],
tasks=[research_task, writing_task, editing_task],
process=Process.sequential,
# Limiti per prevenire costi eccessivi
max_rpm=30, # Rate limit globale
verbose=True, # Monitoring attivo
)
# Dopo l'esecuzione, analizza il consumo
result = crew.kickoff(inputs={"topic": "Test Topic"})
usage = result.token_usage
print(f"Token totali input: {usage.total_tokens}")
print(f"Token totali output: {usage.prompt_tokens}")
print(f"Costo stimato: ${usage.total_tokens * 0.00003:.4f}")
3. エラー処理と回復力
from crewai import Crew, Process
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def run_crew_with_retry(crew, inputs, max_retries=3):
"""Esegue la crew con retry automatico."""
for attempt in range(max_retries):
try:
result = crew.kickoff(inputs=inputs)
logger.info(f"Crew completata al tentativo {attempt + 1}")
return result
except Exception as e:
logger.warning(
f"Tentativo {attempt + 1} fallito: {str(e)}"
)
if attempt == max_retries - 1:
logger.error("Tutti i tentativi esauriti.")
raise
logger.info("Retry in corso...")
return None
4. 乗組員のテスト
import pytest
from unittest.mock import patch, MagicMock
def test_research_agent_configuration():
"""Verifica che l'agente di ricerca sia configurato correttamente."""
assert researcher.role == "Senior Tech Research Analyst"
assert len(researcher.tools) == 2
assert researcher.allow_delegation is False
assert researcher.max_iter == 7
def test_task_context_chain():
"""Verifica la catena di contesto tra i task."""
assert research_task in writing_task.context
assert research_task in editing_task.context
assert writing_task in editing_task.context
def test_crew_process():
"""Verifica il tipo di processo della crew."""
assert content_crew.process == Process.sequential
assert len(content_crew.agents) == 3
assert len(content_crew.tasks) == 3
@patch("crewai_tools.SerperDevTool._run")
def test_crew_execution_mock(mock_search):
"""Test di integrazione con mock dei tool esterni."""
mock_search.return_value = "Risultati di ricerca simulati..."
result = content_crew.kickoff(
inputs={"topic": "Test Topic"}
)
assert result is not None
assert len(result.raw) > 0
制限事項と考慮事項
CrewAI は、その優雅さとシンプルさにもかかわらず、注意すべき重要な制限があります。 本番環境に導入する前に:
CrewAI の主な制限事項
- フローの制御が制限されている: LangGraph とは異なり、これは不可能です カスタム終了条件を使用して複雑な条件分岐またはループを定義します。 フローは基本的に線形 (順次) であるか、マネージャーに委任されています (階層型)。
- 不透明なデバッグ: エージェントが予期しない出力または低い出力を生成した場合 品質が悪いのに、その理由を理解するのは難しいかもしれません。詳細モードは役立ちますが、不足しているのは ステップバイステップのトレースにより、運用環境でのデバッグが困難になります。
- トークン消費量が多い: コンテキスト共有は、 プロンプト内の以前のタスク。チェーンが長いと、トークンの消費量が急速に増加します。 コンテキスト内の 2000 ワードの記事は、後続のタスクごとに約 2500 トークンを消費します。
- LLM への依存: 出力品質はモデルに大きく依存します LLMを選択しました。機能の低いモデル (GPT-3.5、小規模なローカル モデル) では、委任 そして複雑な推論は大幅に低下します。
- フレームワークの成熟度: バージョン 0.80 以降では、API が変更される可能性があります リリース間。重大な変更は、最初のバージョンよりも頻繁ではありませんが、 依存関係の管理には注意が必要です。
- ネイティブ非同期サポートなし: 乗組員は同期して実行されます。 非同期実行が必要なWebアプリケーションの場合はラッピングが必要です 非同期スレッドまたはタスクでの実行。
結論
CrewAI は、マルチエージェント システムの世界への最もアクセスしやすいエントリ ポイントを表します。 彼のビジネス チームのメタファーは、エージェントが直感的に操作できる作業パイプラインの設計を可能にします。 専門家が協力して複雑な目標を達成します。 API のシンプルさは、 電力を犠牲にします: 数十行のコードでシステムを構築できます 自動検索、処理、レビューを調整する洗練されたもの。
CrewAI の主な強みは次のとおりです。 最小限の学習曲線、 の 事前定義ツールの豊富なエコシステム そして メモリシステム マルチレベル。主な制限は次のとおりです ~に対する制限された制御 流れ そしてで トークン消費量が多い 多くのタスクを含むパイプラインの場合。
CrewAI、LangGraph、AutoGen のいずれを選択するかは二者択一ではありません。複雑なアーキテクチャでは、次のことが可能です。 フレームワークを組み合わせる: 構造化された作業チームには CrewAI を使用し、ワークフローには LangGraph を使用します 条件付き分岐と AutoGen を使用して、反復的なネゴシエーションが必要な対話を実現します。 重要なのは、各ツールの長所と限界を理解し、目的に適したツールを選択することです。 システムの各コンポーネント。
次の記事では、詳しく見ていきます AutoGen と AG2、会話の枠組み Microsoft Research による、会話に基づくコミュニケーション モデルの分析 エージェント、コード生成と自己修正サイクル、人間参加型パターン、 Microsoft Agent Framework への移行パス。







