Strands AgentsのAgents as Toolsパターンを試してみた

Strands AgentsのAgents as Toolsパターンを試してみた

2026.01.29

こんにちは。サービス開発室の武田です。

前回の記事ではStrands Agentsの全体像とパターン選択の判断基準について紹介しました。今回から各パターンの詳細な実装例を見ていきます。

今回は、もっともシンプルなマルチエージェントパターンである Agents as Tools を試してみました。

Agents as Toolsとは

Agents as Toolsは、エージェントを@toolデコレーターでラップし、別のエージェント(オーケストレーター)から呼び出す階層構造 のパターンです。

公式ドキュメントでは次のように説明されています。

"Agents as Tools" is an architectural pattern in AI systems where specialized AI agents are wrapped as callable functions (tools) that can be used by other agents.

「専門的なAIエージェントを呼び出し可能な関数(ツール)としてラップし、他のエージェントから利用できるようにするアーキテクチャパターン」ということですね。オーケストレーターエージェントが専門エージェントを調整して複雑な問題を解決する階層構造を形成します。

なぜこのパターンを使うのか

公式ドキュメントでは、このパターンの利点として次の4点が挙げられています。

利点 説明
Separation of Concerns 各エージェントが特定の領域に専念でき、保守性が向上する
Hierarchical Delegation オーケストレーターが適切な専門エージェントにタスクを振り分ける
Modular architecture 専門エージェントの追加・削除を独立して行える
Improved Performance 各エージェントをそのタスクに最適化できる

「責務の分離」「階層的な委譲」「モジュール性」「パフォーマンス向上」といった、ソフトウェア設計で馴染みのある原則がそのまま当てはまりますね。

基本的なしくみ

このパターンの構造を図で示すとこうなります。

strands-agents-agents-as-tools-pattern_1.png

オーケストレーターがユーザーからの入力を受け取り、適切な専門エージェントを「ツール」として呼び出します。専門エージェントの結果はオーケストレーターに返され、必要に応じて統合や追加処理が行われます。

@toolデコレーターの役割

Strands Agentsでは、@toolデコレーターを使ってPython関数をツール化します。LLMはツールの説明(docstring)を頼りに、いつ・どのようにツールを使うかを判断します。そのためdocstringの内容が重要です。

公式ドキュメントでは、docstringに次の内容を含めるとよいとされています。

  • ツールの目的
  • どのような場面で使うか
  • パラメーターの形式
  • 期待される出力形式
  • 制限事項や注意点

実装例1: 基本形(翻訳エージェント)

まずはもっともシンプルな例から見ていきましょう。翻訳専門のエージェントをツールとしてラップし、オーケストレーターから呼び出します。

専門エージェントをツールでラップ

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/01_basic_agent_as_tool.py#L18-L37

@toolデコレーターを付けた関数の内部でAgentを作成し、その結果を返しています。ポイントは次のとおりです。

  • docstringに「テキストを指定された言語に翻訳する専門家エージェント」という説明を記載し、オーケストレーターがこのツールの用途を理解できるようにしている
  • 引数texttarget_language、戻り値の型を明示している
  • 翻訳タスクに特化したシステムプロンプトを専門エージェントに与えている

オーケストレーターの作成

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/01_basic_agent_as_tool.py#L41-L56

オーケストレーターはtoolsパラメーターで専門エージェント(translator_agent)を登録しています。システムプロンプトでは、翻訳リクエストがあった場合にこのツールを使うよう指示しています。

実行すると、オーケストレーターが「英語に翻訳してください」というリクエストを受け取り、translator_agentツールを呼び出して翻訳します。複数言語への翻訳が必要な場合は、それぞれの言語に対してツールを呼び出してくれます。

実装例2: 複数の専門エージェント

次に、複数の専門エージェントをオーケストレーターが使い分ける例を見てみましょう。数学・歴史・科学の各専門家がいて、質問内容に応じて適切な専門家が選ばれます。

専門エージェントの定義

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/02_multiple_specialists.py#L17-L74

それぞれの専門エージェントは、その分野に特化したシステムプロンプトを持っています。docstringには「数学の専門家エージェントです。数学的な問題を解決します。」のように、どのような質問に対応するかを明記しています。

オーケストレーターの設定

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/02_multiple_specialists.py#L78-L89

オーケストレーターのシステムプロンプトには、どの質問にどの専門家を使うかのガイドラインを記載しています。ただし最終的な判断はLLMが行います。

tools=[math_expert, history_expert, science_expert]

このように3つの専門エージェントを登録しています。「ピタゴラスについて、数学者としての業績と生きた時代背景を教えてください」のような複合的な質問では、数学と歴史の両方の専門家に相談することもあります。

実装例3: 階層構造(3層)

最後に、より複雑な階層構造の例を紹介します。エージェントが別のエージェントをツールとして持ち、さらにそのエージェントも別のエージェントをもつ多層構造です。

最上層: orchestrator(テックリード)
    ↓
中間層: code_review_agent(コードレビュー統括)
    ↓
最下層: code_formatter, code_explainer(専門家)

最下層の専門エージェント

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/03_hierarchical_agents.py#L19-L58

code_formatterはコードの整形を、code_explainerはコードの解説を担当します。それぞれが単一の責務を持っています。

中間層のエージェント

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/03_hierarchical_agents.py#L62-L88

code_review_agentは最下層の2つの専門エージェントをツールとして持っています。レビュー時には、まず整形してもらい、次に解説してもらい、そのうえで改善点をコメントするという流れをオーケストレートします。

最上層のオーケストレーター

https://github.com/TAKEDA-Takashi/study-for-strands-agents/blob/main/01-agents-as-tools/03_hierarchical_agents.py#L92-L116

最上層のオーケストレーターは中間層のcode_review_agentのみを知っています。コードレビューが必要な場合は中間層に依頼し、中間層が最下層の専門家を使い分けます。

この階層構造のメリットは次のとおりです。

  • 各層での役割が明確
  • 層ごとに変更可能(最下層に新しい専門家を追加しても最上層には影響しない)
  • 必要に応じて層を追加できる

このパターンが向いているケース

向いているケース

  • 翻訳、要約、分析など、タスクの種類がはっきりしている場合
  • オーケストレーターがタスクの振り分けを判断する構造が適切な場合
  • 専門家の結果をそのまま返すか、軽い加工で済む場合

向いていないケース

  • 専門家間で動的に引き継ぎたい → Swarm
  • 条件分岐やループが必要 → Graph
  • 固定フローを再利用可能なツールとして定義したい → Workflow

Swarmとの比較

Agents as ToolsとSwarmは、どちらも複数のエージェントが協調するパターンですが、制御のしかたが根本的に異なります。

公式ドキュメントでは、Swarmを「Agent-driven」と表現しています。一方、Agents as Toolsは利点として「Hierarchical Delegation(階層的委譲)」が挙げられており、オーケストレーターが専門家を階層的に制御する構造が特徴ですね。

観点 Agents as Tools Swarm
構造 階層構造 フラット構造(ピア間)
実行フロー 各呼び出し後オーケストレーターに戻る 目標達成まで自律的に継続
専門家間の引き継ぎ オーケストレーター経由 handoff_to_agentで直接
開発者の制御 システムプロンプトで選択基準を定義 初期プロンプトで目標を設定

Swarmについて、公式ドキュメントでは次のように説明されています。

An agent performs a task and then uses a handoff_to_agent tool to pass control.

エージェントがタスクを実行した後、handoff_to_agentツールを使って自分で次のエージェントを決めて直接引き継ぐというしくみです。Swarmでは中央制御なしでエージェント間の対等な協調が行われます。

一方、Agents as Toolsでは常にオーケストレーターを経由して専門家が呼び出されます。オーケストレーターが「管理者」として振る舞い、どの専門家を呼ぶかを判断するわけですね。

どちらがよいかはユースケース次第です。予測可能な動作が求められる場合はAgents as Tools、柔軟な対応が求められる場合はSwarmがよさそうです。

まとめ

Agents as Toolsは、Strands Agentsでもっともシンプルなマルチエージェントパターンです。@toolデコレーターでエージェントをラップし、オーケストレーターが専門家を「ツール」として呼び出します。階層構造で複雑なタスクを分解でき、制御の明示性と予測可能性が特徴ですね。

公式ドキュメントでは、Graph・Swarm・Workflowが「3つの主要パターン」として紹介されていますが、Agents as Toolsはそれらの基礎となる構成要素といえます。まずはこのパターンを理解することで、他のパターンの理解もスムーズになるでしょう。どなたかの参考になれば幸いです。

参考リンク

この記事をシェアする

FacebookHatena blogX

関連記事