Amazon Nova Sonic を用いたスケーラブルな音声エージェント設計:マルチエージェント、ツール連携、セッション分割
AWS は Amazon Nova Sonic、Bedrock AgentCore、Strands Agents を組み合わせたアーキテクチャパターンを公開し、音声エージェントのレイテンシ低減とスケーラビリティ向上の実現方法を詳述した。
キーポイント
高パフォーマンスな音声エージェント基盤の統合
Amazon Nova Sonic(音声生成モデル)、Bedrock AgentCore Runtime(サーバーレスホスティングとセッション分離)、Strands Agents(オープンソースフレームワーク)を組み合わせ、リアルタイム性の高い音声対話を実現する。
レイテンシ低減のための技術的アプローチ
マイクロVMレベルのセッション隔離により「ノイジー・ネイバー」問題を排除し、双方向 WebSocket ストリーミングと SigV4 認証を活用して応答速度を最大化する設計パターンを提示している。
複雑なワークフロー管理とツール連携
マルチエージェント構成やセッションセグメンテーション、Model Context Protocol (MCP) を介した共有ツールホスティングなど、複雑なビジネスプロセスに対応するためのアーキテクチャパターンを解説している。
サブエージェントのツール化とオーケストレーション
認証、銀行、住宅ローンなどの専門タスクを個別の Agent として定義し、@tool デコレータでラップして BidiAgent オーケストレーターから呼び出せるように設計している。
Nova Sonic を用いた双方向音声連携
Amazon Nova-2-Sonic モデルと Strands の BidiAgent を組み合わせ、低遅延な双方向音声通信を実現しながら専門サブエージェントのツール使用をシームレスに実行する。
役割ごとの専用プロンプトと制約
各サブエージェントに明確なシステムプロンプト(例:「自然な会話で要約」「生 JSON を返さない」)を設定し、音声出力に適した簡潔かつ人間らしい応答を強制している。
専門特化型サブエージェントによるタスクルーティング
単一の汎用モデルではなく、認証、銀行口座、住宅ローンなど特定のトピックを処理する専用のサブラーティングツール(サブエージェント)に顧客リクエストを振り分ける設計を採用しています。
影響分析・編集コメントを表示
影響分析
この記事は、音声 AI を実務レベルで導入する組織にとって、単なる機能紹介を超えた具体的な実装指針を提供するものであり、特にリアルタイム性が求められるコールセンターや顧客対応分野での採用加速に寄与する。AWS のエコシステム内での標準的なベストプラクティスが確立されることで、開発者の参入障壁が下がり、音声エージェント市場の成熟を早める契機となるだろう。
編集コメント
音声 AI の実用化において最も課題となる「遅延」と「安定性」を、インフラレベルの技術(マイクロVM隔離など)で解決するアプローチは非常に示唆に富んでいます。開発者がすぐに適用可能な具体的な設計パターンが提示されている点が高く評価されます。
スケーラブルな音声エージェントの設計パターンは、迅速かつ自然で信頼性の高い音声体験を提供する必要がある組織にとって重要です。多くのチームは、レイテンシの高さ、リアルタイムオーディオの管理、複雑なワークフローにおける複数エージェントの調整といった課題に直面しています。
本記事では、これらの課題を効率的に処理し、より応答性が高く知的な顧客インタラクションを実現するスケーラブルで保守可能な音声エージェントを構築する方法について学びます。具体的には、Amazon Nova Sonic、Amazon Bedrock AgentCore、および Strands BidiAgent の活用方法について解説します。
音声エージェントの 3 つの一般的なアーキテクチャパターンを探求し、それぞれのトレードオフとレイテンシを最小限に抑えるためのベストプラクティスについて強調して説明します。
ビルドブロック
アーキテクチャパターンについてさらに深く掘り下げる前に、本記事のサンプルソリューションとして使用される 3 つの主要コンポーネントの簡単な概要を紹介します。

Amazon Nova Sonic は、生成 AI アプリケーション向けに自然で人間のような音声対話を実現するファウンデーションモデルです。ユーザーはリアルタイムで音声を通じて AI と対話し、トーンの理解や自然な会話の流れの維持、アクションの実行といった機能を利用できます。
Amazon Bedrock AgentCore Runtime は、AI エージェント向けのサーバーレスホスティング環境です。エージェントをコンテナとしてパッケージ化し、AgentCore Runtime にデプロイするだけで、スケーリング、セッションの分離、課金処理を自動で管理します。音声エージェント向けには、SigV4 認証による双方向 WebSocket ストリーミング bidirectional WebSocket streaming を提供し、マイクロ VM レベルのセッション分離により「ノイジー・ネイバー」によるレイテンシスパイクを防止します。また、Model Context Protocol (MCP) オープンソースプロトコルを活用した共有ツールホスティングのための AgentCore Gateway、セッション間での永続的メモリ機能、音声固有の指標(初回音声までの時間など)を計測するテレメトリ機能を備えています。
Strands Agents は、AI エージェントを構築するためのオープンソースフレームワークです。その BidiAgent クラスは、Nova Sonic とアプリケーション間の統合オプションの一つであり、双方向ストリームのライフサイクル管理、ツール呼び出しのルーティング、セッション管理を担当し、モデル SDK インターフェースを通じて音声エージェントアプリケーションを簡素化します。
3 つの統合パターン:ツール、サブエージェントとしてのエージェント(sub-agent)、およびセッションセグメンテーション
すべての機能を持つ単一の強力なエージェントを構築するのではなく、現代の音声システムは、ツール駆動型エージェント、ツールとして動作するサブエージェント、そしてプロンプト、メモリ、権限を分離するセッションセグメンテーション戦略で構成されることが増えています。これらのパターンにより、チームは大規模なアシスタントをより小さく専門的かつ再利用可能なコンポーネントに分解できながら、明確なセキュリティ境界を維持することができます。
以下のセクションのサンプルを実行する前に、Python と必要な依存関係(strands-agents および boto3 など)をインストールし、IAM 設定に必要なサービスの権限が設定されていることを確認してください。完全な例については、GitHub リポジトリ を参照してください。
パターン 1: AgentCore Gateway – 低遅延のためのツール選択
ツール呼び出しとは、音声エージェントが外部関数やサービスに入力を送信し、それが処理されて出力を返すプロセスのことです。これにより、エージェントは追加の推論ステップを経ずに、データベースへの照会やサービスのトリガーなどのタスクを迅速かつ安全に実行できます。
AgentCore Gateway を使用すると、既存のビジネスロジックをツールとして公開できます。これは Nova Sonic が会話中に直接呼び出すことができる個別関数です。音声モデルはどのツールを呼び出すかを選択し、パラメータを渡して結果を取得し、それを音声で返します。モデルとツールの間には中間推論層はありません。

AgentCore Gateway は、管理されたエンドポイントとして MCP サーバーをホストします。MCP はプロトコルであり、AgentCore Gateway はそれらを実行する AWS の機能です。音声エージェントは Gateway ARN を経由して接続されます。
Nova Sonic は AgentCore Gateway を介してツールを直接呼び出します
model = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=[
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/auth-tools",
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/banking-tools",
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/mortgage-tools",
],
)
ユーザーが「口座残高を教えてください」と言うと、Nova Sonic は以下の処理を行います:
- 音声から意図を理解します。
- 利用可能な MCP ツールの中から get_account_balance を選択します。
- 適切なパラメータでそのツールを呼び出します。
- 結果を音声で返答します。
トレードオフ: Nova Sonic はすべての判断を行います。ツールの呼び出しに多段階の検証、条件分岐、または複数の操作の連鎖が必要となる場合、その推論負荷はすべて音声モデルのシステムプロンプトに依存することになります。単純なツールであればこのアプローチで問題ありませんが、複雑なワークフローでは脆くなる可能性があります。
パターン 2: サブエージェント - 分離されたエージェントによる追加推論
サブエージェントまたは「エージェントをツールとして利用する」パターンでは、既存のビジネスロジックは自律型エージェント内で実行され、それぞれが独自のモデル、システムプロンプト、ツール、および推論能力を持ちます。音声オーケストレーターは個々のツールを呼び出すのではなく、これらのサブエージェントに対してタスク全体を委譲します。
音声エージェントからサブエージェントに接続する方法はいくつかあります。Agent-to-Agent (A2A) と Strands の Agent-as-Tool は、そのうち一般的な 2 つのアプローチです:
- ローカルエージェントをツールとして利用:サブエージェントはプロセス内で実行され、Strands の「Agents as Tools」パターンを用いて@tool 関数としてラップされます。これはネットワークホップも別個のデプロイメントも不要な最もシンプルなアプローチです。その代わり、サブエージェントはオーケストレーターと同じプロセスを共有し、オーケストレーターとスケールします。
- A2A プロトコルによるリモートエージェント:サブエージェントは AgentCore Runtime(またはリモートサーバー)上で独立した A2A サーバーとしてデプロイされ、ネットワーク経由で呼び出されます。A2A はエージェント間通信のためのオープンプロトコルです。MCP がエージェントをツールに接続するのと同様に、A2A はエージェントを他のエージェントに接続します。AgentCore Runtime における A2A プロトコルサポートに関する AWS ブログ記事が説明している通り、異なるフレームワーク(Strands, OpenAI, LangGraph, Google ADK)で構築されたエージェントも、共通形式でコンテキストと推論を共有できます。これにより、完全なデプロイの独立性とクロスフレームワーク間の相互運用性が実現されます。

Strands Agents には、ツールアクセス用の MCP とエージェント間通信用の A2A の両プロトコルに対する組み込みサポートが用意されています。実践的なウォークスルーについては、コミュニティガイドの Agent Collaboration: Strands Agents, MCP, and the Agent2Agent Protocol をご覧ください。
以下に、ローカルエージェントをツールとして利用するアプローチを示します。各サブエージェントは、完全な Strands エージェントをラップした@tool となります。
sub_agents.py — Agents-as-Tools パターンを使用して、Strands ツールとしてサブエージェントを定義する
from strands import Agent, tool
from strands.models import BedrockModel
各サブエージェントは、@tool デコレータでラップされた完全な Strands エージェントです
BidiAgent オーケストレーターは、Nova Sonic のツール使用機能を通じてこれらを呼び出します
@tool
def authenticate_customer(account_id: str, date_of_birth: str) -> str:
"""顧客のアカウント ID と生年月日を使用して顧客を認証する。
本人確認やリトライロジックを含む完全な検証フローを処理します。
認証ステータスとトークンを返します。"""
auth_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""あなたは認証エージェントです。提供されたアカウント ID と生年月日を使用して顧客の身元を確認してください。
verify_identity を呼び出して資格情報をチェックします。明確な認証ステータスを 1〜2 文で返してください。""",
tools=[verify_identity, check_account_exists], # サブエージェント固有のツール
)
result = auth_agent(f"アカウント {account_id}、生年月日:{date_of_birth} を認証してください")
return str(result)
@tool
def handle_banking_inquiry(query: str, auth_token: str) -> str:
"""銀行に関する問い合わせ(残高、取引、送金など)を処理します。
権限を検証し、会話形式の要約を返します。"""
banking_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""あなたは銀行担当エージェントです。提供されたツールを使用して
顧客の問い合わせに回答してください。結果は自然な文で2〜3文に要約してください。
生データの JSON は返さないでください。""",
tools=[get_account_balance, get_recent_transactions, transfer_funds],
)
result = banking_agent(query)
return str(result)
@tool
def handle_mortgage_inquiry(query: str) -> str:
"""住宅ローンに関する問い合わせ(金利、計算、審査基準、申込状況など)を処理します。
独自の計算と推論を行います。"""
mortgage_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""あなたは住宅ローン専門家です。金利の問い合わせ、返済額の計算、審査基準の評価を支援してください。
回答は簡潔かつ会話調に保ち、これは音声で読み上げられることを想定しています。""",
tools=[get_mortgage_rates, calculate_payment, check_eligibility],
)
result = mortgage_agent(query)
return str(result)
音声オーケストレーターはその後、これらのサブエージェントツールを使用して BidiAgent を活用します:
voice_orchestrator.py — BidiAgent をサブエージェントをツールとして使用
from strands.experimental.bidi.agent import BidiAgent
from strands.experimental.bidi.models.nova_sonic import BidiNovaSonicModel
from sub_agents import authenticate_customer, handle_banking_inquiry, handle_mortgage_inquiry
model = BidiNovaSonicModel(
region="us-east-1",
model_id="amazon.nova-2-sonic-v1:0",
provider_config={"audio": {"voice": "tiffany", "input_sample_rate": 16000, "output_sample_rate": 16000}},
)
agent = BidiAgent(
model=model,
tools=[authenticate_customer, handle_banking_inquiry, handle_mortgage_inquiry],
system_prompt="""あなたは銀行の音声アシスタントです。顧客のリクエストを適切な専門家にルーティングしてください。アカウントデータにアクセスする前には必ず本人確認を行ってください。
自身の応答は簡潔にし、詳細はサブエージェントが担当するようにしてください。""",
)
await agent.run(inputs=[ws_input], outputs=[ws_output])
サブエージェントは独自の思考を行います。Nova Sonic は個々のステップを調整する必要はありません。委任し、結果を発話します。
トレードオフ: 各サブエージェントの呼び出しはレイテンシを追加します。これには、サブエージェント自身のモデル推論とツール呼び出しが含まれます。音声会話では、これはサブエージェントが推論している間に生じるより長い沈黙を意味します。AWS のブログ Amazon Nova Sonic と Amazon Bedrock Agent Core を使用したマルチエージェント音声アシスタントの構築 では、レイテンシを削減しつつ専門的なタスクも効果的に処理するために、サブエージェントには Amazon Nova 2 Lite のような小さく効率的なモデルから始めることを推奨しています。
Amazon Nova 2 Sonic は 非同期ツール呼び出し をサポートしているため、ツールがバックグラウンドで実行されている間も会話は自然に続きます。入力を受け付け続け、複数のツールを並列で実行でき、ユーザーがプロセス途中でリクエストを変更した場合でも柔軟に対応し、関連する部分に焦点を当てながらすべての結果を提供します。
パターン 3: 超低レイテンシのためのセッション分割
検討すべき第三のアプローチがあります。これは MCP やサブエージェントのパターンには明確には対応していませんが、レイテンシが最優先事項となる音声シナリオのために特別に設計されたものです。
外部ツールやサブエージェントに委譲するのではなく、会話を論理的なフェーズに分割し、それぞれを独立した Nova Sonic セッション、システムプロンプト、およびツールセットとして扱います。会話があるフェーズから次のフェーズ(例えば認証から口座照会へ)に移行する際、現在のセッションを終了し、同じ WebSocket 接続内で異なるプロンプトとツールを持つ新しいセッションを開始します。各サブ音声エージェントは独自の MCP ゲートウェイ、ツール、さらにはサブエージェントを使用できますが、焦点を絞ったプロンプトと最小限のツール表面で動作するため、推論オーバーヘッドとレイテンシが削減されます。

銀行の音声アシスタントを例に、認証、口座管理、住宅ローン照会の 3 つの会話フェーズがあると想像してください。すべてのツールを含む巨大なシステムプロンプトを読み込むのではなく、各フェーズを焦点を絞った Nova Sonic セッションとして実行します:
フェーズ 1:認証
auth_session = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=["arn:...gateway/auth-tools"], # 認証ツールのみ使用
)
auth_agent = BidiAgent(
model=auth_session,
tools=[],
system_prompt="""あなたは認証アシスタントです。
ユーザーのアカウント ID と生年月日を収集してください。
verify_identity を呼び出して本人確認を行ってください。
確認が完了したら「準備が整いました」と言って終了してください。""",
)
認証が完了するまで実行
await auth_agent.run(inputs=[ws_input], outputs=[ws_output])
フェーズ 2:アカウント管理(新しいセッション、新しいプロンプト、新しいツール)
banking_session = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=["arn:...gateway/banking-tools"], # 銀行業務ツールのみ使用
)
banking_agent = BidiAgent(
model=banking_session,
tools=[],
system_prompt="""あなたは銀行アシスタントです。ユーザーはすでに認証済みです。
残高照会、取引、送金についてサポートしてください。
回答は 1〜2 文に抑えてください。""",
)
await banking_agent.run(inputs=[ws_input], outputs=[ws_output])
各フェーズでは、以下の特徴を持つクリーンな Nova Sonic セッションが用意されます:
- 焦点を絞ったシステムプロンプト:より短く、より具体的であり、モデルが混乱する余地を減らします。
- 必要なツールのみ:MCP ゲートウェイ(Model Context Protocol)、ローカルツール、またはその両方を通じて。モデルは、3 つのツールしか必要ないのに 15 のツールから選択するために推論サイクルを無駄にしません。
- オプションとして独自のサブエージェント:より深い推論が必要なフェーズでは内部でパターン 2 を使用し、単純なフェーズはツールのみを使用します。
- 前のセッションのコンテキストは、チャット履歴として新しいセッションに渡すことができるため、全体としての会話の一貫性が保たれます。
ツール、サブエージェント、およびセッションセグメンテーションパターンとの比較
要因
ツール
サブエージェント(Agent-as-Tool)
セッションセグメンテーション
レイテンシ
低
高い(サブエージェントの推論による)
最低(セッション遷移時のレイテンシあり)
1 回のターンごとのツールセット
読み込まれたツール
サブエージェントのツール
フェーズ関連のみのツール
システムプロンプト
1 つの大規模なプロンプト
オーケストレーター+サブエージェントのプロンプト
小さく、フェーズ固有のプロンプト
推論の深さ
音声モデルのみ
音声モデル+サブエージェント
音声モデルのみ(フェーズごと)
既存のエージェントの再利用
高い(同じ MCP ツール)
最高(同じサブエージェント)
中程度(フェーズごとにツール/サブエージェントを構成)
会話の一貫性
シームレス
シームレス
フェーズ間のハンドオフロジックが必要
音声エージェントのレイテンシに関するベストプラクティス
音声エージェントとテキストエージェントを構築する際、レイテンシは重要な考慮事項です。応答時間を高速かつ即座に保つための実用的なテクニックを以下に示します。
サブエージェントには小規模モデルから開始してください。 会話のオーケストレーションを行う音声オーケストレーターでは Nova Sonic を使用しますが、サブエージェントに大規模モデルは必要ありません。Amazon Nova 2 Lite または Nova 2 Micro から始めるのが良いでしょう。これらは高速でコスト効率に優れ、ほとんどの専門タスクを適切に処理できます。品質が必要であれば特定のサブエージェントをより大規模なモデルへアップグレードすることも可能ですが、基本方針としては小規模モデルを使用してください。
キャッシュを活用したステートフルなサブエージェントを設計してください。 毎回データベースや API にアクセスするステートレスなサブエージェントは、呼び出しのたびにレイテンシを追加してしまいます。代わりに、セッション内でデータソース(API、AWS Lambda 関数、データベース)からの結果をキャッシュするようにサブエージェントを設計しましょう。例えば、銀行関連のサブエージェントがアカウント詳細を一度取得した場合、そのデータをメモリ内に保持し、後続の質問(残高、取引履歴、要約など)に対してバックエンドへの繰り返し呼び出しを行わずにキャッシュから応答を提供すべきです。
認証後にデータをプリフェッチしてください。 これはコンタクトセンターのシナリオにおいて特に価値があります。顧客が認証を完了した時点で、すでに誰であるかが分かっています。彼らが質問するのを待ってからデータを取得する必要はありません。直ちにアカウント残高、最近の取引、保留中のアラート、および住宅ローンのステータスを取得し
原文を表示
Design patterns for scalable voice agents matter for organizations that need to deliver fast, natural, and reliable voice experiences. Many teams face challenges like high latency, managing real-time audio, and coordinating multiple agents in complex workflows.
In this post, you’ll learn how to use Amazon Nova Sonic, Amazon Bedrock AgentCore, and Strands BidiAgent to build scalable, maintainable voice agents that handle these challenges efficiently, resulting in more responsive and intelligent customer interactions.
We’ll explore three popular architectural patterns for voice agents, highlighting their trade-offs and best practices for minimizing latency.
The building blocks
Before diving deeper into the architecture patterns, here’s a quick overview of the three key components used as the sample solution in this post.

Amazon Nova Sonic is a foundation model that creates natural, human-like speech-to-speech conversations for generative AI applications. Users can interact with AI through voice in real time, with capabilities for understanding tone, natural conversational flow, and performing actions.
Amazon Bedrock AgentCore Runtime is a serverless hosting environment for AI agents. You package your agent as a container, deploy to AgentCore Runtime, and it handles scaling, session isolation, and billing. For voice agents, it provides bidirectional WebSocket streaming with SigV4 auth, microVM-level session isolation to avoid noisy-neighbor latency spikes, AgentCore Gateway for shared tool hosting using the Model Context Protocol (MCP) open source protocol, persistent memory across sessions, and telemetry for voice-specific metrics like time-to-first-audio.
Strands Agents is an open source framework for building AI agents. Its BidiAgent class is one integration option between Nova Sonic and your application. It manages the bidirectional stream lifecycle, routes tool calls, and handles session management, simplifying the voice agent application through the model SDK interface.
Three integration patterns: tool, agent-as-tool (sub-agent), and session segmentation
Instead of building one all-powerful agent, modern voice systems are increasingly composed of tool-driven agents, sub-agents acting as tools and session segmentation strategies that isolate prompts, memory, and permissions. These patterns allow teams to decompose large assistants into smaller, specialized, and reusable components while maintaining clear security boundaries.
Before running the samples in the following sections, install Python and the required dependencies, including strands-agents and boto3, and make sure your IAM setup has the necessary permissions for the required services. For the full example, refer to the GitHub repository.
Pattern 1: AgentCore Gateway – tool selection for low latency
A tool call is when a voice agent sends input to an external function or service, which processes it and returns output. It lets the agent perform tasks like querying a database or triggering a service quickly and securely, without extra reasoning steps.
With AgentCore Gateway, you expose your existing business logic as tools, discrete functions that Nova Sonic can call directly during a conversation. The voice model selects which tool to invoke, passes parameters, gets a result, and speaks it back. There’s no intermediate reasoning layer between the model and the tool.

AgentCore Gateway hosts MCP servers as managed endpoints. MCP is the protocol, AgentCore Gateway is the AWS feature that runs them. The voice agent connects via Gateway ARNs.
# Nova Sonic calls tools directly via AgentCore Gateway
model = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=[
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/auth-tools",
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/banking-tools",
"arn:aws:bedrock-agentcore:us-east-1:123456789012:gateway/mortgage-tools",
],
)When a user says “What’s my account balance?”, Nova Sonic:
- Understands the intent from speech.
- Selects get_account_balance from the available MCP tools.
- Calls the tool with the right parameters.
- Speaks the result back.
Trade-off: Nova Sonic makes all the decisions. If a tool call requires multi-step validation, conditional logic, or chaining multiple operations together, that reasoning burden falls entirely on the voice model’s system prompt. For simple tools this is fine. For complex workflows, it gets brittle.
Pattern 2: Sub-agent – additional reasoning with decoupled agents
With the sub-agent or agent-as-tool pattern, your existing business logic runs in autonomous agents, each with its own model, system prompt, tools, and reasoning capabilities. The voice orchestrator delegates whole tasks to these sub-agents instead of calling individual tools.
There are many ways to connect to a sub-agent from your voice agent. Agent-to-Agent (A2A) and Strands Agent-as-Tool are two common approaches:
- Local agent-as-tool: The sub-agent runs in-process, wrapped as a @tool function using the Agents as Tools pattern in Strands. This is the most straightforward approach with no network hop and no separate deployment. The trade-off is that the sub-agent shares the same process and scales with the orchestrator.
- Remote agent via A2A protocol: The sub-agent is deployed as an independent A2A server on AgentCore Runtime (or a remote server) and invoked over the network. A2A is an open protocol for agent-to-agent communication. As MCP connects agents to tools, A2A connects agents to other agents. As the AWS blog on A2A protocol support in AgentCore Runtime explains, agents built with different frameworks (Strands, OpenAI, LangGraph, Google ADK) can share context and reasoning in a common format. This provides full deployment independence and cross-framework interoperability.

Strands Agents has built-in support for both protocols, MCP for tool access and A2A for agent-to-agent communication. For a hands-on walkthrough, see the community guide on Agent Collaboration: Strands Agents, MCP, and the Agent2Agent Protocol.
Here’s the local agent-as-tool approach, each sub-agent is a @tool wrapping a full Strands Agent:
# sub_agents.py — Define sub-agents as Strands tools using the Agents-as-Tools pattern
from strands import Agent, tool
from strands.models import BedrockModel
# Each sub-agent is a full Strands Agent wrapped as a @tool
# The BidiAgent orchestrator calls these via Nova Sonic's tool use
@tool
def authenticate_customer(account_id: str, date_of_birth: str) -> str:
"""Authenticate a customer using their account ID and date of birth.
Handles the full verification flow including identity checks and retry logic.
Returns authentication status and token."""
auth_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""You are an authentication agent. Verify the customer's identity
using the provided account ID and date of birth. Call verify_identity to check
credentials. Return a clear auth status in 1-2 sentences.""",
tools=[verify_identity, check_account_exists], # Sub-agent's own tools
)
result = auth_agent(f"Authenticate account {account_id}, DOB: {date_of_birth}")
return str(result)
@tool
def handle_banking_inquiry(query: str, auth_token: str) -> str:
"""Handle banking questions — balances, transactions, transfers.
Validates permissions and returns a conversational summary."""
banking_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""You are a banking agent. Use the provided tools to answer
the customer's query. Summarize results in 2-3 natural sentences.
Do not return raw JSON.""",
tools=[get_account_balance, get_recent_transactions, transfer_funds],
)
result = banking_agent(query)
return str(result)
@tool
def handle_mortgage_inquiry(query: str) -> str:
"""Handle mortgage questions — rates, calculations, eligibility, application status.
Performs its own calculations and reasoning."""
mortgage_agent = Agent(
model=BedrockModel(model_id="amazon.nova-lite-v1:0"),
system_prompt="""You are a mortgage specialist. Help with rate inquiries,
payment calculations, and eligibility assessments. Keep responses concise
and conversational — this will be spoken aloud.""",
tools=[get_mortgage_rates, calculate_payment, check_eligibility],
)
result = mortgage_agent(query)
return str(result)The voice orchestrator then uses BidiAgent with these sub-agent tools:
# voice_orchestrator.py — BidiAgent with sub-agents as tools
from strands.experimental.bidi.agent import BidiAgent
from strands.experimental.bidi.models.nova_sonic import BidiNovaSonicModel
from sub_agents import authenticate_customer, handle_banking_inquiry, handle_mortgage_inquiry
model = BidiNovaSonicModel(
region="us-east-1",
model_id="amazon.nova-2-sonic-v1:0",
provider_config={"audio": {"voice": "tiffany", "input_sample_rate": 16000, "output_sample_rate": 16000}},
)
agent = BidiAgent(
model=model,
tools=[authenticate_customer, handle_banking_inquiry, handle_mortgage_inquiry],
system_prompt="""You are a banking voice assistant. Route customer requests to the
appropriate specialist. Always authenticate before accessing account data.
Keep your own responses brief — the sub-agents handle the details.""",
)
await agent.run(inputs=[ws_input], outputs=[ws_output])The sub-agent does its own thinking. Nova Sonic doesn’t need to orchestrate the individual steps. It delegates and speaks the result.
Trade-off: Each sub-agent call adds latency: the sub-agent’s own model inference plus its tool calls. In a voice conversation, this means longer silence while the sub-agent reasons. The AWS blog on multi-agent voice assistants recommends starting with smaller, efficient models like Amazon Nova 2 Lite for sub-agents to reduce latency while still handling specialized tasks effectively.
Amazon Nova 2 Sonic supports asynchronous tool calling, so the conversation continues naturally while tools run in the background. It keeps accepting input, can run multiple tools in parallel, and gracefully adapts if the user changes their request mid-process, delivering all results while focusing on what’s still relevant.
Pattern 3: Session segmentation for ultra-low latency
There’s a third approach worth considering. It doesn’t map neatly to the MCP or sub-agent patterns, but is purpose-built for voice scenarios where latency is the overriding concern.
Instead of delegating external tools or sub-agents, you segment the conversation into logical phases, each with its own Nova Sonic session, system prompt, and tool set. When the conversation transitions from one phase to the next (for example, from authentication to account inquiry), you close the current session and open a new one with a different prompt and tools, within the same WebSocket connection. Each sub-voice-agent can use its own MCP gateways, tools, or even sub-agents — the differences that it operates with a focused prompt and minimal tool surface, reducing reasoning overhead and latency.

Think of a banking voice assistant with three conversation phases: authentication, account management, and mortgage inquiry. Rather than loading one massive system prompt with every tool, you run each phase as a focused Nova Sonic session:
# Phase 1: Authentication
auth_session = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=["arn:...gateway/auth-tools"], # Only auth tools
)
auth_agent = BidiAgent(
model=auth_session,
tools=[],
system_prompt="""You are an authentication assistant.
Collect the user's account ID and date of birth.
Call verify_identity to authenticate.
Once verified, say 'You're all set' and stop.""",
)
# Run until authentication completes
await auth_agent.run(inputs=[ws_input], outputs=[ws_output])
# Phase 2: Account management (new session, new prompt, new tools)
banking_session = BidiNovaSonicModel(
model_id="amazon.nova-2-sonic-v1:0",
mcp_gateway_arn=["arn:...gateway/banking-tools"], # Only banking tools
)
banking_agent = BidiAgent(
model=banking_session,
tools=[],
system_prompt="""You are a banking assistant. The user is already authenticated.
Help with balance inquiries, transactions, and transfers.
Keep responses to one or two sentences.""",
)
await banking_agent.run(inputs=[ws_input], outputs=[ws_output])Each phase gets a clean Nova Sonic session with:
- A focused system prompt: Shorter, more specific, less room for the model to get confused.
- Only the relevant tools: via MCP gateways, local tools, or both. The model doesn’t waste reasoning cycles choosing between 15 tools when it only needs 3.
- Optionally its own sub-agents: a phase that requires deeper reasoning can use Pattern 2 internally, while simpler phases stay tool-only.
- The previous session context can be passed into the new session as chat history, so the overall conversation retains continuity.
Compared to tool, sub-agent, and session segmentation patterns
Factor
Tool
Sub-Agent (Agent-as-Tool)
Session Segmentation
Latency
Low
Higher (sub-agent reasoning)
Lowest (with latency during session transitions)
Tool set per turn
Tools loaded
Sub-agent’s tools
Only phase-relevant tools
System prompt
One large prompt
Orchestrator + sub-agent prompts
Small, phase-specific prompts
Reasoning depth
Voice model only
Voice model + sub-agent
Voice model only (per phase)
Reuse of existing agents
High (same MCP tools)
Highest (same sub-agents)
Medium (composes tools/sub-agents per phase)
Conversation continuity
Seamless
Seamless
Requires handoff logic between phases
Latency best practices for voice agents
Latency is a key consideration when building voice versus text agents. Here are practical techniques to keep response times fast and responsive:
Start with small models for sub-agents. Your voice orchestrator uses Nova Sonic for the conversation, but sub-agents don’t need a large model. Start with Amazon Nova 2 Lite or Nova 2 Micro. They’re fast, cost optimized, and handle most specialized tasks well. You can always upgrade a specific sub-agent to a larger model if quality requires it, but default to small.
Design stateful sub-agents with caching. A stateless sub-agent that hits a database or API on every call adds latency every time. Instead, design sub-agents to cache results from data sources (APIs, AWS Lambda functions, databases) within a session. If the banking sub-agent fetches account details once, it should hold that data in memory and serve subsequent questions (balance, transactions, summary) from cache rather than making repeated backend calls.
Prefetch data after authentication. This is especially valuable for contact center scenarios. After a customer authenticates, you already know who they are. Don’t wait for them to ask before pulling their data. Immediately fetch account balances, recent transactions, pending alerts, and mortgage status in the
関連記事
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み