8月14日、AWSが「Orchestrating multi-agent AI architectures with Amazon S3 Files」と題した記事を公開した。マルチエージェントAIの設計で長らく悩みの種だった「エージェント間のデータ受け渡し」を、プロンプトへの詰め込みもエージェント間のAPI連携も使わずに解決できるアーキテクチャとして注目に値する。共有ファイルシステムという古典的な手段をS3スケールで実現した点が、この手法の核心だ。
なぜS3をファイルシステムとして使うのか
マルチエージェントAIで問題になるのが「エージェント間のデータ受け渡し」だ。すべてをプロンプトに詰め込むアプローチはコストが上がり、モデルのコンテキストウィンドウの制限にもすぐ当たる。かといってエージェント間をAPIで繋ぐと、s3.list_objects_v2()やs3.put_object()のような呼び出しと、ページネーション・リトライ処理がステージ数に比例して膨らんでいく。
タイトルが示す「プロンプト詰め込み不要・API連携不要」とは、まさにこの2つの課題を同時に回避することを意味する。各エージェントは共有ファイルシステム上の決まったディレクトリを読み書きするだけでよく、上流エージェントとの直接通信もプロンプトへのデータ埋め込みも必要ない。
Amazon S3 Files はこの問題への回答だ。S3上のデータをPOSIXセマンティクスで扱える共有ファイルシステムを提供し、open()、os.listdir()、write()といった標準ファイル操作でエージェントがデータをやり取りできる。EC2、Lambda、EKS、ECS on Fargate、Amazon Bedrock AgentCore Runtimeといった異なるコンピューティングサービスから同一のファイルシステムをマウントできる点が特徴だ。
5段階パイプラインの全体像
記事で紹介されている実装は、金融サービス企業の書類処理を想定した5段階のドキュメント処理パイプラインだ。意図的に各ステージを別のAWSコンピューティングサービスに乗せることで、S3 Filesのマウント対応範囲を示している。
| ステージ | 担当エージェント | コンピューティング | 入力ディレクトリ | 出力ディレクトリ |
|---|---|---|---|---|
| 1 | 取り込み(Intake) | EC2 | customer-forms/ | intake/ |
| 2 | リスク分析 | Lambda | intake/ | analyzed/ |
| 3 | コンプライアンス検証 | EKS | analyzed/ | validated/ |
| 4 | レポート組み立て | ECS on Fargate | validated/ | reports/ |
| 5 | エグゼクティブ要約 | AgentCore Runtime | reports/ | summaries/ |
パイプラインのトリガーはイベント駆動だ。S3にフォームがアップロードされると、S3イベント通知がSQSキューにメッセージを送り、EC2上の取り込みエージェントがそれを受信する。以降のステージはファイルシステム上のディレクトリをポーリングするか、EventBridge Schedulerで1分ごとに起動する。
全エージェントは**Strands Agents SDK** とAmazon Bedrockを推論に使用し、コードパターンはほぼ共通だ。違うのはシステムプロンプトと読み書きするディレクトリだけである。
import json
from strands import Agent
from strands.models.bedrock import BedrockModel
model = BedrockModel(model_id="<MODEL_ID>", region_name="<REGION>")
agent = Agent(model=model, system_prompt=SYSTEM_PROMPT)
# 共有ファイルシステムから読み込み
with open('/mnt/s3files/intake/doc-abc.json') as f:
doc = json.load(f)
# AIエージェントが処理
result = agent(f"Analyze this document for risks: {json.dumps(doc['content'])}")
# 共有ファイルシステムに書き込み
envelope = {
'id': doc['id'],
'stage': 'analyzed',
'content': json.loads(result.message['content'][0]['text'])
}
with open('/mnt/s3files/analyzed/analysis-abc.json', 'w') as f:
json.dump(envelope, f, indent=2)
実装上の要点
マウント方法はサービスによって異なる
- EC2・EKS:ファイルシステムを直接マウント(rootとして実行)
- Lambda・ECS on Fargate・AgentCore Runtime:S3 Filesアクセスポイント経由でマウント(UID 1000 / GID 1000)
EC2でのマウントコマンド例:
sudo yum install -y amazon-efs-utils
sudo mkdir -p /mnt/s3files
sudo mount -t s3files fs-0123456789abcdef0:/ /mnt/s3files
注釈:ここで使用している
amazon-efs-utilsパッケージおよびmount -t s3filesオプションは、Amazon EFS向けに開発されたマウントユーティリティをAmazon S3 Files向けに流用したものだ。Amazon S3 FilesはEFSとは独立した別サービスだが、マウントの仕組みとして同ユーティリティが対応している。EFSとS3 Filesの違いについては公式ドキュメントを参照されたい。
Lambdaはマウントコマンドを実行できないため、関数のFileSystemConfigsにアクセスポイントのARNを指定する。ハンドラ実行前に自動でマウントが完了する。なお、Strands SDKのコールドスタートとBedrockの推論呼び出しを考慮し、Lambdaには2048MBメモリ・10分タイムアウトが推奨されている。
重複処理の防止
各エージェントは固定間隔でディレクトリをポーリングするため、同じファイルを二重処理しない仕組みが必要だ。記事では2つのアプローチを紹介している。
- EKSエージェント(並列レプリカ構成):アトミックなクレームマーカーファイルを使い、どのレプリカが処理するかを調整
- ECSエージェント(シングルタスク):マウント上に重複排除ステートを保持
- その他(EC2・Lambda・AgentCore):期待される出力ファイルがすでに存在すればスキップ
整合性モデルに注意
S3 Filesはクローズ・トゥ・オープン整合性を提供する。あるエージェントがファイルをクローズした直後、他のエージェントはマウント経由でそのファイルを参照できる。ただし、S3バケット上のオブジェクトとして見えるようになるまでには約1分かかる(マウントからのエクスポートのため)。ダウンストリームエージェントはS3バケットではなくマウントを直接ポーリングするため、この遅延は問題にならない。
可用性とスケーリング
アベイラビリティゾーン(AZ)ごとに1つずつ、計2つのマウントターゲットを設けることで高可用性を確保する。ファイルシステムは自動でスケールし、容量計画は不要だ。
前提条件まとめ
- AWSアカウント(バージョニング有効なS3バケット)
- 少なくとも2AZのサブネットを持つVPC
- 適切なIAMロール(
bedrock:InvokeModel、bedrock:InvokeModelWithResponseStreamを含む) - Python 3.10以降 +
strands-agents(pip install strands-agents) - NFS・POSIXファイルパーミッションの基本的な理解
このうち実務で特にハードルになりやすいのがIAMロールの設計とVPCのサブネット構成だ。各コンピューティングサービス(EC2・Lambda・EKS・ECS・AgentCore)はそれぞれ別のIAMロールを持ち、S3 FilesアクセスポイントへのNFSマウント権限とBedrockの推論権限を個別に付与する必要がある。また、Lambda・ECS・AgentCoreはVPC内に配置する必要があるため、既存のVPC設計によっては追加のサブネットやセキュリティグループの整備が求められる。NFS・POSIXの知識はEC2やEKSへの直接マウント時にパーミッション設定のデバッグで必要になる場面が多い。
詳細はOrchestrating multi-agent AI architectures with Amazon S3 Filesを参照していただきたい。