ブログ

Elastic Agent BuilderとStrands Agents SDKの使用を開始

Elastic Agent Builderでエージェントを作成する方法を学び、次にStrands Agents SDKで管理されたA2Aプロトコルを介してエージェントを使用する方法を学びましょう。

AIエージェントのアイデアをお持ちですか?おそらく、データを使って何かを行うことが関係しているでしょう。エージェントが有用なアクションを開始するには、決定を下す必要があり、正しい決定を下すには正しいデータが必要だからです。

Elastic Agent Builderは、データ接続型AIエージェントを簡単に構築できるようにします。このブログ記事でその方法を説明します。まず、Elasticに格納されているデータにアクセスするMCPツールを使ってエージェントを作成するのに必要なすべてのステップを見ていきましょう。次に、Strands Agents SDKとそのAgent2Agent(A2A)機能を使用してエージェントを操作します。Strands Agents SDKは、望む結果を得るために十分なコードでエージェント向けアプリを構築するマルチエージェントAI開発プラットフォームです。

AIエージェントを構築しましょう。このエージェントは、RPS+というゲームをプレイします。これは古典的な「じゃんけん」に追加のひねりを加えたもので、プレイヤーにいくつかの追加の選択肢を与えます。

要件

こちらのブログ記事の手順に従うために必要なものは次のとおりです。

  • ローカルコンピューターで実行されているテキストエディター

  • ローカルコンピューターで実行されているPython 3.10以上

Serverlessプロジェクトを作成する

最初に必要なのは、Elastic Agentビルダーを含むElasticsearch Serverlessプロジェクトです。

cloud.elastic.coに移動して新しいElasticsearch Serverlessプロジェクトを作成します。

インデックスを作成してデータを追加する

次に、Elasticsearchプロジェクトにデータを追加します。開発者ツールを開き、コマンドを実行して新しいインデックスを作成し、そこにデータを挿入します。トップレベルのナビゲーションメニューから「開発者向けツール」を選択します。

コピーして、以下のPUTコマンドを開発者向けツールコンソールのリクエストインプットエリアに貼り付けてください。この文は「game-docs」という名前のElasticsearchインデックスを作成します。

PUT /game-docs
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "content": { 
        "type": "text"
      },
      "filename": { "type": "keyword" },
      "last_modified": { "type": "date" }
    }
  }
}

開発者ツールのステートメントの右側に表示される [リクエストの送信] ボタンをクリックします。開発者向けツールの対応エリアにgame-docsインデックスが作成されたことを確認する通知が表示されるはずです。

game-docsという名前のインデックスは、作成中のゲームのデータを保存するのに最適な場所です。ゲームに必要なすべてのデータを含むこのインデックスに、rps+-mdという名前のドキュメントを配置しましょう。次のPUTコマンドをコピーして、開発者向けツールコンソールに貼り付けます。

PUT /game-docs/_doc/rps+-md
{
  "title": "Rock Paper Scissors +",
  "content": "
# Game Name
RPS+

# Starting Prompt
Let's play RPS+ !
---
What do you choose?

# Game Objects
1. Rock 🪨 👊
2. Paper 📜 🖐
3. Scissors ✄ ✌️
4. Light ☼ 👍
5. Dark Energy ☄ 🫱

# Judgement of Victory
* Rock beats Scissors
  * because rocks break scissors
* Paper beats Rock
  * because paper covers rock
* Scissors beat Paper
  * because scissors cut paper
* Rock beats Light
  * because you can build a rock structure to block out light
* Paper beats Light
  * because knowledge stored in files and paper books helps us understand light
* Light beats Dark Energy
  * because light enables humans to lighten up and laugh in the face of dark energy as it causes the eventual heat death of the universe
* Light beats Scissors
  * because light is needed to use scissors safely
* Dark Energy beats Rock
  * because dark energy rocks more than rocks. It rocks rocks and everything else in its expansion of the universe
* Dark Energy beats Paper
  * because humans, with their knowledge stored in files and paper books, can't explain dark energy 
* Scissors beat Dark Energy
  * because a human running with scissors is darker than dark energy

# Invalid Input
I was hoping for an worthy opponent
  - but alas it appears that time has past
  - but alas there's little time for your todo list when [todo:fix this] is so vast

# Cancel Game
The future belongs to the bold. Goodbye..
",
  "filename": "RPS+.md",
  "last_modified": "2025-11-25T12:00:00Z"
}

ステートメントの横にある [リクエストの送信] ボタンをクリックして実行し、rps+-mdドキュメントをgame-docsのインデックスに追加してください。

クエリを実行するためのデータが用意されているはずです。Agent Builderを使用すると、クエリはこれまで以上に簡単になります。

トップレベルのナビゲーションメニューから [エージェント] を選択します。

あとは、デフォルトのElastic AI Agentに「どんなデータがありますか?」と聞くだけです。

Elastic AI Agentはデータを評価し、保有するデータの簡潔な説明を返します。

ツールを作成する

さて、Elasticにデータがいくつか入ったので、それを活用してみましょう。Agent Builderには、エージェントが必要なデータにアクセスし、タスクに適したコンテキストを得られるようにMCPツールを作成するための組み込みサポートが含まれています。ゲームデータを取得できるシンプルなツールを作りましょう。

Agent Builderのアクションメニューをクリックします。

メニューオプションから [すべてのツールを表示] を選択します。

[+ 新しいツール] をクリックします。

ツール作成フォームでES|QLを選択します。ツールタイプとして次の値を入力します。

ツールIDについて:

example.get_game_docs

説明について:

Get RPS+ doc from Elasticsearch game-docs index.

構成については、以下のクエリをES|QLクエリテキスト領域にします。

FROM game-docs | WHERE filename == "RPS+.md"

完了したツール作成フォームは次のようになります。ツールを作成するには、 [保存] をクリックします。

ツールラックに新しいツールが追加されました。ツールはラックに掛けておけばよいというものではなく、有効に活用されるべきものです。新しいカスタムツールを使用できるエージェントを作成しましょう。

エージェントを作成し、ツールを割り当てます。

Agent Builderを使えば、エージェントの作成は驚くほど簡単です。いくつかの詳細を記載したエージェントの指示を入力するだけで十分です。それではエージェントを作成しましょう。

[エージェントを管理] をクリックします。

[+ 新しいエージェント] をクリックします。

新しいエージェントフォームに次の情報を入力します。

エージェントIDには以下のテキストを入力します。

rps_plus_agent

カスタム指示テキスト領域には次の指示を入力します。

When prompted, if the prompt contains an integer, then select the corresponding numbered item in the list of "Game Objects" from your documents. Otherwise select a random game object. This is your chosen game object for a single round of the game.

# General Game Rules
* 2 players
    - the user: the person playing the game
    - you: the agent playing the game and serving as the game master
* Each player chooses a game object which will be compared and cause them to tie, win or lose.

# Start the game
1. This is the way each new game always starts. You make the first line of your response only the name of your chosen game object. 

2. The remainder of your response should be the "Starting Prompt" text from your documents and generate a list of "Game Objects" for the person playing the game to choose a game object from.  

# End of Game: The game ends in one of the following three outcomes:
1. Invalid Input: If the player responds with an invalid game object choice, respond with variations of the "Invalid Input" text from your documents and then end the game.

2. Tie: The game ends in a tie if the user chooses the same game object as your game object choice.

3. Win or Lose: The game winner is decided based on the "Judgement of Victory" conditions from your documents. Compare the user's game object choice and your game object choice and determine who chose the winning game object.

# Game conclusion
Respond with a declaration of the winner of the game by outputting the corresponding text in the "Judgement of Victory" section of your documents.

表示名には以下のテキストを入力します。

RPS+ Agent

表示の説明には以下のテキストを入力します。

An agent that plays the game RPS+

[ツール] タブをクリックして、以前に作成したカスタムツールをエージェントに提供します。

先ほど作成したexample.get_game_docsツールのみを選択します。

[保存] をクリックして新しいエージェントを作成します。

新しいエージェントをテストしてみましょう。エージェントのリストから任意のエージェントとチャットを開始するための便利なリンクがあります。

「start game」と入力すると、ゲームが始まります。うまくいきました!

エージェントが応答の上部にゲームオブジェクトの選択を表示することがわかります。これは、エージェントの選択を確認し、ゲームが期待どおりに機能していることを確認できる点で便利です。しかし、自分が選択する前に相手の選択がわかっていると、じゃんけんゲームはあまり楽しくありません。ゲームを最終形に磨き上げるために、コードでエージェントを制御できるエージェントオーケストレーションプラットフォームを使用できます。

Strands Agents SDKがチャットに参加します。

Strands Agents SDK

新しいエージェント開発フレームワークを試してみたい場合は、Strands Agents SDKがおすすめです。Strands Agents SDKはAWSから2025年5月にオープンソースのPython実装としてリリースされ、現在はTypescript版もあります。

PythonでStrands Agents SDKの使用を開始

コーディングエンジンを起動して、Strandsエージェントを使用してA2Aプロトコル経由でRPS+エージェントを制御するサンプルアプリのクローン作成と実行のプロセスを早速実行してみましょう。RPS+ゲームの微調整バージョンを作成し、エージェントの選択がプレイヤーの選択後に明らかになるようにしてみましょう。結局のところ、じゃんけんのようなゲームを楽しいものにするのは推測と驚きの結果だからです。

ローカルコンピューターでVisual Studio Codeを開き、新しいターミナルを開きます。

新しく開いたターミナルで、以下のコマンドを実行してElasticsearch Labsリポジトリをクローンします。

git clone https://github.com/elastic/elasticsearch-labs

次のcdコマンドを実行して、ディレクトリをelasticsearch-labsディレクトリに変更します。

cd elasticsearch-labs

次に、次のコマンドを実行して、Visual Studio Codeでリポジトリを開きます。

code .

Visual Studio File Explorerで、supporting-blog-contentフォルダーとagent-builder-a2a-strands-agentsフォルダーを展開し、elastic_agent_builder_a2a_rps+.pyファイルを開きます。Visual Studio Codeで開いたファイルは次のようになります。

テキストエディターに表示されるelastic_agent_builder_a2a_rps+.pyの内容は次のとおりです。

import asyncio
from dotenv import load_dotenv
from uuid import uuid4
import httpx
import os
import random
from a2a.client import A2ACardResolver, ClientConfig, ClientFactory
from a2a.types import Message, Part, Role, TextPart

DEFAULT_TIMEOUT = 60  # set request timeout to 1 minute


def create_message(*, role: Role = Role.user, text: str, context_id=None) -> Message:
    return Message(
        kind="message",
        role="user",
        parts=[Part(TextPart(kind="text", text=text))],
        message_id=uuid4().hex,
        context_id=context_id,
    )


async def main():
    load_dotenv()
    a2a_agent_host = os.getenv("ES_AGENT_URL")
    a2a_agent_key = os.getenv("ES_API_KEY")
    custom_headers = {"Authorization": f"ApiKey {a2a_agent_key}"}

    async with httpx.AsyncClient(
        timeout=DEFAULT_TIMEOUT, headers=custom_headers
    ) as httpx_client:
        # Get agent card
        resolver = A2ACardResolver(httpx_client=httpx_client, base_url=a2a_agent_host)
        agent_card = await resolver.get_agent_card(
            relative_card_path="/rps_plus_agent.json"
        )
        # Create client using factory
        config = ClientConfig(
            httpx_client=httpx_client,
            streaming=True,
        )
        factory = ClientFactory(config)
        client = factory.create(agent_card)
        # Use the client to communicate with the agent
        print("\nSending 'start game' message to Elastic A2A agent...")
        random_game_object = random.randint(1, 5)
        msg = create_message(text=f"start with game object {random_game_object}")
        async for event in client.send_message(msg):
            if isinstance(event, Message):
                context_id = event.context_id
                response_complete = event.parts[0].root.text
                # Get agent choice from the first line of the response
                parsed_response = response_complete.split("\n", 1)
                agent_choice = parsed_response[0]
                print(parsed_response[1])
        # User choice sent for game results from the agent
        prompt = input("Your Choice  : ")
        msg = create_message(text=prompt, context_id=context_id)
        async for event in client.send_message(msg):
            if isinstance(event, Message):
                print(f"Agent Choice : {agent_choice}")
                print(event.parts[0].root.text)


if __name__ == "__main__":
    asyncio.run(main())

このコードで何が起きているのか見てみましょう。main()メソッドから始めて、コードはエージェントのURLとAPIキーの環境変数にアクセスすることから始まります。その値を用いてエージェントカードを取得するためのhttpx clientを作成します。次に、クライアントはエージェントカードの詳細を使用して、「start game」リクエストをエージェントに送信します。ここで注目すべき興味深い点は、 "start game"リクエストの一部としてrandom_game_object値が含まれていることです。この値は、Python の標準ライブラリのrandomモジュールで生成された乱数です。これを行う理由は、(AIエージェントを可能にする)強力なLLMがランダム性に関してはそれほど優れていないことが判明したためです。Pythonが助けてくれますので問題ありません。

コードの続きですが、エージェントが「start game」リクエストに応答すると、コードはエージェントのゲームオブジェクトセレクションを取り除き、agent_choice変数に保存します。対応の残りの部分は、エンドユーザーに対してテキストとして表示されます。次に、ユーザーはゲームオブジェクトの選択を入力するように求められ、それがエージェントに送信されます。次に、コードはエージェントのゲームオブジェクトの選択と、エージェントの最終的なゲーム結果の決定を表示します。

エージェントのURLとAPIキーを環境変数として設定する

サンプルアプリはローカルコンピュータ上で実行されるため、Agent Builderエージェントと通信するためには、Strands Agents SDKにエージェントのA2A URLとAPI Keyを提供する必要があります。この例のアプリは`.env`というファイルを使用してこれらの値を格納します。

env.exampleファイルのコピーを作成し、新しいファイル名を.envとします。

Elastic Agent Builderに戻りましょう。ここで必要な両方の値を取得できます。

ページの右上にあるAgent Builderアクションメニューから [すべてのツールを表示] を選択します。

ツールページ上部のMCPサーバードロップダウンをクリックし、[MCPサーバーURLをコピー] を選択してください。

MCPサーバーのURL.envに貼り付けます。<YOUR-ELASTIC-AGENT-BUILDER-URL>プレースホルダー値の代わりにファイルを使用します。ここで、URLを1箇所更新する必要があります。つまり、末尾のテキスト「mcp」を「a2a」に置き換えます。これは、Agent Strands SDKがElastic Agent Builderで実行されているエージェントと通信するために使用するプロトコルがA2Aプロトコルであるためです。

編集したURLは次のようになるはずです。

https://rps-game-project-12345a.kb.us-east-1.aws.elastic.cloud/api/agent_builder/a2a

Elastic Cloudで取得する必要があるもう1つの値は、APIキーです。最上位ナビゲーションでElasticsearchをクリックします。

[APIキーをコピー] ボタンをクリックして、APIキーをコピーします。

次に、Visual Studio Codeに戻り、.envファイルにAPIキーを貼り付けて、<YOUR-ELASTIC-API-KEY>プレースホルダーテキストを置き換えます。.envファイルは次のようになります。

サンプルアプリを実行してください

Visual Studio Codeで新しいターミナルを開いてください。

まず、ターミナルで次のcdコマンドを実行します。

cd elasticsearch-labs/supporting-blog-content/agent-builder-a2a-strands-agents

次のコマンドを実行して、Python仮想環境を作成します。

python -m venv .venv

お使いのローカルコンピューターのオペレーティングシステムに応じて、以下のコマンドを実行して仮想環境を有効にしてください。

  • MacOS/Linux

source .venv/bin/activate
  • Windows

.venv\Scripts\activate

サンプルアプリはStrands Agents SDKを使用するため、このチュートリアルではこれをインストールする必要があります。以下のコマンドを実行して、Strands Agents SDKとその必要なPythonライブラリの依存関係をインストールします。

pip install -r requirements.txt

発射台を片付けてカウントダウンを開始する時間です。アプリを起動する準備ができました。後ろに下がってください。次のコマンドを使用して実行しましょう:

python elastic_agent_builder_a2a_rps+.py

RPS+のゲームに挑戦してみましょう。幸運を祈ります!

関連コンテキストでAIアプリを構築

AIエージェントの構築のスキルを習得できました。また、Strands Agents SDKのようなエージェント開発フレームワークで、A2Aを介してElastic Agent Builderエージェントを使用することがいかに簡単であるかをお分かりいただけたと思います。カスタムデータの関連コンテキストに接続されたAIエージェントの構築にはElasticをお試しください。

関連記事

高度なRAGテクニックパート2:クエリとテスト

Han Xiang Choong

Elasticsearchによるエンティティ解決、パート4:究極のチャレンジ

Jessica Moszkowicz

Elastic Agent Builder と GPT-OSS を使用した HR 向け AI エージェントの構築

Tomás Murúa

高度なRAGテクニックパート1:データ処理

Han Xiang Choong

LangGraph.jsとElasticsearchを使用して金融AI検索ワークフローを構築

Jeffrey Rengifo

最先端の検索体験を構築する準備はできましたか?

十分に高度な検索は 1 人の努力だけでは実現できません。Elasticsearch は、データ サイエンティスト、ML オペレーター、エンジニアなど、あなたと同じように検索に情熱を傾ける多くの人々によって支えられています。ぜひつながり、協力して、希望する結果が得られる魔法の検索エクスペリエンスを構築しましょう。

はじめましょう