SageMaker AI と Bedrock AgentCore によるエージェンティックワークフローの構築
Amazon SageMaker AI の OpenAI 互換エンドポイントと Amazon Bedrock AgentCore ランタイムを組み合わせて、各専門エージェントが最適なモデルを使用するマルチエージェントワークフローを構築する方法を紹介します。また、Strands Agents がデフォルトで計測しない SageMaker エンドポイントのトークンレベルの可観測性を取得する方法も説明します。
エージェンティックワークフローを構築する際の一般的な課題は、マネージド基盤モデルと、独自のコスト最適化またはドメイン固有モデルを、エージェントフレームワークを書き直すことなく混在させることです。この記事では、Amazon SageMaker AI の OpenAI 互換エンドポイントと Amazon Bedrock AgentCore ランタイム(Amazon Bedrock AgentCore の機能)およびそのマネージドデプロイを組み合わせる方法を紹介します。専門エージェントは複雑なタスクで連携しながら、それぞれがそのジョブに最適なモデルを使用できます。この組み合わせにより、単一の本番環境対応アーキテクチャでコスト最適化、データ常駐、モデルの柔軟性が得られます。
ソリューション概要:アーキテクチャは、単一の Amazon Bedrock AgentCore コンテナを介して3つのモデルホスティングパスを接続します。オーケストレーターエージェント(Bedrock 上の Claude Haiku 4.5)はユーザーの意図を分類し、グローバルなクロスリージョン推論を通じてタスクをルーティングします。予算エージェント(Bedrock 上の Claude Sonnet 4.6)は、構造化された Pydantic 出力を使用して 50/30/20 の予算内訳を処理します。財務分析エージェント(SageMaker AI 上の Qwen 3.5 9B)は、ツール呼び出しを使用して株式分析とポートフォリオ構築を実行します。Amazon Bedrock のモデル可用性は AWS リージョンによって異なるため、ドキュメントを参照してください。
ユーザーリクエストは、AgentCore ランタイム内で実行されているオーケストレーターエージェントに入ります。オーケストレーターは、Strands Agents の agents as tools パターンを使用して、リクエストを予算エージェントまたは財務分析エージェントにルーティングします。予算エージェントは Amazon Bedrock 経由で Claude Sonnet 4.6 を呼び出し、財務分析エージェントは SageMaker AI リアルタイムエンドポイントの OpenAI 互換 API を介して Qwen 3.5 9B を呼び出します。結果はオーケストレーターを通じてユーザーに返されます。完全なソースコードは GitHub リポジトリにあります。
前提条件:SageMaker AI、Amazon Bedrock、AgentCore のアクセス許可を持つ AWS アカウントが必要です。関連する Python パッケージをインストールし、sagemaker:InvokeEndpoint と sagemaker:CallWithBearerToken を含む IAM ロールを用意します。Claude Haiku 4.5 と Claude Sonnet 4.6 の Bedrock モデルアクセスを有効にし、Python 3.12 以上を使用します。
ステップ1:SageMaker AI に Qwen 3.5 9B をデプロイします。vLLM ディープラーニングコンテナイメージ vllm:0.22.1-gpu-py312-cu130 を ml.g6e.2xlarge で使用します。SM_VLLM_MODEL、SM_VLLM_TENSOR_PARALLEL_SIZE、SM_VLLM_MAX_MODEL_LEN などの環境変数を設定し、モデル、エンドポイント設定、エンドポイントを作成します。
ステップ2:マルチエージェントシステムを構築します。SageMaker AI の OpenAI 互換 API はベアラートークンを必要とし、トークンは期限切れになるため、長時間実行されるエージェントセッションでは、リクエストごとにトークンを更新するメカニズムが必要です。httpx.Auth サブクラスを使用して自動更新を実装できます。次に、Strands Agents の agents as tools パターンを使用し、呼び出しごとに新しいエージェントインスタンスを作成します。
ステップ3:Amazon Bedrock AgentCore ランタイムにデプロイします。bedrock-agentcore-starter-toolkit を使用して設定と起動を行い、SAGEMAKER_ENDPOINT_NAME、SAGEMAKER_REGION、AGENT_OBSERVABILITY_ENABLED などの環境変数を設定します。
可観測性の設定:AgentCore ランタイムは OpenTelemetry を使用してエージェントを自動的に計測しますが、その計測はすべてのモデルプロバイダーに均等に拡張されるわけではありません。Amazon Bedrock のモデル呼び出しにはトークン数を含む完全な生成 AI スパンが自動的に付与されますが、SageMaker の OpenAI 互換エンドポイント(Strands OpenAIModel 経由)は自動的にトークンテレメトリを取得しません。根本原因は、Strands の OTEL 統合がツール呼び出しとエージェントライフサイクルイベントのスパンを出力する一方で、OpenAIModel プロバイダーに対してトークン属性を含む gen_ai.chat スパンを出力しないことです。AgentCore の自動計測は、boto3 を介して行われた Amazon Bedrock モデル推論呼び出しのみを生成 AI 操作として認識します。
解決策は、SageMaker エージェント呼び出しをラップする gen_ai.chat スパンを手動で出力し、Strands の内部 AgentResult.metrics.accumulated_usage からトークン使用量を抽出することです。重要な詳細:Strands は内部で inputTokens、outputTokens、totalTokens というキーを使用し、モデルプロバイダーが使用量データを返した場合にのみこのディクショナリが入力されます。
なぜ stream_options が vLLM で必須なのか?デフォルトでは、vLLM はストリーミングレスポンスに usage チャンクを含めません。Strands はテキストチャンクを受信しますが、最終的な使用量オブジェクトは受信しないため、accumulated_usage はゼロのままです。stream_options: {"include_usage": True} を追加すると、vLLM はトークン数を含む追加の最終チャンクを送信します。このパラメータがないと、gen_ai.chat スパンは0トークンを報告します。
段階的な設定:Amazon CloudWatch Transaction Search を有効にし、strands-agents[otel] をインストールし、AGENT_OBSERVABILITY_ENABLED=true を設定し、コンテナCMDとして opentelemetry-instrument を使用し、OpenAIModel params に stream_options を追加し、カスタム gen_ai.chat スパンを作成します。サンプルのトレース出力には、入力トークン、出力トークン、合計トークン、所要時間が表示されます。
主な学び:Bedrock AgentCore は Bedrock 呼び出しを自動計測します。SageMaker OpenAI エンドポイントには手動スパンが必要です。トークン使用量には stream_options が必要です。result.metrics.accumulated_usage を使用します。AWS X-Ray のサンプリングレートは重要で、デフォルトの1%ではほとんどのトレースが失われるため、開発中は100%を使用します。リクエストごとに新しいエージェントインスタンスを使用して、同時実行エラーを回避します。
パターンの拡張:SM_VLLM_MODEL を S3 上のファインチューニング済みチェックポイントにポイントすることで、ファインチューニング済みモデルに交換できます。認証層、OTEL スパン、AgentCore デプロイは変更されません。また、推論コンポーネントを使用して A/B テストを実行することもできます。