-
Notifications
You must be signed in to change notification settings - Fork 254
Add Agent Builder A2A with Agent Framework example app #508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
carlyrichmond
merged 8 commits into
elastic:main
from
jsimonweb:add-agent-builder-a2a-example-app
Nov 20, 2025
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
4d6ca5b
add Agent Builder A2A with Agent Framework example app
jsimonweb 3c5e56c
pre-commit formatting
jsimonweb a120ed3
update cloud registration url
jsimonweb 08ae566
update to address pre-commit requirement
jsimonweb 5e2a42a
fix typos
jsimonweb 6c5aa71
fix typo
jsimonweb dae7827
address review comments
jsimonweb 49bbd91
update README
jsimonweb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
supporting-blog-content/agent-builder-a2a-agent-framework/Dockerfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| FROM python:3.11-slim | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| RUN python -m venv /opt/venv | ||
|
|
||
| ENV PATH="/opt/venv/bin:$PATH" | ||
|
|
||
| COPY requirements.txt . | ||
|
|
||
| RUN pip install -r requirements.txt | ||
|
|
||
| COPY elastic_agent_builder_a2a.py . | ||
|
|
||
| CMD ["python", "elastic_agent_builder_a2a.py"] |
133 changes: 133 additions & 0 deletions
133
supporting-blog-content/agent-builder-a2a-agent-framework/README.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| # Elastic Agent Builder A2A App | ||
|
|
||
| **Getting started with Agent Builder and A2A using Microsoft Agent Framework** | ||
|
|
||
| This is an example Python console app that demonstrates how to connect and utilize an [Elastic Agent Builder](https://www.elastic.co/elasticsearch/agent-builder) agent via the Agent2Agent (A2A) Protocol orchestrated with the [Microsoft Agent Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview). | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| 1. An Elasticsearch project/deployment running in [Elastic Cloud](https://cloud.elastic.co/registration?utm_source=github&utm_content=elasticsearch-labs-example-apps). | ||
| * Requires Elasticsearch serverless project (or for hosted deployments at least Elasticsearch version 9.2.0). | ||
| 2. A text editor or an integrated development environment (IDE) like [Visual Studio Code](https://code.visualstudio.com/download) running on your local computer. | ||
| 3. [Python version 3.10 or greater](https://www.python.org/downloads/) installed on your local computer. | ||
|
|
||
| ## Set up your Elasticsearch project | ||
|
|
||
| 1. Create an index named `my-docs` in your Elasticsearch project by running the following command in Elastic Developer Tools: | ||
|
|
||
| PUT /my-docs | ||
| { | ||
| "mappings": { | ||
| "properties": { | ||
| "title": { "type": "text" }, | ||
| "content": { | ||
| "type": "semantic_text" | ||
| }, | ||
| "filename": { "type": "keyword" }, | ||
| "last_modified": { "type": "date" } | ||
| } | ||
| } | ||
| } | ||
| 2. Insert a document into your index named `greetings.md` by running the following command in Elastic Developer Tools: | ||
|
|
||
| PUT /my-docs/_doc/greetings-md | ||
| { | ||
| "title": "Greetings", | ||
| "content": " | ||
| # Greetings | ||
| ## Basic Greeting | ||
| Hello! | ||
|
|
||
| ## Helloworld Greeting | ||
| Hello World! 🌎 | ||
|
|
||
| ## Not Greeting | ||
| I'm only a greeting agent. 🤷 | ||
|
|
||
| ", | ||
| "filename": "greetings.md", | ||
| "last_modified": "2025-11-04T12:00:00Z" | ||
| } | ||
|
|
||
| 3. In Elastic Agent Builder, create a **tool** with the following values: | ||
| * **Type**: `ES|QL` | ||
| * **Tool ID**: `example.get_greetings` | ||
| * **Description**: `Get greetings doc from Elasticsearch my-docs index.` | ||
| * **ES|QL**: | ||
|
|
||
| FROM my-docs | WHERE filename == "greetings.md" | ||
|
|
||
| 4. In Elastic Agent Builder, create an **agent** with the following values: | ||
| * **Agent ID**: `helloworld_agent` | ||
| * **Custom Instructions**: | ||
|
|
||
| If the prompt contains greeting text like "Hi" or "Hello" then respond with only the Basic Hello text from your documents. | ||
|
|
||
| If the prompt contains the text “Hello World” then respond with only the Hello World text from your documents. | ||
|
|
||
| In all other cases where the prompt does not contain greeting words, then respond with only the Not Greeting text from your documents. | ||
|
|
||
| * **Display Name**: `HelloWorld Agent` | ||
| * **Display Description**: `An agent that responds to greetings.` | ||
|
|
||
|
|
||
|
|
||
| ## Clone the example app | ||
|
|
||
| 1. Open a terminal and clone the Search Labs source code repository which contains the Elastic Agent Builder A2A App example. Run the following command to clone the example app: | ||
|
|
||
| git clone https://github.com/elastic/elasticsearch-labs | ||
|
|
||
| 3. `cd` to change directory to the example code located in the `supporting-blog-content/agent-builder-a2a-agent-framework` subdirectory. | ||
|
|
||
| cd elasticsearch-labs/supporting-blog-content/agent-builder-a2a-agent-framework | ||
|
|
||
| ## Set up the environment variables | ||
|
|
||
| 1. Set up the environment variables with values copied from your Elastic project. | ||
| 1. Make a copy of the file `env.example` and name the new file `.env ` | ||
| 2. Edit the `.env` file to set the values of the environment variables to use the values copied from your Elastic project. | ||
| * Replace <YOUR-ELASTIC-AGENT-BUILDER-URL\> | ||
| 1. In your Elastic project, go to the Elastic Agent Builder - Tools page. Click the **MCP Server** dropdown at the top of the Tools page. Select **Copy MCP Server URL.** | ||
| 2. Add the **MCP Server URL** value to the `.env` file. | ||
| * Find where the placeholder text “**<YOUR-ELASTIC-AGENT-BUILDER-URL\>**” appears and paste in the copied **MCP Server URL** to replace the placeholder text. Now edit the pasted **MCP Server URL**. Delete the text “mcp” at the end of the URL and replace it with the text “a2a”. The edited URL should look something like this | ||
|
|
||
| `https://example-project-a123.kb.westus2.azure.elastic.cloud/api/agent_builder/a2a` | ||
|
|
||
| * Replace <YOUR-ELASTIC-API-KEY\> | ||
| 1. In your Elastic project, click **Elasticsearch** in the navigation menu to go to your project’s home page. | ||
| 2. Click **Create API key** to create a new API key. | ||
| 3. After the API key is created, copy the API Key value. | ||
| 4. Add the API Key value to the `.env` file. | ||
| * Find where the placeholder text “**<YOUR-ELASTIC-API-KEY\>**” appears and paste in the copied API Key value to replace the placeholder text. | ||
|
|
||
| 3. Save the changes to the `.env` file. | ||
|
|
||
| ## Running the example app with Python | ||
|
|
||
| 1. Create a Python virtual environment by running the following code in the terminal. | ||
|
|
||
| python -m venv .venv | ||
|
|
||
| 2. Activate the Python virtual environment. | ||
| * If you’re running MacOS, the command to activate the virtual environment is: | ||
|
|
||
| source .venv/bin/activate | ||
|
|
||
| * If you’re on Windows, the command to activate the virtual environment is: | ||
|
|
||
| .venv\Scripts\activate | ||
|
|
||
| 3. Install the Microsoft Agent Framework along with its necessary Python packages by running the following `pip` command: | ||
|
|
||
| pip install -r requirements.txt | ||
|
|
||
| 4. Run the example app by entering the following command into the terminal: | ||
|
|
||
| python elastic_agent_builder_a2a.py | ||
|
|
||
| ## Running the example app with Docker | ||
|
|
||
| 1. Run the example app with Docker by entering the following command into the terminal: | ||
|
|
||
| docker compose run elastic-agent-builder-a2a |
9 changes: 9 additions & 0 deletions
9
supporting-blog-content/agent-builder-a2a-agent-framework/docker-compose.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| services: | ||
| elastic-agent-builder-a2a: | ||
| build: . | ||
| container_name: elastic-agent-builder-a2a | ||
| stdin_open: true | ||
| tty: true | ||
| environment: | ||
| - ES_AGENT_URL=${ES_AGENT_URL} | ||
| - ES_API_KEY=${ES_API_KEY} |
43 changes: 43 additions & 0 deletions
43
supporting-blog-content/agent-builder-a2a-agent-framework/elastic_agent_builder_a2a.py
carlyrichmond marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| import asyncio | ||
| from dotenv import load_dotenv | ||
| import httpx | ||
| import os | ||
| from a2a.client import A2ACardResolver | ||
| from agent_framework.a2a import A2AAgent | ||
|
|
||
|
|
||
| async def main(): | ||
| load_dotenv() | ||
| a2a_agent_host = os.getenv("ES_AGENT_URL") | ||
| a2a_agent_key = os.getenv("ES_API_KEY") | ||
|
|
||
| print(f"Connection to Elastic A2A agent at: {a2a_agent_host}") | ||
|
|
||
| custom_headers = {"Authorization": f"ApiKey {a2a_agent_key}"} | ||
|
|
||
| async with httpx.AsyncClient(timeout=60.0, headers=custom_headers) as http_client: | ||
| # Resolve the A2A Agent Card | ||
| resolver = A2ACardResolver(httpx_client=http_client, base_url=a2a_agent_host) | ||
| agent_card = await resolver.get_agent_card( | ||
| relative_card_path="/helloworld_agent.json" | ||
| ) | ||
| print(f"Found Agent: {agent_card.name} - {agent_card.description}") | ||
|
|
||
| # Use the Agent | ||
| agent = A2AAgent( | ||
| name=agent_card.name, | ||
| description=agent_card.description, | ||
| agent_card=agent_card, | ||
| url=a2a_agent_host, | ||
| http_client=http_client, | ||
| ) | ||
| prompt = input("Enter Greeting >>> ") | ||
| print("\nSending message to Elastic A2A agent...") | ||
| response = await agent.run(prompt) | ||
| print("\nAgent Response:") | ||
| for message in response.messages: | ||
| print(message.text) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(main()) |
2 changes: 2 additions & 0 deletions
2
supporting-blog-content/agent-builder-a2a-agent-framework/env.example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| ES_AGENT_URL=<YOUR-ELASTIC-AGENT-BUILDER-URL> | ||
| ES_API_KEY=<YOUR-ELASTIC-API-KEY> |
131 changes: 131 additions & 0 deletions
131
supporting-blog-content/agent-builder-a2a-agent-framework/requirements.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| a2a-sdk~=0.3.14 | ||
| ag-ui-protocol~=0.1.10 | ||
| agent-framework~=1.0.0b251114 | ||
| agent-framework-a2a~=1.0.0b251114 | ||
| agent-framework-ag-ui~=1.0.0b251117 | ||
| agent-framework-anthropic~=1.0.0b251114 | ||
| agent-framework-azure-ai~=1.0.0b251114 | ||
| agent-framework-azurefunctions~=1.0.0b251114 | ||
| agent-framework-chatkit~=1.0.0b251114 | ||
| agent-framework-copilotstudio~=1.0.0b251114 | ||
| agent-framework-core~=1.0.0b251114 | ||
| agent-framework-devui~=1.0.0b251114 | ||
| agent-framework-lab~=1.0.0b251024 | ||
| agent-framework-mem0~=1.0.0b251114 | ||
| agent-framework-purview~=1.0.0b251114 | ||
| agent-framework-redis~=1.0.0b251114 | ||
| aiohappyeyeballs~=2.6.1 | ||
| aiohttp~=3.13.2 | ||
| aiosignal~=1.4.0 | ||
| annotated-doc~=0.0.4 | ||
| annotated-types~=0.7.0 | ||
| anthropic~=0.74.0 | ||
| anyio~=4.11.0 | ||
| attrs~=25.4.0 | ||
| azure-ai-agents~=1.2.0b5 | ||
| azure-ai-projects~=2.0.0b2 | ||
| azure-core~=1.36.0 | ||
| azure-functions~=1.24.0 | ||
| azure-functions-durable~=1.4.0 | ||
| azure-identity~=1.25.1 | ||
| azure-storage-blob~=12.27.1 | ||
| backoff~=2.2.1 | ||
| cachetools~=6.2.2 | ||
| certifi~=2025.11.12 | ||
| cffi~=2.0.0 | ||
| charset-normalizer~=3.4.4 | ||
| click~=8.3.1 | ||
| colorama~=0.4.6 | ||
| cryptography~=46.0.3 | ||
| distro~=1.9.0 | ||
| docstring_parser~=0.17.0 | ||
| fastapi~=0.121.2 | ||
| frozenlist~=1.8.0 | ||
| furl~=2.1.4 | ||
| google-api-core~=2.28.1 | ||
| google-auth~=2.43.0 | ||
| googleapis-common-protos~=1.72.0 | ||
| griffe~=1.15.0 | ||
| grpcio~=1.76.0 | ||
| h11~=0.16.0 | ||
| h2~=4.3.0 | ||
| hpack~=4.1.0 | ||
| httpcore~=1.0.9 | ||
| httptools~=0.7.1 | ||
| httpx~=0.28.1 | ||
| httpx-sse~=0.4.3 | ||
| hyperframe~=6.1.0 | ||
| idna~=3.11 | ||
| importlib_metadata~=8.7.0 | ||
| isodate~=0.7.2 | ||
| jiter~=0.12.0 | ||
| jsonpath-ng~=1.7.0 | ||
| jsonschema~=4.25.1 | ||
| jsonschema-specifications~=2025.9.1 | ||
| MarkupSafe~=3.0.3 | ||
| mcp~=1.21.2 | ||
| mem0ai~=1.0.1 | ||
| microsoft-agents-activity~=0.6.0 | ||
| microsoft-agents-copilotstudio-client~=0.6.0 | ||
| microsoft-agents-hosting-core~=0.6.0 | ||
| ml_dtypes~=0.5.4 | ||
| msal~=1.34.0 | ||
| msal-extensions~=1.3.1 | ||
| multidict~=6.7.0 | ||
| numpy~=2.3.5 | ||
| openai~=2.8.1 | ||
| openai-agents~=0.6.0 | ||
| openai-chatkit~=1.3.0 | ||
| opentelemetry-api~=1.38.0 | ||
| opentelemetry-exporter-otlp-proto-common~=1.38.0 | ||
| opentelemetry-exporter-otlp-proto-grpc~=1.38.0 | ||
| opentelemetry-proto~=1.38.0 | ||
| opentelemetry-sdk~=1.38.0 | ||
| opentelemetry-semantic-conventions~=0.59b0 | ||
| opentelemetry-semantic-conventions-ai~=0.4.13 | ||
| orderedmultidict~=1.0.2 | ||
| packaging~=25.0 | ||
| ply~=3.11 | ||
| portalocker~=3.2.0 | ||
| posthog~=7.0.1 | ||
| propcache~=0.4.1 | ||
| proto-plus~=1.26.1 | ||
| protobuf~=5.29.5 | ||
| pyasn1~=0.6.1 | ||
| pyasn1_modules~=0.4.2 | ||
| pycparser~=2.23 | ||
| pydantic~=2.12.4 | ||
| pydantic-settings~=2.12.0 | ||
| pydantic_core~=2.41.5 | ||
| PyJWT~=2.10.1 | ||
| python-dateutil~=2.9.0.post0 | ||
| python-dotenv~=1.2.1 | ||
| python-multipart~=0.0.20 | ||
| python-ulid~=3.1.0 | ||
| pytz~=2025.2 | ||
| PyYAML~=6.0.3 | ||
| qdrant-client~=1.16.0 | ||
| redis~=6.4.0 | ||
| redisvl~=0.11.0 | ||
| referencing~=0.37.0 | ||
| requests~=2.32.5 | ||
| rpds-py~=0.29.0 | ||
| rsa~=4.9.1 | ||
| six~=1.17.0 | ||
| sniffio~=1.3.1 | ||
| SQLAlchemy~=2.0.44 | ||
| sse-starlette~=3.0.3 | ||
| starlette~=0.49.3 | ||
| tenacity~=9.1.2 | ||
| tqdm~=4.67.1 | ||
| types-requests~=2.32.4.20250913 | ||
| typing-inspection~=0.4.2 | ||
| typing_extensions~=4.15.0 | ||
| urllib3~=2.5.0 | ||
| uvicorn~=0.38.0 | ||
| uvloop~=0.22.1 | ||
| watchfiles~=1.1.1 | ||
| websockets~=15.0.1 | ||
| Werkzeug~=3.1.3 | ||
| yarl~=1.22.0 | ||
| zipp~=3.23.0 |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.