Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ Please be sure to include as much information as possible:

Following these steps will guarantee the quickest resolution possible.

Thanks!
Thanks!
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ A clear and concise description of what you want to happen.
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.
Add any other context or screenshots about the feature request here.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/support_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ If your bug or feature request is not related to this particular library, please

Check for answers on StackOverflow with the [google-maps](http://stackoverflow.com/questions/tagged/google-maps) tag.

---
---
11 changes: 10 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@ updates:
directory: "/client/web/react"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
cooldown:
default-days: 7
- package-ecosystem: "pip"
directory: "/agent/python"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
cooldown:
default-days: 7
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
interval: "weekly"
open-pull-requests-limit: 0
cooldown:
default-days: 7
2 changes: 0 additions & 2 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,3 @@ jobs:

- name: Run zizmor
uses: zizmorcore/zizmor-action@195d10ad90f31d8cd6ea1efd6ecc12969ddbe73f # v0.5.1
with:
args: --ignore insufficient-cooldown
116 changes: 77 additions & 39 deletions agent/python/README.md
Original file line number Diff line number Diff line change
@@ -1,107 +1,142 @@
# Agentic UI Toolkit - Python Agent

This is a sample Python agent that consumes the MAUI packages and provides a backend for the A2UI chat interface.
This is a sample Python agent that consumes the MAUI packages and provides a
backend for the A2UI chat interface.

## Prerequisites

**Source code:**
* Download/clone the Agentic UI Toolkit source code from [GitHub](https://github.com/googlemaps/a2ui)

**Environment variables:**
This example requires the following environment variables to be set:
* Download/clone the Agentic UI Toolkit source code from
[GitHub](https://github.com/googlemaps/a2ui)

**Environment variables:** This example requires the following environment
variables to be set:

* `GEMINI_API_KEY`: Your Gemini API key.
* `GOOGLE_MAPS_API_KEY`: Your Google Maps API key (used by the agent for location-based queries).
* `GOOGLE_MAPS_API_KEY`: Your Google Maps API key (used by the agent for
location-based queries).

**Tools:**
* `uv`: Python package manager and runner. Install from https://docs.astral.sh/uv/

* `uv`: Python package manager and runner. Install from
https://docs.astral.sh/uv/

## To run this sample project

1. Open this directory in a terminal.
2. Set the path to the MAUI package in [pyproject.toml](pyproject.toml).

You can either do this manually by replacing the `$MAUI_PATH` placeholder in [pyproject.toml](pyproject.toml)
with the path to the MAUI package, or by running the [setup.sh](setup.sh) script:

You can either do this manually by replacing the `$MAUI_PATH` placeholder in
[pyproject.toml](pyproject.toml) with the path to the MAUI package, or by
running the [setup.sh](setup.sh) script:

```bash
chmod +x setup.sh
./setup.sh <path_to_maui_package>
```

3. Run the following command to start the server:

```bash
uv run .
```

This will automatically resolve dependencies, install them in a local virtual environment, and start the A2A server on port 10002.
This will automatically resolve dependencies, install them in a local
virtual environment, and start the A2A server on port 10002.

To run the frontend, follow the instructions in [../../client/web/react/README.md](../../client/web/react/README.md)
To run the frontend, follow the instructions in
[../../client/web/react/README.md](../../client/web/react/README.md)

## Google API Keys

### Google Maps API Key

Agentic UI Toolkit requires an API Key to use Google Maps Platform products. To create a Google Maps API Key, follow the instructions in the [Google Maps Platform documentation](https://developers.google.com/maps/documentation/javascript/get-api-key).
Agentic UI Toolkit requires an API Key to use Google Maps Platform products. To
create a Google Maps API Key, follow the instructions in the
[Google Maps Platform documentation](https://developers.google.com/maps/documentation/javascript/get-api-key).

Your API Key must have the following APIs enabled in the [Google Cloud Console](https://console.cloud.google.com/apis/credentials):
Your API Key must have the following APIs enabled in the
[Google Cloud Console](https://console.cloud.google.com/apis/credentials):

* Geocoding API
* Maps JavaScript API
* Places UI Kit
* Routes API
* Geocoding API
* Maps JavaScript API
* Places UI Kit
* Routes API

To use Grounding Lite MCP, you must also enable:

* Maps Grounding Lite API
* Maps Grounding Lite API

To support the use of Grounding Lite within the Python ADK backend, this API Key must be exported or contained within a `.env` file as `GOOGLE_MAPS_API_KEY`.
To support the use of Grounding Lite within the Python ADK backend, this API Key
must be exported or contained within a `.env` file as `GOOGLE_MAPS_API_KEY`.

**Loading the Google Maps JavaScript API**

Your API Key must also be included when loading the Google Maps JavaScript API code. See the [Google Maps Platform Documentation](https://developers.google.com/maps/documentation/javascript/load-maps-js-api) for instructions on how to load the API, including configuring the API Key.
Your API Key must also be included when loading the Google Maps JavaScript API
code. See the
[Google Maps Platform Documentation](https://developers.google.com/maps/documentation/javascript/load-maps-js-api)
for instructions on how to load the API, including configuring the API Key.

Agentic UI Toolkit requires features available in the Alpha channel. You must use `v=alpha` when loading the Maps JavaScript API. Learn more about versions in the [Google Maps Platform Documentation](https://developers.google.com/maps/documentation/javascript/versions).
Agentic UI Toolkit requires features available in the Alpha channel. You must
use `v=alpha` when loading the Maps JavaScript API. Learn more about versions in
the
[Google Maps Platform Documentation](https://developers.google.com/maps/documentation/javascript/versions).

Use of Agentic UI Toolkit requires several [Maps JavaScript API libraries](https://developers.google.com/maps/documentation/javascript/libraries). When loading the Google Maps JavaScript API, you must include the following libraries:
Use of Agentic UI Toolkit requires several
[Maps JavaScript API libraries](https://developers.google.com/maps/documentation/javascript/libraries).
When loading the Google Maps JavaScript API, you must include the following
libraries:

* maps
* maps3d
* marker
* places
* routes
* maps
* maps3d
* marker
* places
* routes

### Gemini API Key

*Note: This API is variously referred to in Google Cloud as the* Gemini API *and the* Generative Language API.
*Note: This API is variously referred to in Google Cloud as the* Gemini API *and
the* Generative Language API.

If you are using Gemini as your LLM, you will also need a Google Cloud API Key with the *Generative Language API* enabled. In order to enable this API for your API Key, the *Gemini API* must be enabled for your Google Cloud project. You can enable this API in the [API Library](https://console.cloud.google.com/apis/library/generativelanguage.googleapis.com).
If you are using Gemini as your LLM, you will also need a Google Cloud API Key
with the *Generative Language API* enabled. In order to enable this API for your
API Key, the *Gemini API* must be enabled for your Google Cloud project. You can
enable this API in the
[API Library](https://console.cloud.google.com/apis/library/generativelanguage.googleapis.com).

To create a new Google Cloud API Key, follow the instructions here in the [Google Cloud docs](https://docs.cloud.google.com/docs/authentication/api-keys#create).
To create a new Google Cloud API Key, follow the instructions here in the
[Google Cloud docs](https://docs.cloud.google.com/docs/authentication/api-keys#create).

This key must be exported or contained within a `.env` file as `GEMINI_API_KEY`

## Accessing Google Maps grounding data

Your agent can access Google Maps grounding data in two ways, depending on your project setup and needs:
Your agent can access Google Maps grounding data in two ways, depending on your
project setup and needs:

1. [Grounding Lite MCP](https://developers.google.com/maps/ai/grounding-lite)
2. [Grounding with Google Maps](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-google-maps)
1. [Grounding Lite MCP](https://developers.google.com/maps/ai/grounding-lite)
2. [Grounding with Google Maps](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-google-maps)

### Grounding Lite MCP

To use Grounding Lite MCP, you must first enable the Maps Grounding Lite API and create or update an API Key to support the required APIs following the [documentation](https://developers.google.com/maps/ai/grounding-lite#configure_llms_to_use_the_mcp_server).
To use Grounding Lite MCP, you must first enable the Maps Grounding Lite API and
create or update an API Key to support the required APIs following the
[documentation](https://developers.google.com/maps/ai/grounding-lite#configure_llms_to_use_the_mcp_server).

### Grounding with Google Maps

To use Grounding with Google Maps, there are additional steps you must take to configure your environment:
To use Grounding with Google Maps, there are additional steps you must take to
configure your environment:

1. Ensure you have the latest version of the genai python package.

1. Ensure you have the latest version of the genai python package.
```bash
pip install --upgrade google-genai
```

2. Configure additional environment variables to connect to your project.
1. Configure additional environment variables to connect to your project.

```bash
## Replace the `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION` values
## with appropriate values for your project.
Expand All @@ -110,9 +145,12 @@ export GOOGLE_CLOUD_LOCATION=global
export GOOGLE_GENAI_USE_VERTEXAI=True
```

3. Ensure you are authenticated to Google Cloud.
1. Ensure you are authenticated to Google Cloud.

```bash
gcloud auth application-default login
```

See the [documentation](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-google-maps#googlegenaisdk_tools_google_maps_with_txt-python_genai_sdk) for more information.
See the
[documentation](https://docs.cloud.google.com/vertex-ai/generative-ai/docs/grounding/grounding-with-google-maps#googlegenaisdk_tools_google_maps_with_txt-python_genai_sdk)
for more information.
89 changes: 47 additions & 42 deletions agent/python/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,21 @@
import logging
import os

import click
from a2a.server.apps import A2AStarletteApplication
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard, AgentSkill
from agent import MAUIAgent
from agent_executor import MAUIAgentExecutor
from agent_with_grounding import MAUIAgentWithGrounding
from dotenv import load_dotenv
import click
import dotenv
from starlette.middleware.cors import CORSMiddleware
from starlette.staticfiles import StaticFiles
from starlette.responses import RedirectResponse
from starlette.staticfiles import StaticFiles

from python_agent.agent import MAUIAgent
from python_agent.agent_with_grounding import MAUIAgentWithGrounding
from agent_executor import MAUIAgentExecutor

load_dotenv()
dotenv.load_dotenv()

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
Expand All @@ -43,48 +44,52 @@ class MissingAPIKeyError(Exception):
@click.option("--host", default="0.0.0.0")
@click.option("--port", default=10002)
def main(serverurl, host, port):
try:
# Check for API key only if Vertex AI is not configured
if not os.getenv("GOOGLE_GENAI_USE_VERTEXAI") == "TRUE":
if not os.getenv("GEMINI_API_KEY"):
raise MissingAPIKeyError(
"GEMINI_API_KEY environment variable not set and GOOGLE_GENAI_USE_VERTEXAI is not TRUE."
)
try:
# Check for API key only if Vertex AI is not configured
if not os.getenv("GOOGLE_GENAI_USE_VERTEXAI") == "TRUE":
if not os.getenv("GEMINI_API_KEY"):
raise MissingAPIKeyError(
"GEMINI_API_KEY environment variable not set and"
" GOOGLE_GENAI_USE_VERTEXAI is not TRUE."
)

base_url = f"http://{host}:{port}"
base_url = f"http://{host}:{port}"

if (serverurl != ""):
base_url = serverurl
if serverurl != "":
base_url = serverurl

ui_agent = MAUIAgent(base_url=base_url)
grounding_agent = MAUIAgentWithGrounding(base_url=base_url)
ui_agent = MAUIAgent(base_url=base_url)
grounding_agent = MAUIAgentWithGrounding(base_url=base_url)

agent_executor = MAUIAgentExecutor(default_agent=ui_agent, grounding_agent=grounding_agent)
agent_executor = MAUIAgentExecutor(
default_agent=ui_agent, grounding_agent=grounding_agent
)

request_handler = DefaultRequestHandler(
agent_executor=agent_executor,
task_store=InMemoryTaskStore(),
)
server = A2AStarletteApplication(
agent_card=ui_agent.agent_card, http_handler=request_handler
)
import uvicorn
request_handler = DefaultRequestHandler(
agent_executor=agent_executor,
task_store=InMemoryTaskStore(),
)
server = A2AStarletteApplication(
agent_card=ui_agent.agent_card, http_handler=request_handler
)
import uvicorn

app = server.build()
app = server.build()

app.add_middleware(
CORSMiddleware,
allow_origin_regex=r"http://localhost:\d+",
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.add_middleware(
CORSMiddleware,
allow_origin_regex=r"http://localhost:\d+",
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

logger.info(f"Starting A2A server on {host}:{port}")
uvicorn.run(app, host=host, port=port)
except Exception as e:
logger.error(f"An error occurred during server startup: {e}")
exit(1)

logger.info(f"Starting A2A server on {host}:{port}")
uvicorn.run(app, host=host, port=port)
except Exception as e:
logger.error(f"An error occurred during server startup: {e}")
exit(1)

if __name__ == "__main__":
main()
main()
Loading
Loading