LlamaIndex は、データに接続された LLM を使用してナレッジ エージェントを構築するためのフレームワークです。この例では、リサーチ エージェントのマルチエージェント ワークフローを構築する方法を示します。LlamaIndex では、
Workflows はエージェント システムとマルチエージェント システムの構成要素です。
Gemini API キーが必要です。キーがない場合は、Google AI Studio で取得できます。まず、必要な LlamaIndex ライブラリをすべてインストールします。LlamaIndex は、内部で google-genai パッケージを使用します。
pip install llama-index llama-index-utils-workflow llama-index-llms-google-genai llama-index-tools-google
LlamaIndex で Gemini を設定する
LlamaIndex エージェントのエンジンは、推論とテキスト処理を処理する LLM です。この例では Gemini 3 Flash を使用します。API キーを環境変数として設定してください。
import os
from llama_index.llms.google_genai import GoogleGenAI
# Set your API key in the environment elsewhere, or with os.environ['GEMINI_API_KEY'] = '...'
assert 'GEMINI_API_KEY' in os.environ
llm = GoogleGenAI(model="gemini-3-flash-preview")
ビルドツール
エージェントはツールを使用して、ウェブの検索や情報の保存など、外部とやり取りします。LlamaIndex のツール
は、通常の Python 関数にすることも、既存の ToolSpecs からインポートすることもできます。Gemini には、Google 検索を使用するための組み込みツールが用意されています。ここでは、そのツールを使用します。
from google.genai import types
google_search_tool = types.Tool(
google_search=types.GoogleSearch()
)
llm_with_search = GoogleGenAI(
model="gemini-3-flash-preview",
generation_config=types.GenerateContentConfig(tools=[google_search_tool])
)
検索が必要なクエリを使用して、LLM インスタンスをテストします。このガイドでは、実行中のイベント ループ(python -m asyncio や Google Colab など)を前提としています。
response = await llm_with_search.acomplete("What's the weather like today in Biarritz?")
print(response)
Research Agent は、ツールとして Python 関数を使用します。このタスクを実行するシステムを構築する方法はたくさんあります。この例では、次のものを使用します。
search_webは、Gemini と Google 検索を使用して、指定されたトピックに関する情報をウェブで検索します。record_notesは、ウェブで見つかった調査結果を状態に保存し、他のツールで使用できるようにします。write_reportは、ResearchAgentが見つけた情報を使用してレポートを書き込みます。review_reportはレポートを確認し、フィードバックを提供します。
Context クラスはエージェント/ツール間で状態を渡し、各エージェントはシステムの現在の状態にアクセスできます。
from llama_index.core.workflow import Context
async def search_web(ctx: Context, query: str) -> str:
"""Useful for searching the web about a specific query or topic"""
response = await llm_with_search.acomplete(f"""Please research given this query or topic,
and return the result\n<query_or_topic>{query}</query_or_topic>""")
return response
async def record_notes(ctx: Context, notes: str, notes_title: str) -> str:
"""Useful for recording notes on a given topic."""
current_state = await ctx.store.get("state")
if "research_notes" not in current_state:
current_state["research_notes"] = {}
current_state["research_notes"][notes_title] = notes
await ctx.store.set("state", current_state)
return "Notes recorded."
async def write_report(ctx: Context, report_content: str) -> str:
"""Useful for writing a report on a given topic."""
current_state = await ctx.store.get("state")
current_state["report_content"] = report_content
await ctx.store.set("state", current_state)
return "Report written."
async def review_report(ctx: Context, review: str) -> str:
"""Useful for reviewing a report and providing feedback."""
current_state = await ctx.store.get("state")
current_state["review"] = review
await ctx.store.set("state", current_state)
return "Report reviewed."
マルチエージェント アシスタントを構築する
マルチエージェント システムを構築するには、エージェントとそのインタラクションを定義します。システムには 3 つのエージェントがあります。
ResearchAgentは、指定されたトピックに関する情報をウェブで検索します。WriteAgentは、ResearchAgentによって検出された情報を使用してレポートを書き込みます。ReviewAgentがレポートを確認し、フィードバックを提供します。
この例では、AgentWorkflow クラスを使用して、これらのエージェントを順番に実行するマルチエージェント システムを作成します。各エージェントは、何をすべきかを指示し、他のエージェントとの連携方法を提案する system_prompt を受け取ります。
必要に応じて、can_handoff_to を使用して、マルチエージェント システムが通信できる他のエージェントを指定できます(指定しない場合、システムは独自に判断しようとします)。
from llama_index.core.agent.workflow import (
AgentInput,
AgentOutput,
ToolCall,
ToolCallResult,
AgentStream,
)
from llama_index.core.agent.workflow import FunctionAgent, ReActAgent
research_agent = FunctionAgent(
name="ResearchAgent",
description="Useful for searching the web for information on a given topic and recording notes on the topic.",
system_prompt=(
"You are the ResearchAgent that can search the web for information on a given topic and record notes on the topic. "
"Once notes are recorded and you are satisfied, you should hand off control to the WriteAgent to write a report on the topic."
),
llm=llm,
tools=[search_web, record_notes],
can_handoff_to=["WriteAgent"],
)
write_agent = FunctionAgent(
name="WriteAgent",
description="Useful for writing a report on a given topic.",
system_prompt=(
"You are the WriteAgent that can write a report on a given topic. "
"Your report should be in a markdown format. The content should be grounded in the research notes. "
"Once the report is written, you should get feedback at least once from the ReviewAgent."
),
llm=llm,
tools=[write_report],
can_handoff_to=["ReviewAgent", "ResearchAgent"],
)
review_agent = FunctionAgent(
name="ReviewAgent",
description="Useful for reviewing a report and providing feedback.",
system_prompt=(
"You are the ReviewAgent that can review a report and provide feedback. "
"Your feedback should either approve the current report or request changes for the WriteAgent to implement."
),
llm=llm,
tools=[review_report],
can_handoff_to=["ResearchAgent","WriteAgent"],
)
エージェントが定義されたので、AgentWorkflow を作成して実行できます。
from llama_index.core.agent.workflow import AgentWorkflow
agent_workflow = AgentWorkflow(
agents=[research_agent, write_agent, review_agent],
root_agent=research_agent.name,
initial_state={
"research_notes": {},
"report_content": "Not written yet.",
"review": "Review required.",
},
)
ワークフローの実行中に、イベント、ツール呼び出し、更新をコンソールにストリーミングできます。
from llama_index.core.agent.workflow import (
AgentInput,
AgentOutput,
ToolCall,
ToolCallResult,
AgentStream,
)
research_topic = """Write me a report on the history of the web.
Briefly describe the history of the world wide web, including
the development of the internet and the development of the web,
including 21st century developments"""
handler = agent_workflow.run(
user_msg=research_topic
)
current_agent = None
current_tool_calls = ""
async for event in handler.stream_events():
if (
hasattr(event, "current_agent_name")
and event.current_agent_name != current_agent
):
current_agent = event.current_agent_name
print(f"\n{'='*50}")
print(f"🤖 Agent: {current_agent}")
print(f"{'='*50}\n")
elif isinstance(event, AgentOutput):
if event.response.content:
print("📤 Output:", event.response.content)
if event.tool_calls:
print(
"🛠️ Planning to use tools:",
[call.tool_name for call in event.tool_calls],
)
elif isinstance(event, ToolCallResult):
print(f"🔧 Tool Result ({event.tool_name}):")
print(f" Arguments: {event.tool_kwargs}")
print(f" Output: {event.tool_output}")
elif isinstance(event, ToolCall):
print(f"🔨 Calling Tool: {event.tool_name}")
print(f" With arguments: {event.tool_kwargs}")
ワークフローが完了すると、レポートの最終出力と、レビュー エージェントからの最終レビュー状態を出力できます。
state = await handler.ctx.store.get("state")
print("Report Content:\n", state["report_content"])
print("\n------------\nFinal Review:\n", state["review"])
カスタム ワークフローでさらに活用する
AgentWorkflow は、マルチエージェント システムを始めるのに最適な方法です。ただし、より詳細な制御が必要な場合はどうすればよいでしょうか。ワークフローはゼロから構築できます。独自のワークフローを構築する理由を以下に示します。
- プロセスをより細かく制御: エージェントがたどる正確なパスを決定できます。これには、ループの作成、特定の時点での意思決定、さまざまなタスクでのエージェントの並行処理などが含まれます。
- 複雑なデータを使用する: プレーン テキストにとどまらず、カスタム ワークフローを使用すると、入力と出力に JSON オブジェクトやカスタム クラスなどの構造化データをより多く使用できます。
- さまざまなメディアを操作する: テキストだけでなく、画像、音声、動画も理解して処理できるエージェントを構築します。
- よりスマートな計画: エージェントが作業を開始する前に、詳細な計画を最初に作成するワークフローを設計できます。これは、複数のステップを必要とする複雑なタスクに役立ちます。
- 自己修正を有効にする: 独自の作業をレビューできるエージェントを作成します。出力が十分でない場合、エージェントは結果が完璧になるまで改善のループを繰り返します。
LlamaIndex Workflows の詳細については、LlamaIndex Workflows のドキュメントをご覧ください。