はじめに
こんにちは、野村総合研究所の早川です。
2025年5月、AWSがAIエージェントSDK「Strands Agents」をオープンソースで公開しました。「数行でエージェントを動かせる」を設計思想の中心に置いたこのフレームワークは、最小構成からマルチエージェントまでをカバーするSKDです。Amazon Bedrock AgentCoreなどAWSサービスとの統合を前提に設計されている点も特徴です。
本記事では、Strands Agentsを実際に動かしながら、基本的な使い方からマルチエージェント設計まで順に解説します。
Strands Agentsとは
Strands Agentsは、AWS が OSS として公開しているAIエージェントSDKです。
MicrosoftではSemantic Kernel、GoogleではAgent Development Kit(ADK)というOSSエージェントSDKがあります。それぞれのプラットフォームとの親和性を重視した設計になっている点は共通しており、Strands AgentsはAmazon Bedrockとの統合を前提に設計されている点が特徴です。
エージェントを構成する要素は「Model」「Tools」「Prompt」の3つがあります。
Model は、ユーザーの指示を解釈してどのツールを使うか・何を返すかを判断するLLMです。デフォルトはAmazon BedrockのClaude Sonnet 4で、BedrockModel を渡すことで任意のモデルに切り替えられます。
Tools は、エージェントが外部と実際にやり取りするための関数群です。ビルトインツールをそのまま渡すか、@tool デコレータで自作の関数をツール化できます。どのツールをいつ呼ぶかはモデルが自律的に判断します。ビルトインツールは計算機、ファイル操作、HTTPリクエスト、コード実行、MCP連携など40種類以上が同梱されています。
Prompt は、system_prompt 引数でエージェントの役割や制約を定義する文字列です。指定しない場合はデフォルトの汎用プロンプトが使われます。マルチエージェント構成では、各エージェントに異なる system_prompt を与えることで役割を分担させます。
対応モデルはAmazon BedrockのClaude・Nova・Titanをはじめ、OpenAI、ローカルで動くOllamaなど様々なモデルに対応しています。対応しているモデルの一覧は公式ドキュメントを参照してください。
最小構成で動かす
エージェントの起動はAgent() を引数なしで呼び出すだけで動きます。2026年6月現在、デフォルトのモデルはAmazon BedrockのClaude Sonnet 4です。Bedrockを使うためには、事前にAWSの認証情報を設定し、Amazon Bedrockコンソールからモデルアクセスを有効化しておく必要があります。
from strands import Agent
agent = Agent()
print(agent("Amazon Bedrockでサポートされているモデルを3つ挙げてください"))
実行すると、エージェントはBedrockを呼び出し、日本語で回答を返します。ツールを何も渡していないため、この状態ではLLMとの対話のみが行われます。
モデルを変更する
デフォルト以外のモデルを使いたい場合は、BedrockModel を model 引数に渡します。
from strands import Agent
from strands.models import BedrockModel
model = BedrockModel(model_id="global.anthropic.claude-sonnet-4-6")
agent = Agent(model=model)
print(agent("Amazon S3の用途を教えてください"))
model_id には推論プロファイルIDを指定します。global. プレフィックスを付けるとリージョンに関わらず使えるグローバルプロファイルになります。us.・eu.・ap. のリージョンプレフィックスを使うことも可能です。Bedrock以外のプロバイダーを使う場合は AnthropicModel(Anthropic API直接)や LiteLLMModel(OpenAI・Ollamaなど)に差し替えるだけで動きます。
ツールを追加する
エージェントに道具を持たせることで、LLMが持つ知識の範囲を超えた処理ができるようになります。
ビルトインツールを使う
strands-agents-tools パッケージが提供する組み込みツール 1 は、そのまま tools 引数に渡せます。代表的なツールを挙げます。
| ツール名 | できること |
|---|---|
calculator |
数式の計算 |
python_repl |
Pythonコードの実行 |
shell |
シェルコマンドの実行 |
http_request |
HTTPリクエストの送信 |
file_read / file_write
|
ファイルの読み書き |
use_aws |
AWS APIの呼び出し(boto3ラッパー) |
image_reader |
画像の内容を解析 |
current_time |
現在日時の取得 |
mem0_memory |
会話をまたいだメモリの管理 |
shell や python_repl、file_write はローカル環境に影響を与えるため、実行時に確認が求められます。
from strands import Agent
from strands_tools import calculator, http_request
agent = Agent(tools=[calculator, http_request])
print(agent("3の17乗はいくつですか?"))
上の例では calculator ツールが自律的に選ばれ、計算結果が返されます。複数のツールを渡した場合も、どれをいつ使うかはエージェントが判断します。
カスタムツールを定義する
既存のPython関数をエージェントのツールに変えたいときは @tool デコレータを使います。関数の直下に書く """〜""" 形式の説明文(docstring)と型ヒントが、LLMへのツール説明として自動的に変換されます。
from strands import Agent, tool
import boto3
@tool
def get_ec2_count(region: str) -> int:
"""指定リージョンで稼働中のEC2インスタンス数を返す"""
ec2 = boto3.client("ec2", region_name=region)
response = ec2.describe_instances(
Filters=[{"Name": "instance-state-name", "Values": ["running"]}]
)
return sum(len(r["Instances"]) for r in response["Reservations"])
agent = Agent(tools=[get_ec2_count])
print(agent("東京リージョンで動いているEC2の台数を教えて"))
実行すると、エージェントは「東京リージョン」という表現から region="ap-northeast-1" を解釈し、get_ec2_count を呼び出します。既存のAWS操作コードをほぼそのまま転用できます。
コード例の """指定リージョンで稼働中のEC2インスタンス数を返す""" がdocstringです。docstringはPythonの慣習で、関数の直下に """〜""" で書く説明文のことです。Strands Agentsでは、このdocstringと引数の型ヒント(region: str)をLLMに渡すツール仕様の生成に使います。LLMはdocstringを読んでツールの目的を判断するため、「何をするツールか」が伝わる説明を書くことがツール選択の精度に直結します。
マルチエージェント設計
単一のエージェントで対応しきれないタスクは、複数のエージェントを組み合わせて解決します。Strands AgentsはGraph、Swarm、Workflowの3つのパターンを公式サポートしています。
パターンの選び方
マルチエージェントの設計は「フローが固定的か」と「エージェント間のデータをどう受け渡すか」で整理できます。
Graphはノード間のデータの流れをグラフとして定義します。次のステップが現在のステップの結果によって決定される場合に適しています。ただし、エージェントが返したテキストの中身を読んで「この内容なら次へ、そうでなければ別のノードへ」という判断はできないため、そのような分岐が必要な場合はWorkflowを使います。
Swarm は、問題をそれぞれ異なる専門的な視点で解決するサブタスクに分解できる場合に適しています。カスタマーサポートを例にとると、受付エージェントが対応し、請求の話なら請求エージェントへ、技術的な問題なら技術エージェントへとハンドオフします。どのエージェントに渡るかは入力内容によって変わるため、事前にルートをすべてコードに書けるならGraphかWorkflowを選んだほうが動作が安定します。
Workflowは複雑だが明確に定義可能なワークフローが必要な場合に適しています。「承認エージェントが"却下"を返したら修正エージェントを呼んで再度承認に回す、3回却下されたら人間にエスカレーションする」のような、返答の内容を読んで次を決める処理はWorkflowで書きます。
3パターンの使い分け
| Graph | Swarm | Workflow | |
|---|---|---|---|
| 構造 | プログラマーが遷移フローを定義する | LLMが判断する | プログラマーがタスクと依存関係をコードで定義する |
| 実行フロー | 制御されているが動的 | 逐次的かつ自律的 | 決定論的かつ並列処理 |
| 向いているケース | インタラクティブな顧客サポート | 複数分野にわたるインシデント対応 | 標準的な業務プロセス |
Graphパターンの例を示します。
from strands import Agent
from strands.multiagent import GraphBuilder
researcher = Agent(system_prompt="あなたはAWSサービスを調査する専門家です。")
summarizer = Agent(system_prompt="あなたは技術文書を日本語で要約する専門家です。")
builder = GraphBuilder()
builder.add_node(researcher, "research")
builder.add_node(summarizer, "summarize")
builder.add_edge("research", "summarize")
graph = builder.build()
result = graph("Amazon S3 Vectorsの概要を調査して要約してください")
print(result.results["summarize"].result.message["content"][0]["text"])
add_edge("research", "summarize") で実行順を定義します。実行結果は GraphResult オブジェクトとして返るため、特定ノードの出力を取り出すには result.results["ノード名"] でアクセスします。
制約と注意点
ツールのdocstringが精度を左右する点は特に意識が必要です。LLMはdocstringだけを頼りにツールを選ぶため、「何をするツールか」が曖昧な説明だと意図しないツールが呼ばれることがあります。英語・日本語どちらでも動きますが、具体的な動詞と名詞で書くことが大切です。
Swarmのルーティングはsystem_promptの精度に依存します。 各エージェントの役割が曖昧なsystem_promptだと、タスクが意図しないエージェントに渡ることがあります。「〇〇に関する質問のみを担当する」のように役割の境界を明確に書くことで、ハンドオフの精度が上がります。
ツール呼び出しのたびにBedrockへのAPI呼び出しが発生します。 ループを含む設計ではトークン消費が積み上がるため、終了条件の設計に注意が必要です。
まとめ
Strands AgentsはAWSが公開したPython製のOSSエージェントSDKで、Agent() 1行から動かし始められる手軽さが特徴です。AWSサービスとの統合を前提としたエージェントをシンプルに書きたい場面で選択肢に入れるSDKです。シンプルなエージェントから、マルチエージェントまで、幅広いエージェントの開発に対応できます。