iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
生成式 AI

Multi-Agent 實戰:開發多代理智慧小幫手系列 第 16

【Day 16】 Google ADK 的工具型與子代理寫法

  • 分享至 

  • xImage
  •  

上一篇我們已經介紹了工具型與子代理型 Agent 的定義、差異以及子代理型寫法為什麼更好 等了,那這篇就來實際做做看吧。不過這一篇篇幅會比較長,我會先放上程式碼再逐步解析其中的重點。

工具型 Agent 的寫法

工具型 Agent 是把函數綁到 tools 參數上來提供功能。下面是示範如何定義一個處理數學與文字的代理:把函式寫好後直接放到 tools 裡,讓 root agent 根據輸入選擇要用哪個工具(以 Day 13 為例):

root_agent = Agent(
    name="math_text_agent",
    model="gemini-2.0-flash",
    description=prompt.ROOT_AGENT_DESCRIPTION,
    instruction=prompt.ROOT_AGENT_INSTRUCTION,
    tools=[add_numbers, reverse_text],
)

程式碼解析

  • 工具定義add_numbersreverse_text 是兩個獨立的 Python 函數,分別封裝加法與文字反轉功能,並符合 ADK 的工具規範(明確輸入/輸出型別)。
  • 代理配置
    • name:代理名稱,用來識別。
    • model:指定的語言模型(例如 gemini-2.0-flash)。
    • descriptioninstruction:從外部 prompt 引入,用來定義代理的行為與任務範圍。
    • tools:綁定工具函數清單,代理會根據使用者輸入挑選適合的工具。
  • 運作方式:當使用者請求把 'hello' 反轉時,代理會呼叫 reverse_text;若輸入「2 加 3」,則會選擇 add_numbers

優點

  • 實作簡單,適合快速開發單一功能。
  • 工具函數易於維護,邏輯集中且直觀。

限制

  • 適用於單一代理,無法處理需要多步驟或協作的任務。
  • 工具功能固定,缺乏動態適應能力。

子代理(Sub-Agent)的寫法

子代理是把多個獨立 Agent 綁到主代理的 sub_agents,達成多代理協作。下面示範一個有兩個子代理(問候與天氣)的結構。

__init__.py

from .RootAgent import root_agent

子代理 1 - HelloAgent.py

將 Day 06 的問候 API 改為工具函式,讓 sub agent 可呼叫:

from fastapi import FastAPI, HTTPException
from google.adk.agents import Agent
from . import prompt

# 將 API 改為函式
def greet_user(request: dict) -> dict:
    """
    呼叫問候 Agent,根據提供的名字回傳客製化問候語。
    """
    try:
        # 從 request dict 取出名字
        user_name = request.get("name", "")

        # 生成問候語
        greeting_message = generate_greeting(user_name)

        # 回傳結果
        return {"greeting": greeting_message}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"An error occurred: {e}")

def generate_greeting(name: str) -> str:
    """
    根據輸入的名字生成一個問候語。
    """
    if not name:
        return "Hello there! What's your name?"
    else:
        return f"Hello, {name}! Nice to meet you."

hello_agent = Agent(
    name="hello_agent",
    model="gemini-2.5-flash",
    description=prompt.HELLO_AGENT_DESCRIPTION,
    instruction=prompt.HELLO_AGENT_INSTRUCTION,
    tools=[greet_user],
)

子代理 2 - WeatherAgent.py

把 Day 07 的天氣 API 改為工具函式,供 sub agent 使用:

import datetime
from zoneinfo import ZoneInfo
from google.adk.agents import Agent
import httpx
import os
from dotenv import load_dotenv

from . import prompt

load_dotenv()

# 將 API 改為函式
def get_weather(city: str) -> dict:
    """從中央氣象局 API 獲取指定城市的 36 小時天氣資訊(同步)"""
    try:
        url = "https://opendata.cwa.gov.tw/api/v1/rest/datastore/F-C0032-001"
        params = {
            "Authorization": os.getenv("CWA_API_KEY"),
            "locationName": city,
            "format": "JSON"
        }

        with httpx.Client() as client:
            response = client.get(url, params=params)
            response.raise_for_status()
            data = response.json()

        locations = data["records"]["location"]
        for loc in locations:
            if loc["locationName"] == city:
                wx = _get_first_param(loc, "Wx")
                pop = _get_first_param(loc, "PoP")
                min_t = _get_first_param(loc, "MinT")
                max_t = _get_first_param(loc, "MaxT")
                ci = _get_first_param(loc, "CI")
                return {
                    "status": "success",
                    "report": (
                        f"{city} 天氣預報:{wx},降雨機率 {pop}%,"
                        f"氣溫 {min_t}°C ~ {max_t}°C,體感 {ci}。"
                    )
                }

        return {"status": "error", "error_message": f"找不到 {city} 的天氣資料"}

    except Exception as e:
        return {"status": "error", "error_message": str(e)}

def _get_first_param(location: dict, element_name: str) -> str:
    """從 weatherElement 擷取指定 element 的第一筆資料"""
    for element in location["weatherElement"]:
        if element["elementName"] == element_name:
            return element["time"][0]["parameter"]["parameterName"]
    return "無資料"

weather_agent = Agent(
    name="weather_agent",
    model="gemini-2.5-flash",
    description=prompt.WEATHER_AGENT_DESCRIPTION,
    instruction=prompt.WEATHER_AGENT_INSTRUCTION,
    tools=[get_weather],
)

主代理 - RootAgent.py

把兩個子代理加入 sub_agents

from google.adk.agents import Agent
import os
from dotenv import load_dotenv

from .HelloAgent import hello_agent
from .WeatherAgent import weather_agent
from . import prompt

load_dotenv()

root_agent = Agent(
    name="root_agent",
    model="gemini-2.5-flash",
    description=prompt.ROOT_AGENT_DESCRIPTION,
    instruction=prompt.ROOT_AGENT_INSTRUCTION,
    sub_agents=[
        hello_agent,
        weather_agent
    ],
)

prompt.py

為每個 Agent 撰寫對應的 prompt:

ROOT_AGENT_DESCRIPTION = """
This is a coordination agent (root agent) capable of handling greetings ("hello world") and weather queries. It delegates user requests to the appropriate sub-agents.
"""

ROOT_AGENT_INSTRUCTION = """
You are a root agent responsible for coordinating different sub-agents, handling user greetings and weather-related questions. You can use the following sub-agents:

1. **Hello Agent**: Handles greetings and casual conversation, and can provide personalized greetings based on the user's name.
2. **Weather Agent**: Handles weather queries related to specific cities or locations.

Your responsibilities:
- Analyze user input and determine which sub-agent should handle it.
- If the input is a greeting, casual chat, or small talk, delegate it to the Hello Agent.
- If the input is about weather, temperature, climate, or weather conditions, delegate it to the Weather Agent.
- If the input involves both categories, you may use both agents.
- Integrate the sub-agent outputs into a clear, friendly, and helpful response.

Dispatch guidelines:
- Weather-related keywords: weather, temperature, rain, sunny, cloudy, forecast, climate, hot, cold, etc.
- Greeting-related keywords: hello, hi, hey, good morning, how are you, etc.
- Understand the context and the user's actual intent to make the best dispatch decision.

Respond naturally and friendly, ensuring the user receives the most relevant and helpful information.
"""


WEATHER_AGENT_DESCRIPTION = """
Provides real-time weather information and conditions for specific cities or locations, delivering accurate and referenceable meteorological data.
"""

WEATHER_AGENT_INSTRUCTION = """
You are a weather query agent responsible for providing users with weather information for specified locations.

Your responsibilities:
- Retrieve the latest weather conditions based on the city or location provided by the user.
- Provide temperature, precipitation probability, weather description, and feels-like information.
- Respond in a clear and friendly format.
- Handle all weather-related queries concerning geographic locations.

Focus on weather-related questions and provide as complete information as possible, including current conditions, temperature range, precipitation probability, and any weather alerts.
"""


HELLO_AGENT_DESCRIPTION = """
Handles user greetings and opening remarks, generating personalized greetings when the user provides their name.
"""

HELLO_AGENT_INSTRUCTION = """
You are a greeting agent. Your task is to handle greetings and opening conversation, providing personalized responses if the user provides their name.

Your responsibilities:
- Respond to user greetings (e.g., hello, hi, hey, good morning, etc.).
- If the user provides their name, generate a personalized greeting including the name.
- If the user does not provide a name, respond with a generic greeting.

Maintain a friendly, natural, and relaxed tone.
"""

記得要在 .env 裡加入會使用到的 API Key,否則執行會失敗。


程式碼解析重點

  • 主代理 (RootAgent.py):透過 sub_agents 綁定 hello_agentweather_agent,由主代理負責任務分配(例如把「問候」派給 hello_agent,把「天氣」派給 weather_agent)。使用較高階模型(如 gemini-2.5-flash)有助於任務協調與理解複雜指令。
  • 子代理 (helloAgent.py, weatherAgent.py):每個子代理都是獨立的 Agent 實例,擁有自己的模型、指令、描述與工具,專注特定任務。
  • 運作流程:Root Agent 判斷輸入類型後分派任務,子代理執行後回傳結果,Root Agent 再整合並回覆給使用者。

優點

  • 模組化:每個子代理專注單一領域,便於維護與擴展。
  • 支援複雜任務:多代理協作能處理多步驟或非結構化任務。
  • 彈性高:可針對不同子代理配置不同模型或工具,逐一優化。

限制

  • 開發與維護成本較高,需要設計代理間協作邏輯。
  • 代理間通訊可能增加延遲與複雜性。

實際測試截圖

  • hello_agent
    https://ithelp.ithome.com.tw/upload/images/20250930/20168456qGcLhkeqAA.png
  • weather_agent
    https://ithelp.ithome.com.tw/upload/images/20250930/20168456933KWrHvdx.png

上一篇
【Day 15】 Google ADK 工具型(Tool) 與 子代理(Sub Agent) 的比較
下一篇
【Day 17】小結
系列文
Multi-Agent 實戰:開發多代理智慧小幫手17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言