AWS Strands Agents Multiagent Graph 試してみた

に公開

はじめに

Fusicのレオナです。今回は、Strands AgentsのMultiagent Graph機能を使ってみました。

Strands Agentsとは

Strands Agentsは、AWSが2025年5月に公開したオープンソースのAIエージェント構築SDKで、2025年7月にバージョン1.0がリリースされました。数行のPythonコードでAIエージェントを作成できるモデル駆動型のフレームワークです。

ベータ版のStrands Agentsについて執筆した以下のブログも参考にしてください。
https://zenn.dev/fusic/articles/8dd670c37a8d68

Strands Agents Multiagent Graphとは

そもそもグラフとは、物事を点(ノード)と線(エッジ)を結んだものになります。数学におけるグラフ理論になります。ここでは解説しません。

Strands Agents の Multiagent Graph は、複数のエージェントが協調するワークフローを有向非巡回グラフ(DAG) として表現する仕組みです。ノードとして配置された各エージェントやサブワークフローが、あらかじめ定義された依存関係で順番に実行されます。

A2Aプロトコルとの違い

Strands Agents には、異なるシステム間でエージェント同士が通信する「Agent‑to‑Agent(以下、A2A)」も用意されています。以下では、GraphA2Aの違いを簡潔にまとめました。

Strands AgentsでA2Aを実装してみたい方は以下のブログも参考にしてください。
https://zenn.dev/fusic/articles/379f26fa2ca7a5

特徴 Graph A2A
適用範囲 単一システム内のワークフロー 異なるシステムの通信
制御方法 あらかじめ定義されたワークフロー 標準化されたプロトコル
データ共有 メモリアクセス エージェントカードベース
実行環境 同一プロセス 分散ネットワーク環境

やってみた

今回は、Strands Agents のMultiagent Graphをカレーライス作りに置き換えて試してみました。例えば次のような工程があります。

  1. 材料の準備:必要な食材を揃える
  2. 野菜を切る:玉ねぎ・にんじん・じゃがいもを切る
  3. 肉を切る:鶏もも肉を一口大にし下味を付ける
  4. 炒める:野菜と肉を炒めて香りを引き出す
  5. 煮込む:水とブイヨンを加え具材が柔らかくなるまで煮る
  6. ルーを入れる:火を止めてカレールーを溶かし再加熱
  7. 味見:味が整っているか確認・調整
  8. 盛り付け:ご飯とカレーを皿に盛り付ける

例えば、「味見」の結果しだいで煮込みに戻るか盛り付けに進むか、といった分岐も条件付きエッジとして表現できます。このようにGraphを使えば、料理レシピの手順と依存関係をそのままモデル化でき、実行順序や条件分岐を定義できます。

実装

実際に Strands Agents のGraphBuilderを使ってカレーの工程を組んでみます。各工程をエージェントとして実装しました。今回はGraphの遷移を見たいのでエージェントが生成したテキストを表示させていません。

main.py
from strands import Agent
from strands.multiagent import GraphBuilder
from strands.models import BedrockModel
import contextlib, os 

bedrock_model = BedrockModel(
    model_id="apac.anthropic.claude-sonnet-4-20250514-v1:0",
    region="ap-northeast-1"
)
# 各工程の担当エージェント
prep = Agent(
    name="prep",
    system_prompt="材料の確認・下準備を簡潔に説明してください。",
    model=bedrock_model
)
cut_veg = Agent(
    name="cut_veg",
    system_prompt="野菜の切り方を短く説明してください。",
    model=bedrock_model
)
cut_meat = Agent(
    name="cut_meat",
    system_prompt="肉の処理・下味付けを短く説明してください。",
    model=bedrock_model
)
saute = Agent(
    name="saute",
    system_prompt="炒めのポイントを説明してください。",
    model=bedrock_model
)
simmer = Agent(
    name="simmer",
    system_prompt="煮込む際の水加減や火加減を説明してください。",
    model=bedrock_model
)
add_roux = Agent(
    name="add_roux",
    system_prompt="ルーの入れ方を説明してください。",
    model=bedrock_model
)
taste = Agent(
    name="taste",
    system_prompt="味見担当です。一行目にPASSかFAILを書き、二行目に調整案を記載してください。",
    model=bedrock_model

)
plate = Agent(
    name="plate",
    system_prompt="盛り付けのポイントを説明してください。",
    model=bedrock_model
)

# Graph 構築(元のまま)
gb = GraphBuilder()
gb.add_node(prep, "prep"); gb.add_node(cut_veg, "cut_veg"); gb.add_node(cut_meat, "cut_meat")
gb.add_node(saute, "saute"); gb.add_node(simmer, "simmer"); gb.add_node(add_roux, "add_roux")
gb.add_node(taste, "taste"); gb.add_node(plate, "plate")
gb.add_edge("prep", "cut_veg"); gb.add_edge("prep", "cut_meat")
gb.add_edge("cut_veg", "saute"); gb.add_edge("cut_meat", "saute")
gb.add_edge("saute", "simmer"); gb.add_edge("simmer", "add_roux"); gb.add_edge("add_roux", "taste")

def taste_passed(state):
    text = str(state.results["taste"].result).lower()
    return "pass" in text
def taste_failed(state):
    text = str(state.results["taste"].result).lower()
    return "fail" in text
gb.add_edge("taste", "plate", condition=taste_passed)
gb.add_edge("taste", "simmer", condition=taste_failed)

gb.set_entry_point("prep")
graph = gb.build()

# 実行
with open(os.devnull, "w") as devnull, \
    contextlib.redirect_stdout(devnull), \
    contextlib.redirect_stderr(devnull):
    result = graph("4人前のチキンカレーを作ってください。")

# 遷移ログだけを表示
for i, (name, node_result) in enumerate(result.results.items(), start=1):
    status = getattr(node_result, "status", "UNKNOWN")
    print(f"{i}. {name} -> {status}")

print("-" * 40)
print("[END] plate に到達" if "plate" in result.results else "盛り付けまで進みませんでした")

結果

Terminal
1. prep -> Status.COMPLETED
2. cut_veg -> Status.COMPLETED
3. cut_meat -> Status.COMPLETED
4. saute -> Status.COMPLETED
5. simmer -> Status.COMPLETED
6. add_roux -> Status.COMPLETED
7. taste -> Status.COMPLETED
8. plate -> Status.COMPLETED
----------------------------------------
[END] plate に到達

全てのノードが Status.COMPLETED となっており、途中の味見も合格だったため、最後の盛り付け工程までスムーズに進めたことが確認できます。つまり、「材料の準備」から「野菜や肉を切る」「炒める」「煮込む」「ルーを入れる」「味見」までの各工程を順番に問題なく完了し、無事に盛り付けまで到達したという結果になります。

まとめ

Strands AgentsのMultiagent Graphがどのようにノード間の依存関係や条件分岐を管理するのかを知れました。Graphは「材料の準備→切る→炒める→煮込む→味見→盛り付け」のような工程を明確に表現できる有向グラフであり、エッジに条件を付けることで成功時と失敗時の分岐も書けます。AIエージェントが何をいつ実行するかを管理し、再現性の高いワークフローを構築できる点が大きなメリットだと感じます。

Fusic 技術ブログ

Discussion