CrewAI で GitHub リポジトリ要約システムを構築する
CrewAI を用いたマルチエージェント協調と Weave によるリアルタイムのデバッグおよび可観測性を組み合わせ、完全自動の GitHub ドキュメント生成システムを構築するための実践ガイド。コメント欄で誤訳の可能性があればお知らせください。
Created on August 27|Last edited on August 27
Comment
マルチエージェントシステム複数の AI エージェントが専門化されたタスクで協調するマルチエージェントシステムは、複雑なワークフローを自動化する中核的な手法になりつつあります。 CrewAI は、こうしたシステムを設計するためのプラットフォームで、開発者がタスクを割り当て、エージェントの役割を定義し、ツールを接続して実世界のプロジェクトに対応できるようにします。これに を組み合わせると W&B Weave各エージェントの挙動を追跡・デバッグするためのツールである を組み合わせることで、実行全体に対する完全な可視性とコントロールが得られます エージェント型ワークフロー全体。
このチュートリアルでは、GitHub リポジトリを自動でドキュメント化するマルチエージェントシステムを構築します。エージェントがリポジトリを探索し、コードを要約し、利用ガイドを作成し、アーキテクチャ図を生成し、すべてを HTML ページにまとめます。フローの管理には CrewAI を、各意思決定の過程を監視するには Weave を使用します。

目次
エージェントとは何か?マルチエージェントシステムの理解CrewAI プラットフォームの主な特長チュートリアル:CrewAI と Weave を用いた GitHub リポジトリ自動ドキュメント化のマルチエージェントシステム構築LLM の可観測性とデバッグを強化するための Weave の統合まとめ
エージェントとは何か?
AI エージェント は、計画、外部ツールの活用、記憶の保持、経時的な適応を通じて特定の目標を達成するよう設計された高度なシステムです。あらかじめ定義された硬直的な規則に従う従来の自動化と異なり、AI エージェントは情報を動的に処理し、意思決定を行い、フィードバックに基づいて手法を洗練します。
一方で チャットボット 主に対話に従事し、各ステップでユーザー入力を必要とするのに対し、AI エージェントは自律的に動作します。単に応答を生成するだけでなく、行動を起こし、外部システムとやり取りし、 複数ステップのエージェント型ワークフローを管理する 常時の監督なしで
AI エージェントの主な構成要素は次のとおりです。
- ツールAPI、データベース、ソフトウェアに接続して機能を拡張する。
- メモリタスク間で情報を保持し、一貫性と想起精度を高める。
- 継続学習過去の成果に基づいて戦略を適応・洗練する。
- オーケストレーション複数ステップのプロセスを管理し、タスクを分解し、他のエージェントと連携する。
マルチエージェントシステムの理解
本質的には、マルチエージェントシステムとは、〜のネットワークです 自律型AIエージェント 互いに通信し、調整し合うことで、単一のエージェントでは達成しにくい複雑なタスクをより効率的に遂行します。各エージェントには明確な役割と責務が割り当てられ、専門化が進み、必要に応じて並列処理も可能になります。たとえばニュース集約システムでは、あるエージェントが最新の見出しを収集し、別のエージェントが詳細な分析を行う、といった分担が考えられます。効果的なマルチエージェント設計は、モジュール性、明確なタスク委譲、シームレスなデータ交換を要件としており、人間のチームの動態を反映した、スケーラブルで適応性の高いAIソリューションを実現します。
複数の専門化されたエージェントを活用することで、開発者は大規模で複雑な問題を、より小さく明確に定義されたサブタスクへと分割できます。ワークフローのあらゆる側面を単一の巨大なシステムで扱うのではなく、各コンポーネントやフェーズを、その責務に最適化されたエージェントに割り当てられます。たとえば、 テキストの要約、 コードスニペットの生成、 感情分析、または 出力の整形この分業化により、システムは理解しやすくなるだけでなく、保守性と堅牢性も向上します。各エージェントを個別に更新・置換・スケールでき、パイプライン全体を乱さずに改良できます。
また、モデルのコンテキスト制限を管理しやすくし、特定のタスクごとに別のモデルへ入れ替えたり、システム全体でプロンプトの使い方を微調整・制御したりできるため、各段階でのリソース使用と精度の最適化に役立ちます。
CrewAI プラットフォームの主な特長
- 自動化フレームワークCrewAI の中核には、エージェント・タスク・ツールを明確に分離する設計があります。エージェントは役割と目的を持つ自律的な実体を表し、タスクはそれらに割り当てられる個別の作業単位です。ツールは外部の API、検索エンジン、あるいはカスタム関数で、エージェントがタスクを実行・強化するために利用します。この「エージェント・タスク・ツール」という三位一体が、モジュール性と保守性に優れた AI ワークフローの基盤を成します。
- クルーとフローCrews とフロー:CrewAI は、複数のエージェントとそのタスクをオーケストレーションするために Crew を使用します。Crew はエージェント間の全体的な実行フローとデータのやり取りを制御します。プラットフォームは、Process クラスを通じて異なるワークフロー処理戦略をサポートします。
- 逐次タスクは逐次的に実行され、前のタスクの出力が後続のタスクに引き継がれます。
- 階層型タスクは入れ子構造や依存関係を持つように編成でき、エージェント間での複雑な調整や委譲を可能にします。
- 柔軟なデプロイメントCrewAI は、アジャイルな開発向けのインライン Python スクリプトと、より構造化・スケーラブルな YAML 設定ファイルの両方をサポートします。これにより、開発者は素早くプロトタイプを作成し、その後シームレスに拡張して、より複雑なマルチエージェントシステムに対応できます。
- 外部ツールとの統合CrewAI のエージェントは、さまざまなツールを接続することで拡張できます。これらのツールは、ウェブ検索 API、データベース、その他のサービスなど、外部のデータや機能へのインターフェースとして機能します。ツールを活用することで、エージェントは最新情報の取得、特化した計算の実行、サードパーティシステムとの連携が可能になり、自動化ワークフローの適用範囲を大幅に広げられます。
- 明示的なタスク割り当てCrewAI では、タスクを明示的に定義し、エージェントに割り当てる必要があります。自律的な自己監視や自動委譲に頼るのではなく、開発者が各タスクの責務と担当エージェントを指定します。こうした明示性により、透明性と予測可能性が高まり、複雑なマルチエージェントの相互作用をデバッグしやすくなります。
チュートリアル:CrewAI と Weave を用いた GitHub リポジトリ自動ドキュメント化のマルチエージェントシステム構築
このチュートリアルでは、CrewAI を用いて、GitHub リポジトリを自動的に探索・理解・ドキュメント化・可視化するマルチエージェント AI システムの構築方法を解説します。目的は、生のコードベースを包括的な使用ガイドとアーキテクチャ図に変換し、整った HTML ドキュメントとしてまとめる全自動パイプラインを作ることです。
AI エージェントを作成する前に、まず GitHub リポジトリとやり取りするために必要な機能を提供する、特化型のツール群を用意する必要があります。ツールは、エージェントがファイル検索、内容の読み取り、コードの要約といった特定の機能を実行するために呼び出せる、外部インターフェースまたはユーティリティとして機能します。
このチュートリアルでは、コアとなる3つのツールを実装します。
- リポジトリ探索ツールユーザーのクエリを受け取り、リポジトリ全体のファイル構造を検索し、クエリに関連するファイルパスを返して、エージェントが分析の焦点を特定できるようにします。
- ファイル閲覧ツール指定したファイルパスの内容を全て読み取り、そのまま返します。これにより、エージェントは生のソースコードやドキュメントにアクセスできます。
- ファイル要約ツール言語モデルを用いてファイル内容を要約し、簡潔なサマリーを生成します。これにより、エージェントはコードやドキュメントの全行を逐一読まずとも、複雑な内容を把握できます。
import osimport subprocessfrom typing import Typefrom pydantic import BaseModel, Fieldfrom crewai.tools import BaseToolfrom langchain_openai import ChatOpenAI# Clone the repo if not already clonedREPO_URL = "https://github.com/karpathy/nanogpt.git"REPO_DIR = "./nanogpt"if not os.path.exists(REPO_DIR):subprocess.run(["git", "clone", REPO_URL])# --- Define the Repo Explorer Tool ---class RepoQueryInput(BaseModel):query: str = Field(..., description="Describe what you are looking for in the codebase.")class RepoExplorerTool(BaseTool):name: str = "Repo Explorer"description: str = "Given a query, find relevant file paths from the nanogpt repo."args_schema: Type[BaseModel] = RepoQueryInputdef _run(self, query: str) -> str:file_list = []for root, _, files in os.walk(REPO_DIR):for file in files:full_path = os.path.join(root, file)file_list.append(full_path)llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)prompt = f"""You are a codebase expert. Here is a list of files:\n{file_list}\n\nBased on the user query "{query}", return ONLY the full file paths that are most relevant.Respond with one file path per line, no extra text."""response = llm.invoke(prompt)return response.content.strip()# --- Define the View File Content Tool ---class ViewFileInput(BaseModel):filepath: str = Field(..., description="Full path to the file you want to read.")class ViewFileTool(BaseTool):name: str = "View File Content"description: str = "Reads the full content of a given file path from the nanogpt repo."args_schema: Type[BaseModel] = ViewFileInputdef _run(self, filepath: str) -> str:filepath = filepath.strip() # <<< add thistry:with open(filepath, "r", encoding="utf-8") as f:content = f.read()return contentexcept Exception as e:return f"Error reading file: {str(e)}"# --- Instantiate the tools ---repo_explorer_tool = RepoExplorerTool()view_file_tool = ViewFileTool()# --- Example usage ---if __name__ == "__main__":# Step 1: Find files related to training loopquery = "Where is the training loop defined?"result_paths = repo_explorer_tool._run(query=query)print("Relevant Files:\n", result_paths)# Step 2: Read the first file foundfirst_file = result_paths.splitlines()[0]file_content = view_file_tool._run(filepath=first_file)print("\nContent of the first relevant file:\n")print(file_content[:3000]) # only print first 3000 chars to keep output readable
これで、構築したツールを活用して、AI エージェントとその実行タスクを定義する準備が整いました。
このシステムは、複数の専門エージェントが逐次的に協調し、最終的なドキュメント出力を生成します。
- デモ生成ツールリポジトリの初心者向けの入門ガイドを作成し、最小限のサンプルコマンドを含めます。
- フォローアップ担当分析者生成された使用ガイドをレビューし、抜け漏れを特定して確認のための質問を行い、改善に向けた具体的な提案を提示します。
- リポジトリ要約担当リポジトリ内の主要ファイルを走査して要約し、開発者の理解を助ける簡潔な説明を提供します。
- 図表生成担当:ファイル要約に基づいて、PlantUML や ASCII などのテキストベースのアーキテクチャ図を作成し、リポジトリの高レベルな構造を概観します。
- シェルスクリプト自動化担当:依存関係のインストール、環境構築、デモの実行を含むリポジトリのセットアップ手順をすべて自動化し、再実行しても安全な包括的な Bash スクリプトを生成します。開発者は単一のコマンドで開始できます。
- HTML コーダー改良済みの使用ガイド、アーキテクチャ図、生成されたセットアップスクリプトを統合し、読みやすいスタイル付きのクリーンなHTMLドキュメントページにまとめます。
コードはこちらです。
import osimport subprocessfrom typing import Type, Listfrom pydantic import BaseModel, Fieldfrom crewai import Agent, Task, Crew, Processfrom crewai.tools import BaseToolfrom langchain_openai import ChatOpenAIimport weave; weave.init("crewai_git_documenter")# --- Repo Setup ---REPO_URL = os.getenv('REPO_URL', 'https://github.com/LiveCodeBench/LiveCodeBench')REPO_NAME = REPO_URL.split("/")[-1].replace(".git", "")REPO_DIR = f"./{REPO_NAME}"if not os.path.exists(REPO_DIR):subprocess.run(["git", "clone", REPO_URL])# --- Tools ---class RepoQueryInput(BaseModel):query: str = Field(..., query="Describe what you are looking for in the codebase.")class RepoExplorerTool(BaseTool):name: str = "Repo Explorer"description: str = "Given a query, find relevant file paths from the repo."args_schema: Type[BaseModel] = RepoQueryInputdef _run(self, query: str) -> str:file_list = []for root, _, files in os.walk(REPO_DIR):for file in files:full_path = os.path.join(root, file)file_list.append(full_path)llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)prompt = f"""Here is a list of files:\n{file_list}\n\nUser query: "{query}"Return ONLY full file paths that match. One per line."""response = llm.invoke(prompt)return response.content.strip()class ViewFileInput(BaseModel):filepath: str = Field(..., description="Full path to the file you want to read.")class ViewFileTool(BaseTool):name: str = "View File Content"description: str = "Reads the full content of a given file path from the repo."args_schema: Type[BaseModel] = ViewFileInputdef _run(self, filepath: str) -> str:filepath = filepath.strip()try:with open(filepath, "r", encoding="utf-8") as f:return f.read()except Exception as e:return f"Error reading file: {str(e)}"class SummarizeFileTool(BaseTool):name: str = "Summarize File Content"description: str = "Summarizes a given file's content into a short description."args_schema: Type[BaseModel] = ViewFileInputdef _run(self, filepath: str) -> str:filepath = filepath.strip()try:with open(filepath, "r", encoding="utf-8") as f:content = f.read()llm = ChatOpenAI(model_name="gpt-4o-mini", temperature=0)prompt = f"Summarize the following code file in 5 sentences:\n\n{content}"response = llm.invoke(prompt)return response.content.strip()except Exception as e:return f"Error summarizing file: {str(e)}"# --- Instantiate tools ---repo_explorer_tool = RepoExplorerTool()view_file_tool = ViewFileTool()summarize_file_tool = SummarizeFileTool()# --- Agents ---demo_generator_agent = Agent(role="Demo Generator",goal="Write and expand a basic usage example for the repo.",backstory="Expert technical writer.",tools=[repo_explorer_tool, view_file_tool],allow_delegation=False,verbose=True,llm=ChatOpenAI(model_name="gpt-4o-mini", temperature=0.5))followup_analyst_agent = Agent(role="Follow-Up Analyst",goal="Analyze the usage guide, find missing info, suggest improvements.",backstory="Developer experience expert.",allow_delegation=False,verbose=True,llm=ChatOpenAI(model_name="gpt-4o-mini", temperature=0.3))html_coder_agent = Agent(role="HTML Coder",goal="Turn the improved usage guide into a clean HTML page.",backstory="Frontend dev specializing in docs websites. DO NOT GENERATE IMAGES MAN eg dont do src=data:image/png etc etc",allow_delegation=False,verbose=True,llm=ChatOpenAI(model_name="gpt-4o-2024-08-06", temperature=0.4))repo_summarizer_agent = Agent(role="Repo Summarizer",goal="Summarize all important files in the repo for easier understanding.",backstory="Documentation architect.",tools=[repo_explorer_tool, view_file_tool, summarize_file_tool],allow_delegation=False,verbose=True,llm=ChatOpenAI(model_name="gpt-4o-mini", temperature=0.4))diagram_generator_agent = Agent(role="Diagram Generator",goal="Using file summaries, generate a full architecture diagram of the repo.",backstory="System architect skilled in explaining large codebases.",allow_delegation=False,verbose=True,llm=ChatOpenAI(model_name="gpt-4o-mini", temperature=0.4))shell_script_agent = Agent(role="Shell Script Automation Engineer",goal="Create a working shell script that sets up all requirements and runs the repo's demo or basic usage.",backstory="Expert in bash scripting, devops, and repo onboarding automations.",tools=[repo_explorer_tool, view_file_tool, summarize_file_tool], # Optional, useful for reading filesallow_delegation=False,verbose=True,llm=ChatOpenAI(model_name="gpt-4o-mini", temperature=0.3))# --- Tasks ---demo_generation_task = Task(description=f"Write a beginner-friendly usage guide explaining how to use {REPO_NAME}. Include a minimal example command.",expected_output="Markdown snippet with instructions.",agent=demo_generator_agent,output_file="basic_usage.md")followup_task = Task(description="Read 'basic_usage.md', find confusing parts, generate 5+ questions and improvements.",expected_output="List of questions + feedback report.",agent=followup_analyst_agent,context=[demo_generation_task],output_file="feedback_report.md")improvement_task = Task(description="Use 'feedback_report.md' to expand and improve the usage guide.",expected_output="New improved guide.",agent=demo_generator_agent,context=[followup_task],output_file="improved_usage.md")repo_summarization_task = Task(description="Scan the repo, summarize the major files (training, models, data utils, etc.).",expected_output="List of file summaries.",agent=repo_summarizer_agent,output_file="repo_summary.md")diagram_generation_task = Task(description="Using 'repo_summary.md', create an overall architecture diagram of the repo in text/plantuml format.",expected_output="Architecture diagram text.",agent=diagram_generator_agent,context=[repo_summarization_task],tools=[repo_explorer_tool, view_file_tool, summarize_file_tool],output_file="architecture_diagram.md")shell_script_task = Task(description=("Read the improved usage guide and repo summary. Write a BASH shell script that fully sets up the repo from scratch, ""including dependency installation, environment setup, any required downloads, and running the minimal example demo. ""The script should be idempotent (safe to rerun), and **explain each step with comments**. Output the script in a codeblock."),expected_output="A complete shell script (setup_and_run_demo.sh) with comments.",agent=shell_script_agent,context=[improvement_task, repo_summarization_task], # Uses improved usage and file summariesoutput_file="setup_and_run_demo.sh")html_generation_task = Task(description="Combine 'improved_usage.md', and 'architecture_diagram.md' into a final HTML file. Make sure to append the full setup_and_run_demo.sh script at the end",expected_output="Final styled HTML guide. Follow styling similar to Wandb's website styling",agent=html_coder_agent,context=[improvement_task, diagram_generation_task, shell_script_task],output_file="final_guide.html")# --- Run Crew ---crew = Crew(agents=[demo_generator_agent,followup_analyst_agent,repo_summarizer_agent,diagram_generator_agent,html_coder_agent,shell_script_agent, # <-- Add here],tasks=[demo_generation_task,followup_task,improvement_task,repo_summarization_task,diagram_generation_task,shell_script_task, # <-- Add here, before html_generation_taskhtml_generation_task,],process=Process.sequential,verbose=True)if __name__ == "__main__":result = crew.kickoff()print("\n\nFinal HTML Guide and Repo Diagram Created:\n")print(result)
このコードは、CrewAI と Weave を用いて GitHub リポジトリのドキュメント化を自動化するマルチエージェントシステムを構築します。まずリポジトリをクローンし、エージェントがファイル検索、内容の読み取り、要約生成を行える一連のツールを初期化します。各エージェントには明確な役割があり、使用ガイドの作成、レビューと改良、ソースファイルの要約、セットアップ用シェルスクリプトの作成、アーキテクチャ図の生成、そしてすべてを HTML ページにまとめる作業を担当します。
これらのタスクは厳密な順序で実行されます。初期のエージェントが生成した成果物(使用ガイドやリポジトリ要約など)は、後続エージェントへのコンテキストとして受け渡されます。システムはすべてをログに記録します。 LLM インタラクション 可観測性のための Weave の活用実行すると、洗練された使用ガイド、リポジトリ構造のビジュアル概要、実行可能なセットアップスクリプトを含む完全なHTMLドキュメントが、ソースコードから自動生成されます。
CrewAI の Agent、Task、Crew クラスを用いてワークフロー全体をオーケストレーションします。各エージェントには専門のタスクを割り当て、すべてのタスクは逐次的に実行されます。これにより、ある段階の出力が次の段階の入力となり、情報が段階的に積み上がっていきます。具体的には、最初の使用ガイドやファイル要約から始まり、図の生成やシェルスクリプト作成を経て、最終的にはすべての成果物を統合した包括的な HTML ドキュメントページに到達します。
スクリプトを実行すると、次の名前の新しいファイルが作成されます。 final_guide.htmlには、リポジトリの使い方ガイドが含まれています。見た目の参考として、いくつかスクリーンショットを紹介します。


LLM の可観測性とデバッグを強化するための Weave の統合
このマルチエージェントシステムを効率的に監視・デバッグするために、冒頭で Weave を次のように初期化して統合します。 import weave; weave.init("crewai_git_documenter"). このセットアップにより、各エージェントが OpenAI のモデルへ行うすべての呼び出しを取得し、プロンプト、レスポンス、関連するコンテキストを一元的に記録します。
〜により Weave の可視化ダッシュボード、開発者は各エージェントの LLM 呼び出しごとの詳細なリクエスト/レスポンスの流れを精査し、エージェントが取得・分析・生成する情報のフローをトレースして、ボトルネックや想定外の出力、チェーン内のエラーを素早く特定できます。また、実際の使用データに基づいてプロンプト指示やパラメータをチューニングできます。以下は Weave のスクリーンショットで、エージェントが LLM に行ったすべての呼び出しをどのように簡単に可視化できるかを示しています。

このようなエージェント間のやり取りを粒度高く可視化できることは、複数のモデルが専門知識を持ち寄る私たちのようなマルチエージェント型ワークフローにおいて特に有用です。ローカルファイルに散在するログをかき集める代わりに、Weave はパイプライン全体の履歴をウェブ上で検索可能な形で提供し、より効果的な反復開発と保守を可能にします。
専門特化したエージェントに役割を分担し、Weave で各ステップを追跡することで、CrewAI を基盤としたこのマルチエージェントシステムは、スケーラブルで保守しやすく、かつ透明性の高い自動ソフトウェアドキュメント化の手法を提供します。
まとめ
マルチエージェントシステムは、AI エージェントが協調して複雑なタスクに取り組めるようにすることで、自動化を大きく前進させています。CrewAI はこの用途に特化しており、開発者が明確な役割を持つエージェントを定義し、ツールやタスクに接続できます。コードと設定の両方によるワークフローに対応し、オーケストレーションが明快なため、デバッグやスケーリングが容易です。さらに Weave と組み合わせれば、すべてのモデル呼び出しが追跡・可視化され、エージェントがどのように考え、行動し、協働しているかを開発者が俯瞰できます。
GitHub のドキュメント生成システムでは、各エージェントが固有の役割を担当します。たとえば、コードの要約、ダイアグラムの生成、使用ガイドの執筆、セットアップスクリプトの作成などです。システムは逐次的に実行され、各ステップの結果が次のステップに受け渡されます。Weave を統合することで、開発者はプロンプトとレスポンスの対応関係を監視し、ロジックをトレースし、エラーを修正し、出力品質を改善できます。自動化は CrewAI が担い、内部の見える化は Weave が提供し、両者を組み合わせることで、保守しやすく透明性の高いマルチエージェントシステムを実現します。
Add a comment
Iterate on AI agents and models faster. Try Weights & Biases today.