10月8日、InfoQが「Multi-Agent Patterns from Spotify's AI Powered Advertising Platform」と題した講演動画を公開した。発表者はSpotify Adsのシニアエンジニア、Pratik Rasam氏。ローンチ以来、Spotify上の広告の70%以上がAIツールを活用しており、7,000社以上の広告主向けに約20,000件のクリエイティブが生成されている——冒頭の一文目から「これはリサーチトークではない」と断言するこの発表は、マルチエージェントの実運用に取り組むエンジニアにとって参照価値が高い。
「研究デモ」ではなく、本番稼働中のシステム
「Ads AI」とは何か。広告主が「米国のテクハブでエンジニアリングリーダーに広告を打ちたい」と自然言語で入力すると、LLMがその意図を解析し、ターゲティング条件(技術セグメント・DMAジオターゲティング等)や広告スクリプトを自動生成する仕組みだ。実際の広告キャンペーン、実際の予算、実際のオーディエンスを対象に動いているシステムの話である。
オーケストレーション層にはGoogle ADK(Agent Development Kit)のJava実装を採用し、以下の並列エージェントが協調動作する:
- Ad Script Generation Agent:広告スクリプトを生成
- Ad Guardrail Agent:ポリシー準拠を検証
- Audience Recommendation Agent(パイロット中):オーディエンスを推薦
※編集部の考察:Google ADKは公式にはPythonおよびJavaScript向けのサポートが前面に出ているが、Rasam氏の発表ではJava実装として紹介されている。SpotifyのバックエンドがJVM中心であることを踏まえると自然な選択といえるが、Java向けADKの利用はまだ事例が少なく、採用を検討する際はADKの公式ドキュメントで最新のサポート状況を確認されたい。
アーキテクチャの核心:「1エージェント・1パッケージ・1オーナー」
この発表で最も実装のヒントになる部分がここだ。Spotify社内では「One Agent, One Package, One Owner」という原則を明示的に強制している。
各エージェントはBazelパッケージとして独立しており、パッケージには以下が含まれる:
- Bazelパッケージ:依存関係と、どのエージェントからアクセス可能かの可視性制御
- lib-info:オーナーチームの定義。PRレビューも自動でそのチームに割り当てられる
- monitoring-info:ダッシュボードとPagerDutyアラートの設定(YAMLファイル)
- AgentFactory / Adapter / Service / AgentModule:DIスキャフォールディング
- LLM設定:エージェント指示のフロントマターとして保存
重要なのは、エージェント間の依存関係の制御がBazelの可視性制約によってコンパイル時に強制される点だ。Ad Script Generation AgentがAudience Resolverを使いたければ、Audience Resolver側がそのアクセスを明示的に許可する必要がある。許可されていなければビルドが落ちる。コードレビューやCIの運用ルールではなく、ビルドシステムの仕組みとして強制している。
以下のディレクトリ構造は、Rasam氏の発表内容をもとに編集部が再構成したものだ(発表スライドに示された構成要素に基づく):
agent_ad_script/
├── BUILD # Bazelパッケージ(可視性定義)
├── lib-info.yaml # オーナーチーム定義
├── monitoring-info.yaml # ダッシュボード・アラート設定
├── AgentFactory.java
├── AgentAdapter.java
└── agent_instructions.md # LLM設定をフロントマターで管理
チームレベルで見ると、複数のチームが各自のエージェントとツールを所有しつつ、共有のgRPCサービス・Google ADKランタイム・プラットフォーム層の上で動かす構成だ。オーケストレーションとガードレールは個別エージェント内ではなく、別レイヤーとして共通実装されている。これにより、各エージェントの実装を変えても、全体のポリシー整合性が崩れない。
「何をエージェントに任せ、何を任せないか」の原則
Rasam氏が「最も長い議論になる」と述べているのが、エージェントの境界設計だ。Spotifyが採用した整理は明快だ:
| 担当 | 内容 |
|---|---|
| エージェント(LLM) | 意図の解釈、判断、推論。例:広告主の言葉から「Gen Zをターゲットにしたい」の意味を理解する |
| ツール(API) | データ取得。ジオターゲティング、インタレストセグメントなどの実データはAPIから取得。LLMに推測させない |
| アプリケーションコード | 決定論的に書けることは決定論的に書く。LLMに任せない |
「決定論的に書けるものは必ず決定論的に書く」というのがこのアーキテクチャの基本思想だ。ツール設計についても「ツールのスキーマ定義はプロンプトエンジニアリングである」と述べており、ツールのdescriptionはLLMが読む仕様書でもある。
マルチエージェント採用の動機:なぜ今か
Rasam氏は「エージェントがクールだからではない」と断った上で、マルチエージェント採用の背景として以下を挙げている:
- モデルの成熟:18ヶ月前は構造化JSONの出力も不安定だったが、現在はスキーマ検証や業務ロジックのバリデーションが現実的になった
- フレームワークの整備:LangChain4j、Google ADK、CrewAIなどが並列実行やセッション管理のプリミティブを提供するようになった
- OTelのGenAI規約:OpenTelemetry GenAI semantic conventionsにより、GenAIワークフローの標準的なトレーシングが可能になった。以前はチームごとに独自のアノテーションを書いていた
- マルチエントリーポイントの需要:広告主がモバイルアプリで入力を始めてAds Manager APIで続けるような場合、コンテキストを統合できるのはマルチエージェント構成のみ
信頼性担保の面では、トレーシングを先に実装し、その本番トレースを使って評価(eval)するアプローチを取っている。合成テストではなく実際の本番トレースを再生してモデルを評価することで、ブラックボックスを避ける。
失敗から学んだこと
Rasam氏は発表の最後に「やり直すなら何を変えるか」というテーマも取り上げている。発表の文脈から読み取れる範囲では、以下の点が「初期の失敗から得た教訓」として位置付けられている:
- ガードレールの後付けは難しい:Ad Guardrail Agentをオーケストレーション層の共通コンポーネントとして分離した背景には、個別エージェント内でポリシー検証を実装しようとした際の複雑化があったとみられる
- 決定論的ゲーティングの重要性:LLMに任せすぎた部分で予期しない出力が生じ、「決定論的に書けるものは書く」という原則が後から強化された
- ツールのスキーマ設計を軽視していた:description の書き方がエージェントの動作精度に直結することは、運用を経て明らかになったという
なお、発表では失敗事例の詳細がさらに掘り下げられており、動画本編で確認することを勧める。
詳細はMulti-Agent Patterns from Spotify's AI Powered Advertising Platformを参照していただきたい。




