Skip to content

Commit 224d4f5

Browse files
kthota-gmikeas1
andauthored
feat: Merge latest changes (#7)
* Rename package and clean up dependencies Change-Id: I33496d84c3b40cfbafa395211b4396da709f0b3c * Create a new ADK agent that can use another agent via A2A This also handles updates to the request handler to return from message/send early when a Task reaches an "interruptable" state, which right now is just `auth-required`. Events from the agent are still processed in the background. Change-Id: I5b0848721342bfdba0f4f34909abbf790c0350df --------- Co-authored-by: Mike Smith <[email protected]>
1 parent 0c3f633 commit 224d4f5

File tree

13 files changed

+671
-2450
lines changed

13 files changed

+671
-2450
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# ADK Agent with A2A Client
2+
3+
This example shows how to create an A2A Server that uses an ADK-based Agent that communicates with another agent using A2A.
4+
5+
This agent helps plan birthday parties. It has access to a Calendar Agent that it can delegate calendar-related tasks to. This agent is accessed via A2A.
6+
7+
## Prerequisites
8+
9+
- Python 3.9 or higher
10+
- [UV](https://docs.astral.sh/uv/)
11+
- A Gemini API Key
12+
13+
## Running the example
14+
15+
1. Create the .env file with your API Key
16+
17+
```bash
18+
echo "GOOGLE_API_KEY=your_api_key_here" > .env
19+
```
20+
21+
2. Run the Calendar Agent. See examples/google_adk/calendar_agent.
22+
23+
3. Run the example
24+
25+
```
26+
uv run .
27+
```
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import asyncio
2+
import functools
3+
import logging
4+
import os
5+
6+
import click
7+
import uvicorn
8+
from adk_agent_executor import ADKAgentExecutor
9+
from dotenv import load_dotenv
10+
11+
from a2a.server.apps import A2AStarletteApplication
12+
from a2a.server.request_handlers import DefaultRequestHandler
13+
from a2a.server.tasks import InMemoryTaskStore
14+
from a2a.types import (
15+
AgentAuthentication,
16+
AgentCapabilities,
17+
AgentCard,
18+
AgentSkill,
19+
)
20+
21+
load_dotenv()
22+
23+
logging.basicConfig()
24+
25+
26+
def make_sync(func):
27+
@functools.wraps(func)
28+
def wrapper(*args, **kwargs):
29+
return asyncio.run(func(*args, **kwargs))
30+
31+
return wrapper
32+
33+
34+
@click.command()
35+
@click.option('--host', 'host', default='localhost')
36+
@click.option('--port', 'port', default=10008)
37+
@click.option(
38+
'--calendar-agent', 'calendar_agent', default='http://localhost:10007'
39+
)
40+
def main(host: str, port: int, calendar_agent: str):
41+
# Verify an API key is set. Not required if using Vertex AI APIs, since those can use gcloud credentials.
42+
if not os.getenv('GOOGLE_GENAI_USE_VERTEXAI') == 'TRUE':
43+
if not os.getenv('GOOGLE_API_KEY'):
44+
raise Exception(
45+
'GOOGLE_API_KEY environment variable not set and GOOGLE_GENAI_USE_VERTEXAI is not TRUE.'
46+
)
47+
48+
skill = AgentSkill(
49+
id='plan_parties',
50+
name='Plan a Birthday Party',
51+
description='Plan a birthday party, including times, activities, and themes.',
52+
tags=['event-planning'],
53+
examples=[
54+
'My son is turning 3 on August 2nd! What should I do for his party?',
55+
'Can you add the details to my calendar?',
56+
],
57+
)
58+
59+
agent_executor = ADKAgentExecutor(calendar_agent)
60+
agent_card = AgentCard(
61+
name='Birthday Planner',
62+
description='I can help you plan fun birthday parties.',
63+
url=f'http://{host}:{port}/',
64+
version='1.0.0',
65+
defaultInputModes=['text'],
66+
defaultOutputModes=['text'],
67+
capabilities=AgentCapabilities(streaming=True),
68+
skills=[skill],
69+
authentication=AgentAuthentication(schemes=['public']),
70+
)
71+
request_handler = DefaultRequestHandler(
72+
agent_executor=agent_executor, task_store=InMemoryTaskStore()
73+
)
74+
app = A2AStarletteApplication(agent_card, request_handler)
75+
uvicorn.run(app.build(), host=host, port=port)
76+
77+
78+
if __name__ == '__main__':
79+
main()

0 commit comments

Comments
 (0)