はじめに
最近、いろんなエージェント系のフレームワークが登場していますが、その中でも「StrandsAgents」という名前を見かけるようになり、気になって触ってみることにしました。
StrandsAgentsはかなりシンプルな構成でエージェントを定義できる軽量フレームワークです。
この記事では、StrandsAgentsを使い始めるための基本的な環境構築から、モデルの呼び出し方、ツール(外部関数)の組み込み方までを一通り紹介していきます。
「なんか最近エージェントって流行ってるけど、結局どう始めたらいいの?」という方に向けて、なるべく丁寧にまとめていくつもりです。
StrandsAgentsとは
StrandsAgentsは、AWSのオープンソース部門が発表した、モデル駆動型(model‑driven)アプローチをとるAIエージェント向けのSDKです。
「Strands」というのは、DNAの螺旋構造のことを指しているようで、モデルとツールをがっちゃんこして、より使いやすくしてくれるフレームワークなんですね〜
環境構築手順
今回はVS Codeで実行していきます。記事作成時、私はMacで実行していますが、Windowsでも概ね同様の手順で実施できるはずです。
デスクトップに「Strands」フォルダを作成し、その中で作業しています。
まずは、uvをインストールし、仮想環境を作ってしまいます。
brew install uv
uv venv
次に仮想環境を有効化し、strandsのあれこれをインポートします。
source .venv/bin/activate
uv pip install strands-agents strands-agents-tools strands-agents-builder
最後に、実行するファイルを作成します。
StrandsAgentは環境構築こそ必要ですが、最小コード自体はたったのこれだけで実行できてしまいます。
from strands import Agent
agent = Agent()
response = agent("Japan AWS Jr.Championsについて教えて")
ここまでで準備は完了です。試しに早速実行してみましょう!
また、StrandsAgentはClaude 4 Sonnetがデフォルトで呼び出される仕組みになっています。
以下のコマンドをターミナルに打ち込んで実行結果を確認してみて下さい。
uv run strands_1.py
好きなモデルを呼び出してみる
StrandsはさまざまなLLMモデルを呼べることも特徴の一つです。
今回は試しにAmazon Novaを使ってみたいと思います。
from strands import Agent
from strands.models import BedrockModel
bedrock_model = BedrockModel(
model_id="us.amazon.nova-premier-v1:0",
temperature=0.3,
top_p=0.8,
)
agent = Agent(model=bedrock_model)
response = agent("Amazon Bedrockについて教えて")
以下のコマンドで実行してみて下さい!
uv run strands_2.py
他のモデルでも試したい、という方は、下記のモデル一覧を参考に色々いじってみて下さい。
また、Amazon Novaをはじめとするクロスリージョン推論対応モデルを使用する場合、モデルIDのみ指定してもエラーになってしまうかと思います。
その場合推論プロファイルという指定された型で記述しないといけないようです。
ツールを持たせてみる
StrandsAgentは、「tool」でデコレートしてあげると、AIがこれは使っていいツールだ!って勝手に判断して使えるようになります。
今回は、
- 天気を教えてくれるツール(ダミーで晴れしか返さない)
- Web検索ツール
を実装してみたいと思います。
天気予報ツール
from dotenv import load_dotenv
from strands import Agent, tool
load_dotenv()
# ダミーで晴れを必ず返す
@tool
def weather():
""" Get weather """
return "sunny"
# エージェントを作成
agent = Agent(
model="us.anthropic.claude-3-7-sonnet-20250219-v1:0",
tools=[weather]
)
# エージェントを呼び出し
agent("今日の天気は?")
以下のコマンドで実行してみて下さい!
uv run strands_3.py
Web検索ツール
まず、下記のコマンドでWeb検索のツール、今回はダックダックGOをインポートします!
uv pip install ddgs
コードは下記の通りです!
最新ニュースを調べて要約してきてくれます!
# Import Agent and tools
import logging
from ddgs import DDGS
from ddgs.exceptions import DDGSException, RatelimitException
from strands import Agent, tool
# Configure logging
logging.getLogger("strands").setLevel(logging.INFO)
# Define a websearch tool
@tool
def websearch(keywords: str, region: str = "jp-ja", max_results: int | None = None) -> str:
"""DuckDuckGoを用いて日本語のWebニュースを検索します。 """
try:
results = DDGS().text(keywords, region=region, max_results=max_results)
return results if results else "結果が見つかりませんでした。"
except RatelimitException:
return "レート制限に達しました。しばらく待ってから再試行してください。"
except DDGSException as d:
return f"DuckDuckGo検索でエラーが発生しました: {d}"
except Exception as e:
return f"不明なエラーが発生しました: {e}"
recipe_agent = Agent(
system_prompt=(
"あなたは親切なニュースアシスタントです。"
"ユーザーが関心を示した話題について、最新のニュース記事を検索し、簡潔に要約してください。"
"必要に応じてwebsearchツールを使用し、記事のタイトルとURLをまとめてください。"
"返答は必ず日本語で行ってください。"
),
tools=[websearch],
)
response = recipe_agent("最近のAIに関する重要なニュースを教えてください")
print(f"メトリクス : {response.metrics}")
下記コマンドで実行してみてください!
uv run strands_4.py
MCPサーバーと繋げる
StrandsAgentは、今話題のMCPとの連携もお手のものです。
今回はAWSドキュメントについて解説してくれるドキュメントMCPサーバーを使用してみます。
from mcp import stdio_client, StdioServerParameters
from strands import Agent
from strands.tools.mcp import MCPClient
mcp = MCPClient(lambda: stdio_client(
StdioServerParameters(
command="uvx",
args=["awslabs.aws-documentation-mcp-server@latest"]
)
))
with mcp:
tools = mcp.list_tools_sync()
agent = Agent(tools=tools)
agent("Amazon Bedrock AgentCoreについて教えて下さい")
下記コマンドで実行してみてください!
uv run strands_5.py
マルチエージェントにしてみる
StrandsAgentsでは、1つのエージェントにツールを持たせて使うだけでなく、複数のエージェントを連携させる「マルチエージェント構成」もサポートされています。
ここでは、いわゆる「役割の異なる複数のエージェントが協力して1つのタスクを進める」ような構成を、実際に動かしてみた例を紹介します。
Swarmツール
Strandsには、複数エージェントを一気に呼び出すための便利なツールとして Swarm という仕組みが用意されています。
これは「複数のエージェントに同じ問いを投げて、それぞれの視点から答えてもらう」ような場面でとても便利です。
以下のようにエージェントをまとめて定義して、一気に呼び出すことができます。
実行中、「〇〇エージェントに処理を引き継ぎました」と確認できますが、それはAIが勝手に判断していい感じに処理する人を決めてくれているんですね。
from strands import Agent
from strands_tools import swarm
from strands.multiagent import Swarm
# エージェントの初期化
agent = Agent(model="us.anthropic.claude-3-7-sonnet-20250219-v1:0", tools=[swarm])
# 自然言語による呼び出し
result = str(agent(
"生成AIベースのエージェントに関する現在の市場動向を、4体のエージェント群で分析してください。"
))
print(result)
# 専門分野の異なるエージェントを作成
research_agent = Agent(system_prompt=("""あなたは情報収集と分析を専門とするリサーチエージェントです。
あなたの役割は、スワーム内で事実に基づいた情報と調査結果を提供することです。
正確なデータを提供し、問題の主要な側面を特定することに集中してください。
他のエージェントからの情報を受け取った際には、それがあなたの調査と一致しているかを評価してください。
"""),
name="research_agent", model="us.anthropic.claude-3-7-sonnet-20250219-v1:0")
creative_agent = Agent(system_prompt=("""あなたは革新的な解決策を生み出すことを専門とするクリエイティブエージェントです。
あなたの役割は、スワーム内で独自の視点から創造的なアプローチを提案することです。
他のエージェントの情報を活用しつつ、あなた自身の創造力を加えてください。
他のエージェントが考えつかないような新しいアプローチに焦点を当ててください。
"""),
name="creative_agent", model="us.anthropic.claude-3-7-sonnet-20250219-v1:0")
critical_agent = Agent(system_prompt=("""あなたは提案されたアイデアを分析し、欠点を見つけ出すことを専門とするクリティカルエージェントです。
あなたの役割は、他のエージェントによって提案された解決策を評価し、潜在的な問題点を指摘することです。
提案された解決策を注意深く検討し、弱点や見落としを見つけ、改善点を提案してください。
批判的でありながら建設的に貢献し、最終的な解決策がより堅牢になるようにしてください。
"""),
name="critical_agent", model="us.anthropic.claude-3-7-sonnet-20250219-v1:0")
summarizer_agent = Agent(system_prompt=("""あなたは情報の統合を専門とするサマライザーエージェントです。
あなたの役割は、すべてのエージェントからの洞察を統合し、最終的な包括的な解決策を作成することです。
最も優れたアイデアを組み合わせ、批判に対応したうえで、元の質問に的確に答える明確で実行可能な要約を作成してください。
"""),
name="summarizer_agent", model="us.anthropic.claude-3-7-sonnet-20250219-v1:0")
# 上記のエージェントをまとめてスワームを作成
swarm = Swarm(
[research_agent, creative_agent, critical_agent, summarizer_agent],
max_handoffs=20,
max_iterations=20,
execution_timeout=900.0, # 最大実行時間:15分
node_timeout=300.0, # 各エージェントの実行時間:5分
repetitive_handoff_detection_window=8, # 直近8回のハンドオフで3体以上の異なるエージェントが含まれている必要あり
repetitive_handoff_min_unique_agents=3
)
# タスクをスワームに実行させる
result = swarm("Agentic AIについてブログ記事を作成し、その要約をSNS用に出力してください。")
# 最終結果にアクセス
print(f"ステータス: {result.status}")
# どのエージェントが関与したか確認
for node in result.node_history:
print(f"エージェント: {node.node_id}")
# 特定のノードの結果を取得
research_result = result.results["research_agent"].result
print(f"リサーチ結果: {research_result}")
# 実行時のパフォーマンス情報を取得
print(f"総イテレーション数: {result.execution_count}")
print(f"実行時間: {result.execution_time}ms")
print(f"トークン使用量: {result.accumulated_usage}")
下記コマンドで実行してみてください!
uv run strands_6.py
最後に
いかがでしたか?
私自身、少し乗り遅れた感がありましたが学んでみるととっても面白かったです。
こんな簡単にAIエージェントが開発できるようになるとは...
StrandsAgentは今回書ききれていないところもあるので今後試していこうと思います。
この記事がこれからStrandsAgentやってみようかな..という方の手助けになれば幸いです。