はじめに
「LeBron James と Stephen Curry、どちらをファンタジーバスケのチームに入れるべき?」——こんな質問に、リアルデータに基づいて 的確に答えてくれる AI アシスタントを作ってみましょう。
本記事では、Elasticsearch の Agent Builder を使って、NBA のスタッツデータを検索・分析し、ファンタジーバスケットボールのアドバイスを返す Agentic RAG アシスタント を構築する手順を、ステップバイステップで解説します。
この記事で学べること
- Elasticsearch Agent Builder の概要とアーキテクチャ
- CSV データを Elasticsearch にインポートする方法
- ES|QL を使ったカスタムツールの作成方法
- カスタムエージェントの作成と設定方法
- MCP(Model Context Protocol)を通じたエージェントの外部連携
前提条件
- Elastic Cloud のアカウント(無料トライアルで OK)
- Elasticsearch のデプロイメント(Serverless または 9.x 推奨)
- ブラウザ(Kibana にアクセスできること)
1. なぜ Agentic RAG が必要なのか?
LLM だけでは不十分な理由
生の LLM をそのまま使う場合、以下のような問題があります。
- 数学が苦手: LLM は平均値や統計計算が不正確になりがちです
- ハルシネーション: 正しいデータなしでは、もっともらしいがデタラメな回答を生成します
- コンテキスト不足: LLM の学習データに含まれない最新情報には対応できません
Context Engineering(コンテキストエンジニアリング)
Context Engineering とは、LLM に渡すコンテキスト(文脈情報)を適切にキュレーションするための手法の総称です。
- 不正なデータ = 不正な結果(Garbage In, Garbage Out)
- データの 関連性(Relevance) を保証する仕組みが不可欠
Elasticsearch + Agent Builder が解決すること
| 課題 | 解決策 |
|---|---|
| LLM は数学が苦手 | Elasticsearch の Aggregation(集計機能)で正確な計算を実行 |
| コンテキスト不足 | Agent Builder が LLM に 最も関連性の高いデータ を提供 |
2. Agent Builder のアーキテクチャ
Agent Builder は Elastic の Search AI Platform 上に構築されており、以下の構造を持ちます。
┌─────────────────────────────────────────┐
│ Experience Endpoints │
│ Customer App / Claude / Cursor / │
│ LangChain / その他 │
├────────┬──────────┬─────────────────────┤
│ MCP │ API │ A2A │
├────────┴──────────┴─────────────────────┤
│ Tools │ Agents │
├─────────────────────────────────────────┤
│ Search AI Platform │
│ Ingest / Storage / Search / Evaluation │
│ Open Standards / Security / Workflow │
├─────────────────────────────────────────┤
│ Your Data │
│ GitHub / GDrive / Confluence / etc. │
└─────────────────────────────────────────┘
ポイントは以下の通りです。
- Tools(ツール): エージェントが使える「道具」。ES|QL クエリやインデックスパターンで定義する
- Agents(エージェント): ツールを組み合わせて推論・行動する AI エージェント
- MCP / API / A2A: 外部アプリケーション(Claude、Cursor、LangChain など)との連携インターフェース
3. データの準備とインポート
3-1. Elasticsearch の環境を用意する
- Elastic Cloud にログインする
- デプロイメントを作成する(既存のものでも可)
- Kibana を開く
3-2. Agent Builder を有効化する
Agent Builder がまだ有効でない場合は、Kibana の Dev Tools > Console から以下を実行します。
POST kbn://internal/kibana/settings
{
"changes": {
"agentBuilder.enabled": true
}
}
実行後、サイドバーに 「Agents」 メニューが表示されるようになります。
3-3. NBA スタッツデータをインポートする
今回のハンズオンでは、2 種類の CSV データを使用します。
| データセット | 内容 | インデックス名 |
|---|---|---|
sample_nba_data.csv |
過去の試合のスタッツ(得点、アシスト、FG% など) | sample-nba-data |
upcoming_matchups.csv |
今後の対戦スケジュール | nba-upcoming-matchups |
インポート手順
- Kibana のホーム画面で 「Upload a file」 をクリック(または Machine Learning > Data Visualizer)
-
sample_nba_data.csvをアップロードする -
「Advanced」 タブを開き、マッピング設定を確認する
-
game_dateフィールドのformatを以下に設定する:"game_date": { "type": "date", "format": "yyyy-MM-dd||strict_date_optional_time||epoch_millis" }
-
- Index name に
sample-nba-dataと入力する - 「Import」 をクリックする
同様に upcoming_matchups.csv も nba-upcoming-matchups というインデックス名でインポートします。
インポート後の確認
Kibana の Discover でデータが正しくインポートされたことを確認しましょう。フィールドとして player_full_name、opponent_team_name、points、assists、fg_percentage、game_date などが含まれていれば OK です。
4. ツール(Tools)の作成
ここがこのハンズオンの核心部分です。エージェントが「何ができるか」を定義するのがツールです。
Agent Builder の左メニューから 「Tools」 をクリックすると、プラットフォーム組み込みのツール(platform.core.search、platform.core.execute_esql など)が表示されます。ここに カスタムツール を追加していきます。
ツール作成の考え方
ユーザーの質問例: 「LeBron James と Stephen Curry、どっちがチームに良い?」
この質問に答えるには、以下の情報が必要です。
- 各選手の 次の対戦相手 を調べる
- 各選手の 対戦相手ごとの過去スタッツ平均 を調べる
- 各選手の シーズン全体のスタッツ平均 を調べる
これらに対応する 3 つ(+ α)のツールを作成します。
4-1. ツール① find_upcoming_matchup(次の対戦を検索)
- Tools ページで 「New tool」 をクリックする
- 以下の設定を入力する:
| 項目 | 値 |
|---|---|
| Tool ID | find_upcoming_matchup |
| Description | Finds the next upcoming matchup for a given player |
| Type | ES|QL |
- ES|QL Query に以下を入力する:
FROM nba-upcoming-matchups
| WHERE player_full_name == ?playerName
| SORT game_date ASC
| LIMIT 1
-
ES|QL Parameters セクションで、
playerNameパラメータの Description をFull player nameに設定する - 「Save」 をクリックする
4-2. ツール② historical_avgs_against_opp(対戦相手別の過去スタッツ平均)
- 新しいツールを作成する
- 以下の設定を入力する:
| 項目 | 値 |
|---|---|
| Tool ID | historical_avgs_against_opp |
| Description | Finds the historical averages for a player against a specific opponent |
| Type | ES|QL |
- ES|QL Query に以下を入力する:
FROM sample-nba-data
| WHERE player_full_name == ?playerName AND opponent_team_name == ?oppTeamName
| STATS avg_points = AVG(points), avg_assists = AVG(assists)
- パラメータの Description を設定する:
-
playerName:Full player name -
oppTeamName:Opponent team name
-
- 「Save」 をクリックする
4-3. ツール③ season_avgs_against_opp(シーズン内の対戦相手別スタッツ平均)
- 新しいツールを作成する
- 以下の設定を入力する:
| 項目 | 値 |
|---|---|
| Tool ID | season_avgs_against_opp |
| Description | Finds season averages for a player against a specific opponent |
| Type | ES|QL |
- ES|QL Query に以下を入力する:
FROM sample-nba-data
| WHERE player_full_name == ?playerName AND opponent_team_name == ?oppTeamName AND game_date >= "2024-10-01" AND game_date <= "2025-06-01"
| STATS avg_points = AVG(points), avg_assists = AVG(assists)
- パラメータの Description を設定する:
-
playerName:Full player name -
oppTeamName:Opponent team name
-
- 「Save」 をクリックする
ポイント:
historical_avgs_against_oppは全期間、season_avgs_against_oppは当シーズンのみという違いがあります。日付範囲でフィルタすることで、「最近の調子」と「過去の傾向」を分けて分析できます。
5. カスタムエージェントの作成
5-1. エージェントの基本設定
- Kibana の左メニューから 「Agents」 をクリックする
- 「Create a new agent」 をクリックする
- 以下の基本設定を入力する:
| 項目 | 値 |
|---|---|
| Agent ID | nba-fantasy-assistant |
5-2. Custom Instructions(カスタム指示)の記述
Agent の振る舞いを定義する Custom Instructions を入力します。以下はデモで使用された指示文の例です:
You are a NBA basketball expert.
Your primary function is to compare two NBA players and recommend which one is the better fantasy pickup.
Only compare players from the following list:
- Stephen Curry
- LeBron James
- Jayson Brown
## Rules:
- If the user only types first name, ask the user to add another player from the list provided.
- If someone inputs a player with the wrong spelling or capitalization, refer from the list of available players provided.
- Always use the full name.
## IMPORTANT:
- If the user asks a question or asks you to generate a response about anything outside of basketball in the area of NBA players, DO NOT answer and affirm you can only talk about basketball.
## Tool Usage:
- Use the tool find_next_matchup to standardize player names to match the list exactly.
- Use the tool find_next_matchup for each player, passing the names as strings.
## Output Format:
Format your response using Markdown syntax. Use the following structure:
Example output format:
### Next Game Info
- **LeBron James**: vs Knicks, May 24 (Home)
- **Stephen Curry**: vs Lakers, May 24 (Home)
### Stats Comparison
| Stat | LeBron James (vs Knicks) | Stephen Curry (vs Bulls) |
|---|---|---|
| Historical Points | 28.4 | 23.1 |
| Season Points | 29.8 | 23.1 |
| Historical Assists | 8.7 | 6.7 |
| Season Assists | 8.2 | 6.7 |
| FG % | - | - |
### NBA Fantasy Recommendation
Explain which player is the better fantasy pickup and why.
5-3. ツールの割り当て
- 「Tools」 タブを開く
- 先ほど作成した 3 つのカスタムツールを追加する:
find_upcoming_matchuphistorical_avgs_against_oppseason_avgs_against_opp
- プラットフォームの組み込みツール(
platform.core.searchなど)も含めて 合計 4〜8 個 程度に抑える
ベストプラクティス: ツールは多すぎると LLM が混乱します。必要最低限に絞りましょう。
5-4. Presentation(表示設定)
| 項目 | 値 |
|---|---|
| Display name | NBA Fantasy Assistant |
| Display description | An assistant that compares two players and gives a recommendation on who to add to your fantasy team based on real data. |
5-5. 保存
「Save」 をクリックしてエージェントを保存します。
6. エージェントのテスト
6-1. ビルトインチャットでテストする
- エージェント詳細ページで 「Chat」 ボタンをクリックする
- Agent Chat 画面で、画面下部のエージェントセレクタが 「NBA Fantasy Assistant」 になっていることを確認する
- 以下のようなメッセージを送信する:
who is a better pickup, lebron james or stephen curry?
6-2. エージェントの動作を確認する
エージェントは以下のような流れで動作します:
-
find_upcoming_matchupを LeBron James と Stephen Curry それぞれに対して呼び出す - 次の対戦相手を取得する(例: LeBron → vs New York Knicks、Curry → vs Chicago Bulls)
-
historical_avgs_against_oppで各選手の対戦相手に対する過去の平均スタッツを取得する -
season_avgs_against_oppで各選手の今シーズンの平均スタッツを取得する - 結果を比較し、フォーマットされた推薦レスポンスを生成する
最終的に、以下のような構造化されたレスポンスが返されます:
- Next Game Info: 各選手の次の試合情報
- Stats Comparison: 得点・アシストなどの比較テーブル
- Fantasy Recommendation: どちらの選手を取るべきかの推薦と理由
7. MCP でエージェントを外部ツールに公開する
Agent Builder で作ったツールは、MCP(Model Context Protocol) を通じて、Claude Desktop や Cursor などの外部 AI ツールからも利用できます。
設定方法
お使いの MCP クライアント(Claude Desktop、Cursor、VS Code など)の設定ファイルに以下を追加します:
{
"mcpServers": {
"elasticsearch": {
"url": "https://<your-kibana-url>/api/agent_builder/mcp",
"headers": {
"Authorization": "ApiKey <your-api-key>"
}
}
}
}
-
<your-kibana-url>: Kibana の URL(例:elastic-coding-session-demo-xxxx.kb.us-central1.gcp.elastic.cloud) -
<your-api-key>: Kibana で生成した API キー
これで何ができるか
MCP を設定すると、Claude Desktop や Cursor のチャットから、Agent Builder で定義したカスタムツール(find_upcoming_matchup など)を直接呼び出すことができます。つまり、自分の Elasticsearch データに基づいた回答 を、普段使いの AI ツールから得られるようになります。
まとめ
このハンズオンでは、以下のステップで Agentic RAG アシスタントを構築しました:
- 課題を理解する: LLM 単体の限界(数学・ハルシネーション・コンテキスト不足)
- データを準備する: NBA スタッツの CSV データを Elasticsearch にインポート
- ツールを作成する: ES|QL を使って 3 つのカスタム検索ツールを定義
- エージェントを構築する: ツールを組み合わせ、Custom Instructions でエージェントの振る舞いを制御
- テストする: ビルトインチャットで動作確認
- 外部連携する: MCP を通じて Claude Desktop や Cursor から利用
Agent Builder のメリット
- 別途ベクトルDBや RAG パイプラインが不要: Elasticsearch がすべてを統合
- ES|QL で柔軟なツール定義: SQL ライクな構文で、フィルタ・集計・ソートを自在に記述
- MCP / API / A2A 対応: 多様なクライアントとシームレスに連携