mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
chore: Add a basic a2a agent demo sample
PiperOrigin-RevId: 776660703
This commit is contained in:
committed by
Copybara-Service
parent
f0183a9b98
commit
1cf5cf0d0a
@@ -0,0 +1,120 @@
|
|||||||
|
# A2A Basic Sample Agent
|
||||||
|
|
||||||
|
This sample demonstrates the **Agent-to-Agent (A2A)** architecture in the Agent Development Kit (ADK), showcasing how multiple agents can work together to handle complex tasks. The sample implements an agent that can roll dice and check if numbers are prime.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The A2A Basic sample consists of:
|
||||||
|
|
||||||
|
- **Root Agent** (`root_agent`): The main orchestrator that delegates tasks to specialized sub-agents
|
||||||
|
- **Roll Agent** (`roll_agent`): A local sub-agent that handles dice rolling operations
|
||||||
|
- **Prime Agent** (`prime_agent`): A remote A2A agent that checks if numbers are prime, this agent is running on a separate A2A server
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌──────────────────┐ ┌────────────────────┐
|
||||||
|
│ Root Agent │───▶│ Roll Agent │ │ Remote Prime │
|
||||||
|
│ (Local) │ │ (Local) │ │ Agent │
|
||||||
|
│ │ │ │ │ (localhost:8001) │
|
||||||
|
│ │───▶│ │◀───│ │
|
||||||
|
└─────────────────┘ └──────────────────┘ └────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
### 1. **Local Sub-Agent Integration**
|
||||||
|
- The `roll_agent` demonstrates how to create and integrate local sub-agents
|
||||||
|
- Handles dice rolling with configurable number of sides
|
||||||
|
- Uses a simple function tool (`roll_die`) for random number generation
|
||||||
|
|
||||||
|
### 2. **Remote A2A Agent Integration**
|
||||||
|
- The `prime_agent` shows how to connect to remote agent services
|
||||||
|
- Communicates with a separate service via HTTP at `http://localhost:8001/a2a/check_prime_agent`
|
||||||
|
- Demonstrates cross-service agent communication
|
||||||
|
|
||||||
|
### 3. **Agent Orchestration**
|
||||||
|
- The root agent intelligently delegates tasks based on user requests
|
||||||
|
- Can chain operations (e.g., "roll a die and check if it's prime")
|
||||||
|
- Provides clear workflow coordination between multiple agents
|
||||||
|
|
||||||
|
### 4. **Example Tool Integration**
|
||||||
|
- Includes an `ExampleTool` with sample interactions for context
|
||||||
|
- Helps the agent understand expected behavior patterns
|
||||||
|
|
||||||
|
## Setup and Usage
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. **Start the Remote Prime Agent server**:
|
||||||
|
```bash
|
||||||
|
# Start the remote a2a server that serves the check prime agent on port 8001
|
||||||
|
adk api_server --a2a --port 8001 contributing/samples/a2a_basic/remote_a2a
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **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:
|
||||||
|
|
||||||
|
**Simple Dice Rolling:**
|
||||||
|
```
|
||||||
|
User: Roll a 6-sided die
|
||||||
|
Bot: I rolled a 4 for you.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Prime Number Checking:**
|
||||||
|
```
|
||||||
|
User: Is 7 a prime number?
|
||||||
|
Bot: Yes, 7 is a prime number.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Combined Operations:**
|
||||||
|
```
|
||||||
|
User: Roll a 10-sided die and check if it's prime
|
||||||
|
Bot: I rolled an 8 for you.
|
||||||
|
Bot: 8 is not a prime number.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Structure
|
||||||
|
|
||||||
|
### Main Agent (`agent.py`)
|
||||||
|
|
||||||
|
- **`roll_die(sides: int)`**: Function tool for rolling dice
|
||||||
|
- **`roll_agent`**: Local agent specialized in dice rolling
|
||||||
|
- **`prime_agent`**: Remote A2A agent configuration
|
||||||
|
- **`root_agent`**: Main orchestrator with delegation logic
|
||||||
|
|
||||||
|
### Remote Prime Agent (`remote_a2a/check_prime_agent/`)
|
||||||
|
|
||||||
|
- **`agent.py`**: Implementation of the prime checking service
|
||||||
|
- **`agent.json`**: Agent card of the A2A agent
|
||||||
|
- **`check_prime(nums: list[int])`**: Prime number checking algorithm
|
||||||
|
|
||||||
|
|
||||||
|
## Extending the Sample
|
||||||
|
|
||||||
|
You can extend this sample by:
|
||||||
|
|
||||||
|
- Adding more mathematical operations (factorization, square roots, etc.)
|
||||||
|
- Creating additional remote agent
|
||||||
|
- Implementing more complex delegation logic
|
||||||
|
- Adding persistent state management
|
||||||
|
- Integrating with external APIs or databases
|
||||||
|
|
||||||
|
## 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
|
||||||
|
|
||||||
|
**Agent Not Responding:**
|
||||||
|
- Check the logs for both the local ADK web server on port 8000 and remote A2A server on port 8001
|
||||||
|
- Verify the agent instructions are clear and unambiguous
|
||||||
Executable
+15
@@ -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
|
||||||
Executable
+120
@@ -0,0 +1,120 @@
|
|||||||
|
# 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 random
|
||||||
|
|
||||||
|
from google.adk.agents import Agent
|
||||||
|
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
|
||||||
|
from google.adk.tools.example_tool import ExampleTool
|
||||||
|
from google.genai import types
|
||||||
|
|
||||||
|
|
||||||
|
# --- Roll Die Sub-Agent ---
|
||||||
|
def roll_die(sides: int) -> int:
|
||||||
|
"""Roll a die and return the rolled result."""
|
||||||
|
return random.randint(1, sides)
|
||||||
|
|
||||||
|
|
||||||
|
roll_agent = Agent(
|
||||||
|
name="roll_agent",
|
||||||
|
description="Handles rolling dice of different sizes.",
|
||||||
|
instruction="""
|
||||||
|
You are responsible for rolling dice based on the user's request.
|
||||||
|
When asked to roll a die, you must call the roll_die tool with the number of sides as an integer.
|
||||||
|
""",
|
||||||
|
tools=[roll_die],
|
||||||
|
generate_content_config=types.GenerateContentConfig(
|
||||||
|
safety_settings=[
|
||||||
|
types.SafetySetting( # avoid false alarm about rolling dice.
|
||||||
|
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||||
|
threshold=types.HarmBlockThreshold.OFF,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
example_tool = ExampleTool([
|
||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"role": "user",
|
||||||
|
"parts": [{"text": "Roll a 6-sided die."}],
|
||||||
|
},
|
||||||
|
"output": [
|
||||||
|
{"role": "model", "parts": [{"text": "I rolled a 4 for you."}]}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"role": "user",
|
||||||
|
"parts": [{"text": "Is 7 a prime number?"}],
|
||||||
|
},
|
||||||
|
"output": [{
|
||||||
|
"role": "model",
|
||||||
|
"parts": [{"text": "Yes, 7 is a prime number."}],
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": {
|
||||||
|
"role": "user",
|
||||||
|
"parts": [{"text": "Roll a 10-sided die and check if it's prime."}],
|
||||||
|
},
|
||||||
|
"output": [
|
||||||
|
{
|
||||||
|
"role": "model",
|
||||||
|
"parts": [{"text": "I rolled an 8 for you."}],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"role": "model",
|
||||||
|
"parts": [{"text": "8 is not a prime number."}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
prime_agent = RemoteA2aAgent(
|
||||||
|
name="prime_agent",
|
||||||
|
description="Agent that handles checking if numbers are prime.",
|
||||||
|
agent_card=(
|
||||||
|
"http://localhost:8001/a2a/check_prime_agent/.well-known/agent.json"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
root_agent = Agent(
|
||||||
|
model="gemini-1.5-flash",
|
||||||
|
name="root_agent",
|
||||||
|
instruction="""
|
||||||
|
You are a helpful assistant that can roll dice and check if numbers are prime.
|
||||||
|
You delegate rolling dice tasks to the roll_agent and prime checking tasks to the prime_agent.
|
||||||
|
Follow these steps:
|
||||||
|
1. If the user asks to roll a die, delegate to the roll_agent.
|
||||||
|
2. If the user asks to check primes, delegate to the prime_agent.
|
||||||
|
3. If the user asks to roll a die and then check if the result is prime, call roll_agent first, then pass the result to prime_agent.
|
||||||
|
Always clarify the results before proceeding.
|
||||||
|
""",
|
||||||
|
global_instruction=(
|
||||||
|
"You are DicePrimeBot, ready to roll dice and check prime numbers."
|
||||||
|
),
|
||||||
|
sub_agents=[roll_agent, prime_agent],
|
||||||
|
tools=[example_tool],
|
||||||
|
generate_content_config=types.GenerateContentConfig(
|
||||||
|
safety_settings=[
|
||||||
|
types.SafetySetting( # avoid false alarm about rolling dice.
|
||||||
|
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||||
|
threshold=types.HarmBlockThreshold.OFF,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"capabilities": {},
|
||||||
|
"defaultInputModes": ["text/plain"],
|
||||||
|
"defaultOutputModes": ["application/json"],
|
||||||
|
"description": "An agent specialized in checking whether numbers are prime. It can efficiently determine the primality of individual numbers or lists of numbers.",
|
||||||
|
"name": "check_prime_agent",
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"id": "prime_checking",
|
||||||
|
"name": "Prime Number Checking",
|
||||||
|
"description": "Check if numbers in a list are prime using efficient mathematical algorithms",
|
||||||
|
"tags": ["mathematical", "computation", "prime", "numbers"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"url": "http://localhost:8001/a2a/check_prime_agent",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# 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 random
|
||||||
|
|
||||||
|
from google.adk import Agent
|
||||||
|
from google.adk.tools.tool_context import ToolContext
|
||||||
|
from google.genai import types
|
||||||
|
|
||||||
|
|
||||||
|
async def check_prime(nums: list[int]) -> str:
|
||||||
|
"""Check if a given list of numbers are prime.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nums: The list of numbers to check.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A str indicating which number is prime.
|
||||||
|
"""
|
||||||
|
primes = set()
|
||||||
|
for number in nums:
|
||||||
|
number = int(number)
|
||||||
|
if number <= 1:
|
||||||
|
continue
|
||||||
|
is_prime = True
|
||||||
|
for i in range(2, int(number**0.5) + 1):
|
||||||
|
if number % i == 0:
|
||||||
|
is_prime = False
|
||||||
|
break
|
||||||
|
if is_prime:
|
||||||
|
primes.add(number)
|
||||||
|
return (
|
||||||
|
'No prime numbers found.'
|
||||||
|
if not primes
|
||||||
|
else f"{', '.join(str(num) for num in primes)} are prime numbers."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
root_agent = Agent(
|
||||||
|
model='gemini-2.0-flash',
|
||||||
|
name='check_prime_agent',
|
||||||
|
description='check prime agent that can check whether numbers are prime.',
|
||||||
|
instruction="""
|
||||||
|
You check whether numbers are prime.
|
||||||
|
When checking prime numbers, call the check_prime tool with a list of integers. Be sure to pass in a list of integers. You should never pass in a string.
|
||||||
|
You should not rely on the previous history on prime results.
|
||||||
|
""",
|
||||||
|
tools=[
|
||||||
|
check_prime,
|
||||||
|
],
|
||||||
|
# planner=BuiltInPlanner(
|
||||||
|
# thinking_config=types.ThinkingConfig(
|
||||||
|
# include_thoughts=True,
|
||||||
|
# ),
|
||||||
|
# ),
|
||||||
|
generate_content_config=types.GenerateContentConfig(
|
||||||
|
safety_settings=[
|
||||||
|
types.SafetySetting( # avoid false alarm about rolling dice.
|
||||||
|
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
|
||||||
|
threshold=types.HarmBlockThreshold.OFF,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user