# Google ADK Google Agent Development Kit * 一個模組化框架 * 支援多智能體 * 支援MCP * 可跨平台 ![quickstart-flow-tool[1]](https://google.github.io/adk-docs/assets/quickstart-flow-tool.png) ## 基礎操作 **以下為 WSL 環境下操作步驟** [Agent Development Kit -- Quickstart](https://google.github.io/adk-docs/get-started/quickstart/#venv-install) * 使用 `uv` ([uv 安裝](https://docs.astral.sh/uv/getting-started/installation/)) ```bash= mkdir google_adk uv init uv run main.py uv pip install google-adk mkdir multi_tool_agent/ echo "from . import agent" > multi_tool_agent/__init__.py touch multi_tool_agent/agent.py touch multi_tool_agent/.env ``` ![data_structure](https://hackmd.io/_uploads/B1diaqjRJl.png) :::spoiler agent.py ```python= import datetime from zoneinfo import ZoneInfo from google.adk.agents import Agent def get_weather(city: str) -> dict: """Retrieves the current weather report for a specified city. Args: city (str): The name of the city for which to retrieve the weather report. Returns: dict: status and result or error msg. """ if city.lower() == "new york": return { "status": "success", "report": ( "The weather in New York is sunny with a temperature of 25 degrees" " Celsius (41 degrees Fahrenheit)." ), } else: return { "status": "error", "error_message": f"Weather information for '{city}' is not available.", } def get_current_time(city: str) -> dict: """Returns the current time in a specified city. Args: city (str): The name of the city for which to retrieve the current time. Returns: dict: status and result or error msg. """ if city.lower() == "new york": tz_identifier = "America/New_York" else: return { "status": "error", "error_message": ( f"Sorry, I don't have timezone information for {city}." ), } tz = ZoneInfo(tz_identifier) now = datetime.datetime.now(tz) report = ( f'The current time in {city} is {now.strftime("%Y-%m-%d %H:%M:%S %Z%z")}' ) return {"status": "success", "report": report} root_agent = Agent( name="weather_time_agent", model="gemini-2.0-flash", description=( "Agent to answer questions about the time and weather in a city." ), instruction=( "You are a helpful agent who can answer user questions about the time and weather in a city." ), tools=[get_weather, get_current_time], ) ``` ::: [google_api_key](https://aistudio.google.com/apikey) :::spoiler .env ```bash GOOGLE_GENAI_USE_VERTEXAI=FALSE GOOGLE_API_KEY=PASTE_YOUR_ACTUAL_API_KEY_HERE ``` ::: * run `uv run adk web` ,接著瀏覽器開啟 http://127.0.0.1:8000 ![result](https://hackmd.io/_uploads/HJicmTiR1e.png) **function calling** ![image](https://hackmd.io/_uploads/B1mGV6jC1x.png) **response** ![image](https://hackmd.io/_uploads/HytuVaoAJl.png) ## Workflow Agents * Sequential agents * Loop agents * Parallel agents ### 1. Sequential agents **線性流程示意圖** ![sequential-agent[1]](https://hackmd.io/_uploads/SJUDhZa0Jx.png) **以線性方式進行,agent1 的輸出為 agent2 的輸入** * **程式碼 & 結果** **範例中讓 code_writer_agent 產生第一版兩數字相加程式碼,code_reviewer_agent 判斷是否夠好(有無優化空間),最後 code_refactorer_agent 決定終版** [Sequential agents code](https://google.github.io/adk-docs/agents/workflow-agents/sequential-agents/#full-example-code-development-pipeline) ![image](https://hackmd.io/_uploads/Hk_ERWTAkl.png) ### 2. Loop agents **循環流程示意圖** ![loop-agent[1]](https://hackmd.io/_uploads/SJhZJGTAyx.png) **不斷循環 Agent ,直到滿足條件(夠好)或是達到上限(循環次數)** * **程式碼 & 結果** [Loop agents code](https://google.github.io/adk-docs/agents/workflow-agents/loop-agents/#how-it-works) **在原始程式碼的這段控制循環上限** ```python=46 # Create the LoopAgent loop_agent = LoopAgent( name="LoopAgent", sub_agents=[writer_agent, critic_agent], max_iterations=2 ) ``` **下圖為 `max_iterations=5` 的結果,writer_agent 和 critic_agent 各進行五次** ![image](https://hackmd.io/_uploads/Hkqszz601x.png) ### 3. Parallel agents **平行流程示意圖** ![parallel-agent[1]](https://hackmd.io/_uploads/SkANyfT01e.png) **適合用於每個 Agent 負責不同事物** * **程式碼 & 結果** **官方範例為「再生能源、電動車技術、碳捕獲法」三種 Agent** [Parallel agents code](https://google.github.io/adk-docs/agents/workflow-agents/parallel-agents/#full-example-parallel-web-research) ![image](https://hackmd.io/_uploads/H1XxrMpCkl.png) ## Multi-agent systems (MAS) * 多個不同的 Agent 組合 * 模組化、專業化、可重用性、可維護性、工作流程結構化控制(Workflow Agent) * 父子結構 Agent * 協調器 * 互動溝通機制 ### Agent Hirearchy 代理層級結構 **在 Agent 之中定義其父子關係,每個 sub_agent 只會對應到一個 parent_agent** ```python= from google.adk.agents import LlmAgent, BaseAgent greeter = LlmAgent(name="Greeter", model="gemini-2.0-flash") task_doer = BaseAgent(name="TaskExecutor") # 建立父子關係 coordinator = LlmAgent( name="Coordinator", model="gemini-2.0-flash", description="I coordinate greetings and tasks.", sub_agents=[ greeter, task_doer ] ) # 顯示階層關係 print(f"Greeter 的父 Agent:{greeter.parent_agent.name}") print(f"TaskExecutor 的父 Agent:{task_doer.parent_agent.name}") ``` ![Agent Hirearchy test result](https://hackmd.io/_uploads/HJmoWZAAye.png) ### Workflow Agents as Orchestrators * Sequential Agent **僅實作結合 Agent Hirearchy 的 Sequential agent** ```python= from google.adk.agents import SequentialAgent, LlmAgent step1 = LlmAgent(name="Step1_Fetch", output_key="data") # Saves output to state['data'] step2 = LlmAgent(name="Step2_Process", instruction="Process data from state key 'data'.") pipeline = SequentialAgent(name="MyPipeline", sub_agents=[step1, step2]) print(f"開始執行 {pipeline.name}\n") state = {} for agent in pipeline.sub_agents: print(agent.name) ``` ![sequential agent result](https://hackmd.io/_uploads/rJrAdWA0yx.png) * Paralle Agent **與 Sqquential agent 寫法大致相同,可以透過 `session.state` 避免 agent 間的衝突** ```python= from google.adk.agents import ParallelAgent, LlmAgent fetch_weather = LlmAgent(name="WeatherFetcher", output_key="weather") fetch_news = LlmAgent(name="NewsFetcher", output_key="news") gatherer = ParallelAgent(name="InfoGatherer", sub_agents=[fetch_weather, fetch_news]) ``` * Loop Agent [Loop Agent 作法範例](https://google.github.io/adk-docs/agents/multi-agents/#22-workflow-agents-as-orchestrators:~:text=LoopAgent%3A%20Executes%20its%20sub_agents%20sequentially%20in%20a%20loop.) ### Interaction & Communication Mechanisms 1. session.state **在以下片段中AgentB 會將AgentA的輸出作為輸入使用** ```pytohn agent_A = LlmAgent(name="AgentA", instruction="Find the capital of France.", output_key="capital_city") agent_B = LlmAgent(name="AgentB", instruction="Tell me about the city stored in state key 'capital_city'.") ``` 2. Agent Transfer **parent_agent 的指令(instruction) 要明確什麼時候用哪個** **sub_agent 的描述(description) 要清楚到能讓 parent_agent 選擇** ```python booking_agent = LlmAgent(name="Booker", description="Handles flight and hotel bookings.") info_agent = LlmAgent(name="Info", description="Provides general information and answers questions.") coordinator = LlmAgent( name="Coordinator", instruction="You are an assistant. Delegate booking tasks to Booker and info requests to Info.", description="Main coordinator.", # AutoFlow is typically used implicitly here sub_agents=[booking_agent, info_agent] ) ``` 3. Agent Tool **將其它 Agent 也視為一個 tool 來呼叫** **`agent_tool.AgentTool()` 將 Agent 包裝成 tool** ```python from pydantic import BaseModel # Define a target agent (could be LlmAgent or custom BaseAgent) class ImageGeneratorAgent(BaseAgent): # Example custom agent name: str = "ImageGen" description: str = "Generates an image based on a prompt." # ... internal logic ... # ... internal logic ... # ... internal logic ... image_agent = ImageGeneratorAgent() image_tool = agent_tool.AgentTool(agent=image_agent) # Wrap the agent # Parent agent uses the AgentTool artist_agent = LlmAgent( name="Artist", model="gemini-2.0-flash", instruction="Create a prompt and use the ImageGen tool to generate the image.", tools=[image_tool] # Include the AgentTool ) ```