This project demonstrates simple agents built using the Google Agent Development Kit (ADK). It accompanies the YouTube tutorial series "ADK Made Simple" hosted on the AIOriented YouTube channel.
Full series playlist: ADK Made Simple Playlist
| Lesson | Link | Description |
|---|---|---|
| 1 | Lesson 1: Basics of ADK & Reddit Scout Agent | Basics of ADK, Building a Reddit news agent with PRAW |
| 2 | Lesson 2: Multi-Agent Systems & TTS | Combining ADK with MCP, Multi-Agent Systems, Text-To-Speech with ElevenLabs, LiteLLM |
| 3 | Lesson 3: Custom UI for Speaker Agent (ADK API Server) | Building a Streamlit UI for the Speaker Agent using the ADK API server (no A2A yet) |
| 4 | Lesson 4: Serving Agents via A2A Protocol | Introducing the A2A protocol, running agents as standalone A2A services, and building UIs for A2A agents |
- Reddit Scout: Simulates fetching recent discussion titles from game development subreddits.
- Speaker Agent: Converts text to speech using the ElevenLabs TTS API via an MCP toolset. Can be run via
adk api_serveror as a standalone A2A service.
-
Clone the repository:
git clone https://github.com/chongdashu/adk-made-simple cd adk-made-simple -
Create and activate a virtual environment (Recommended):
python -m venv .venv # On Windows .\.venv\Scripts\activate # On macOS/Linux source .venv/bin/activate
-
Install general dependencies:
pip install -r requirements.txt
-
Agent-Specific Setup: Navigate to the specific agent's directory within
agents/and follow the instructions in itsREADME.md(or follow the steps below for the default agent).
This section describes running agents via the ADK framework (e.g., adk run or adk web).
-
Navigate to Agent Directory:
cd agents/reddit_scout -
Set up API Key:
- Copy the example environment file:
cp ../.env.example .env
- Edit the
.envfile and add your Google AI API Key. You can obtain one from Google AI Studio.GOOGLE_API_KEY=YOUR_API_KEY_HERE
- Note: You might need to load this into your environment depending on your OS and shell (
source .envor similar) ifpython-dotenvdoesn't automatically pick it up when runningadk.
- Copy the example environment file:
-
Run the Agent:
- Make sure your virtual environment (from the root directory) is activated.
- From the
agents/reddit_scoutdirectory, run the agent using the ADK CLI, specifying the core code package:adk run reddit_scout
- Alternatively, from the project root (
adk-made-simple), you might be able to run:(Check ADK documentation for preferred discovery method)adk run agents/reddit_scout
- Asynchronous agents can only be run from the web view, so first
cdinto theagentsdirectory and run(Check ADK documentation for preferred discovery method)adk web
-
Interact: The agent will start, and you can interact with it in the terminal or web UI.
The Speaker Agent can be run in two ways:
Mode 1: Via adk api_server (Recommended for ADK framework integration)
- Purpose: Integrates the Speaker Agent with the ADK's coordination layer, allowing it to be used alongside other agents managed by the
api_server. Leverages theAgentdefinition inagents/speaker/agent.py. - How to Run:
- Ensure the Speaker Agent is correctly set up (API keys in
.env, etc.). - Run the main ADK API server from the project root:
adk api_server
- The server will be available (usually on
http://localhost:8000) and manage the Speaker Agent along with others.
- Ensure the Speaker Agent is correctly set up (API keys in
- Interaction: Send requests to the
adk api_server's/runendpoint (port 8000). The server handles session creation and uses the agent's definition (agents/speaker/agent.py) to process requests, potentially involving its internal LLM coordinator. - Testing: Use the test scripts in
scripts/tests/speaker/(e.g.,test_extract_audio.sh) which target port 8000 and expect the ADK event stream response format.
Mode 2: As a Standalone A2A Service
- Purpose: Exposes the Speaker Agent's core TTS functionality directly via an Agent-to-Agent (A2A) compliant HTTP endpoint, bypassing the main ADK
api_server's coordination layer. Uses theagents/speaker/__main__.pyscript. - How to Run:
- Ensure the Speaker Agent is correctly set up (API keys in
.env, etc.). - Run the agent's main script directly from the project root:
python -m agents.speaker
- The standalone server will be available on
http://localhost:8003.
- Ensure the Speaker Agent is correctly set up (API keys in
- Interaction: Send requests directly to the standalone agent's
/runendpoint (port 8003). The payload must match the simpler A2AAgentRequestschema (defined incommon/a2a_server.py). TheTaskManageruses theAgentinstance defined inagents/speaker/agent.pyviaagent.execute. - Testing: Use the specific A2A test script
scripts/tests/speaker/test_a2a_extract_audio.shwhich targets port 8003 and expects the structured JSONAgentResponseformat.
Note on Response Formatting Differences:
While both modes now ultimately call the agent.execute(...) method defined using agents/speaker/agent.py, the final HTTP response received by the client (test script or Streamlit app) differs significantly. This is because the server handling the /run request formats the output of agent.execute differently:
- The
adk api_server(Mode 1) streams the raw sequence of internal ADK events generated byagent.executeback to the client. - The Standalone A2A Server (Mode 2), using our
agents/speaker/task_manager.pyandcommon/a2a_server.py, intercepts the list of events fromagent.execute, processes them to extract key information (like the audio URL), and then constructs and returns a single, structured JSON summary (AgentResponse).
This distinction explains why the test scripts and Streamlit apps need different parsing logic depending on which mode they are interacting with.
test_extract_audio.sh(and similar): Targets theadk api_serveron port 8000. It expects the raw stream of ADK events as a response. It parses the audio file location by looking for specific text patterns (like log messagesFile saved as: ...) within that stream.test_a2a_extract_audio.sh: Targets the standalone agent server on port 8003. It expects a structured JSON response (AgentResponsemodel). It extracts the audio file location directly from thedata.audio_urlfield in the JSON.
This difference arises because the adk api_server and the standalone A2A server format their responses differently for the /run endpoint.
adk-made-simple/
├── agents/
│ ├── reddit_scout/ # Lesson 1: Reddit Scout Agent
│ │ ├── __init__.py
│ │ └── agent.py
│ ├── async_reddit_scout/ # Lesson 2: Asynchronous Reddit Scout Agent
│ │ ├── __init__.py
│ │ └── agent.py
│ ├── summarizer/ # Lesson 2: Newscaster Summarizer Agent
│ │ ├── __init__.py
│ │ └── agent.py
│ ├── speaker/ # Lesson 2: Speaker Agent
│ │ ├── __init__.py
│ │ └── agent.py
│ └── coordinator/ # Lesson 2: Coordinator Agent combining sub-agents
│ ├── __init__.py
│ └── agent.py
├── .env.example # Environment variables example
├── .gitignore # Root gitignore file
├── requirements.txt # Project dependencies
├── README.md # This file (Overall Project README)
└── PLAN.md # Development plan notes
├── apps/
│ ├── speaker_app.py # Streamlit UI for Speaker (via adk api_server)
│ ├── a2a_speaker_app.py # Streamlit UI for Speaker (via standalone A2A)
│ └── README.md # Explanation of the apps
├── common/
│ └── a2a_server.py # Helper for creating standalone A2A servers
├── scripts/
│ ├── tests/
│ │ └── speaker/ # Test scripts for Speaker Agent
│ │ ├── test_extract_audio.sh
│ │ └── test_a2a_extract_audio.sh
│ │ └── ... (other tests)
│ └── run_agents.py # Script to run multiple standalone agents (if needed)
Two Streamlit UIs are provided for the Speaker Agent, demonstrating the two interaction modes:
apps/speaker_app.py: Interacts with the agent via theadk api_server(Mode 1).apps/a2a_speaker_app.py: Interacts directly with the standalone A2A agent service (Mode 2).
See the apps/README.md for details on running these and their differences.
-
Ensure Dependencies:
Make sure you have all required dependencies installed:
pip install -r requirements.txt
-
Run a Streamlit App:
From the project root:
# To run the app interacting with adk api_server: streamlit run apps/speaker_app.py # To run the app interacting with the standalone A2A agent: streamlit run apps/a2a_speaker_app.py
(Note: The
--experimental-asyncflag mentioned previously might not be necessary for these simpler apps, but can be added if async issues arise). -
Using the Apps:
- For
speaker_app.py: Ensureadk api_serveris running. Use the UI to create sessions and send messages. - For
a2a_speaker_app.py: Ensure the standalone agent is running (python -m agents.speaker). Start chatting directly; sessions are handled implicitly.
- For