Skip to content

chore: Add an a2a agent to demo oauth flow #1664

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
183 changes: 183 additions & 0 deletions contributing/samples/a2a_auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# A2A OAuth Authentication Sample Agent

This sample demonstrates the **Agent-to-Agent (A2A)** architecture with **OAuth Authentication** workflows in the Agent Development Kit (ADK). The sample implements a multi-agent system where a remote agent can surface OAuth authentication requests to the local agent, which then guides the end user through the OAuth flow before returning the authentication credentials to the remote agent for API access.

## Overview

The A2A OAuth Authentication sample consists of:

- **Root Agent** (`root_agent`): The main orchestrator that handles user requests and delegates tasks to specialized agents
- **YouTube Search Agent** (`youtube_search_agent`): A local agent that handles YouTube video searches using LangChain tools
- **BigQuery Agent** (`bigquery_agent`): A remote A2A agent that manages BigQuery operations and requires OAuth authentication for Google Cloud access

## Architecture

```
┌─────────────────┐ ┌────────────────────┐ ┌──────────────────┐
│ End User │───▶│ Root Agent │───▶│ BigQuery Agent │
│ (OAuth Flow) │ │ (Local) │ │ (Remote A2A) │
│ │ │ │ │ (localhost:8001) │
│ OAuth UI │◀───│ │◀───│ OAuth Request │
└─────────────────┘ └────────────────────┘ └──────────────────┘
```

## Key Features

### 1. **Multi-Agent Architecture**
- Root agent coordinates between local YouTube search and remote BigQuery operations
- Demonstrates hybrid local/remote agent workflows
- Seamless task delegation based on user request types

### 2. **OAuth Authentication Workflow**
- Remote BigQuery agent surfaces OAuth authentication requests to the root agent
- Root agent guides end users through Google OAuth flow for BigQuery access
- Secure token exchange between agents for authenticated API calls

### 3. **Google Cloud Integration**
- BigQuery toolset with comprehensive dataset and table management capabilities
- OAuth-protected access to user's Google Cloud BigQuery resources
- Support for listing, creating, and managing datasets and tables

### 4. **LangChain Tool Integration**
- YouTube search functionality using LangChain community tools
- Demonstrates integration of third-party tools in agent workflows

## Setup and Usage

### Prerequisites

1. **Set up OAuth Credentials**:
```bash
export OAUTH_CLIENT_ID=your_google_oauth_client_id
export OAUTH_CLIENT_SECRET=your_google_oauth_client_secret
```

2. **Start the Remote BigQuery Agent server**:
```bash
# Start the remote a2a server that serves the BigQuery agent on port 8001
adk api_server --a2a --port 8001 contributing/samples/a2a_auth/remote_a2a
```

3. **Run the Main Agent**:
```bash
# In a separate terminal, run the adk web server
adk web contributing/samples/
```

### Example Interactions

Once both services are running, you can interact with the root agent:

**YouTube Search (No Authentication Required):**
```
User: Search for 3 Taylor Swift music videos
Agent: I'll help you search for Taylor Swift music videos on YouTube.
[Agent delegates to YouTube Search Agent]
Agent: I found 3 Taylor Swift music videos:
1. "Anti-Hero" - Official Music Video
2. "Shake It Off" - Official Music Video
3. "Blank Space" - Official Music Video
```

**BigQuery Operations (OAuth Required):**
```
User: List my BigQuery datasets
Agent: I'll help you access your BigQuery datasets. This requires authentication with your Google account.
[Agent delegates to BigQuery Agent]
Agent: To access your BigQuery data, please complete the OAuth authentication.
[OAuth flow initiated - user redirected to Google authentication]
User: [Completes OAuth flow in browser]
Agent: Authentication successful! Here are your BigQuery datasets:
- dataset_1: Customer Analytics
- dataset_2: Sales Data
- dataset_3: Marketing Metrics
```

**Dataset Management:**
```
User: Show me details for my Customer Analytics dataset
Agent: I'll get the details for your Customer Analytics dataset.
[Using existing OAuth token]
Agent: Customer Analytics Dataset Details:
- Created: 2024-01-15
- Location: US
- Tables: 5
- Description: Customer behavior and analytics data
```

## Code Structure

### Main Agent (`agent.py`)

- **`youtube_search_agent`**: Local agent with LangChain YouTube search tool
- **`bigquery_agent`**: Remote A2A agent configuration for BigQuery operations
- **`root_agent`**: Main orchestrator with task delegation logic

### Remote BigQuery Agent (`remote_a2a/bigquery_agent/`)

- **`agent.py`**: Implementation of the BigQuery agent with OAuth toolset
- **`agent.json`**: Agent card of the A2A agent
- **`BigQueryToolset`**: OAuth-enabled tools for BigQuery dataset and table management

## OAuth Authentication Workflow

The OAuth authentication process follows this pattern:

1. **Initial Request**: User requests BigQuery operation through root agent
2. **Delegation**: Root agent delegates to remote BigQuery agent
3. **Auth Check**: BigQuery agent checks for valid OAuth token
4. **Auth Request**: If no token, agent surfaces OAuth request to root agent
5. **User OAuth**: Root agent guides user through Google OAuth flow
6. **Token Exchange**: Root agent sends OAuth token to BigQuery agent
7. **API Call**: BigQuery agent uses token to make authenticated API calls
8. **Result Return**: BigQuery agent returns results through root agent to user

## Supported BigQuery Operations

The BigQuery agent supports the following operations:

### Dataset Operations:
- **List Datasets**: `bigquery_datasets_list` - Get all user's datasets
- **Get Dataset**: `bigquery_datasets_get` - Get specific dataset details
- **Create Dataset**: `bigquery_datasets_insert` - Create new dataset

### Table Operations:
- **List Tables**: `bigquery_tables_list` - Get tables in a dataset
- **Get Table**: `bigquery_tables_get` - Get specific table details
- **Create Table**: `bigquery_tables_insert` - Create new table in dataset

## Extending the Sample

You can extend this sample by:

- Adding more Google Cloud services (Cloud Storage, Compute Engine, etc.)
- Implementing token refresh and expiration handling
- Adding role-based access control for different BigQuery operations
- Creating OAuth flows for other providers (Microsoft, Facebook, etc.)
- Adding audit logging for authentication events
- Implementing multi-tenant OAuth token management

## Troubleshooting

**Connection Issues:**
- Ensure the local ADK web server is running on port 8000
- Ensure the remote A2A server is running on port 8001
- Check that no firewall is blocking localhost connections
- Verify the agent.json URL matches the running A2A server

**OAuth Issues:**
- Verify OAuth client ID and secret are correctly set in .env file
- Ensure OAuth redirect URIs are properly configured in Google Cloud Console
- Check that the OAuth scopes include BigQuery access permissions
- Verify the user has access to the BigQuery projects/datasets

**BigQuery Access Issues:**
- Ensure the authenticated user has BigQuery permissions
- Check that the Google Cloud project has BigQuery API enabled
- Verify dataset and table names are correct and accessible
- Check for quota limits on BigQuery API calls

**Agent Communication Issues:**
- Check the logs for both the local ADK web server and remote A2A server
- Verify OAuth tokens are properly passed between agents
- Ensure agent instructions are clear about authentication requirements
15 changes: 15 additions & 0 deletions contributing/samples/a2a_auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from . import agent
62 changes: 62 additions & 0 deletions contributing/samples/a2a_auth/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from google.adk.agents import Agent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
from google.adk.tools.langchain_tool import LangchainTool
from langchain_community.tools import YouTubeSearchTool

# Instantiate the tool
langchain_yt_tool = YouTubeSearchTool()

# Wrap the tool in the LangchainTool class from ADK
adk_yt_tool = LangchainTool(
tool=langchain_yt_tool,
)

youtube_search_agent = Agent(
name="youtube_search_agent",
model="gemini-2.0-flash", # Replace with the actual model name
instruction="""
Ask customer to provide singer name, and the number of videos to search.
""",
description="Help customer to search for a video on Youtube.",
tools=[adk_yt_tool],
output_key="youtube_search_output",
)

bigquery_agent = RemoteA2aAgent(
name="bigquery_agent",
description="Help customer to manage notion workspace.",
agent_card=(
"http://localhost:8001/a2a/bigquery_agent/.well-known/agent.json"
),
)

root_agent = Agent(
model="gemini-2.0-flash",
name="root_agent",
instruction="""
You are a helpful assistant that can help search youtube videos, look up BigQuery datasets and tables.
You delegate youtube search tasks to the youtube_search_agent.
You delegate BigQuery tasks to the bigquery_agent.
Always clarify the results before proceeding.
""",
global_instruction=(
"You are a helpful assistant that can help search youtube videos, look"
" up BigQuery datasets and tables."
),
sub_agents=[youtube_search_agent, bigquery_agent],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from . import agent
29 changes: 29 additions & 0 deletions contributing/samples/a2a_auth/remote_a2a/bigquery_agent/agent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"capabilities": {},
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["application/json"],
"description": "A Google BigQuery agent that helps manage users' data on Google BigQuery. Can list, get, and create datasets, as well as manage tables within datasets. Supports OAuth authentication for secure access to BigQuery resources.",
"name": "bigquery_agent",
"skills": [
{
"id": "dataset_management",
"name": "Dataset Management",
"description": "List, get details, and create BigQuery datasets",
"tags": ["bigquery", "datasets", "google-cloud"]
},
{
"id": "table_management",
"name": "Table Management",
"description": "List, get details, and create BigQuery tables within datasets",
"tags": ["bigquery", "tables", "google-cloud"]
},
{
"id": "oauth_authentication",
"name": "OAuth Authentication",
"description": "Secure authentication with Google BigQuery using OAuth",
"tags": ["authentication", "oauth", "security"]
}
],
"url": "http://localhost:8000/a2a/bigquery_agent",
"version": "1.0.0"
}
78 changes: 78 additions & 0 deletions contributing/samples/a2a_auth/remote_a2a/bigquery_agent/agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os

from dotenv import load_dotenv
from google.adk import Agent
from google.adk.tools.google_api_tool import BigQueryToolset

# Load environment variables from .env file
load_dotenv()

# Access the variable
oauth_client_id = os.getenv("OAUTH_CLIENT_ID")
oauth_client_secret = os.getenv("OAUTH_CLIENT_SECRET")
tools_to_expose = [
"bigquery_datasets_list",
"bigquery_datasets_get",
"bigquery_datasets_insert",
"bigquery_tables_list",
"bigquery_tables_get",
"bigquery_tables_insert",
]
bigquery_toolset = BigQueryToolset(
client_id=oauth_client_id,
client_secret=oauth_client_secret,
tool_filter=tools_to_expose,
)

root_agent = Agent(
model="gemini-2.0-flash",
name="bigquery_agent",
instruction="""
You are a helpful Google BigQuery agent that help to manage users' data on Google BigQuery.
Use the provided tools to conduct various operations on users' data in Google BigQuery.

Scenario 1:
The user wants to query their biguqery datasets
Use bigquery_datasets_list to query user's datasets

Scenario 2:
The user wants to query the details of a specific dataset
Use bigquery_datasets_get to get a dataset's details

Scenario 3:
The user wants to create a new dataset
Use bigquery_datasets_insert to create a new dataset

Scenario 4:
The user wants to query their tables in a specific dataset
Use bigquery_tables_list to list all tables in a dataset

Scenario 5:
The user wants to query the details of a specific table
Use bigquery_tables_get to get a table's details

Scenario 6:
The user wants to insert a new table into a dataset
Use bigquery_tables_insert to insert a new table into a dataset

Current user:
<User>
{userInfo?}
</User>
""",
tools=[bigquery_toolset],
)
Loading
Loading