본문 바로가기
Agentic AI/Google ADK

5. G-ADK Tool 활용[3] - Custom Open API Tool (Python requests 함수 직접 구현)

by 아톨 2026. 10. 10.

실제 외부 날씨 API(OpenWeatherMap, Open-Meteo)를 호출하는 파이썬 함수를 작성하고, 이를 에이전트의 Custom Tool로 등록하는 방식입니다.

1. 주요 동작 방식

2단계 API 연동 구조를 가집니다. 사용자가 도시 이름을 입력하면, 먼저 위도/경도를 찾아주는 get_coordinates 함수를 거친 후, 해당 좌표를 이용해 OpenWeatherMap API에서 실시간 날씨 JSON 데이터를 받아옵니다. ADK는 이 전체 과정을 하나의 get_real_current_weather 툴로 인식하여 필요할 때 자동으로 실행합니다.

2. 코드 라인별 상세 해설

  • get_coordinates(location: str) (위경도 변환 함수)
    • Open-Meteo Geocoding API를 사용해 입력된 도시 이름(예: "서울")을 경도(longitude)와 위도(latitude) 좌표로 변환합니다.
    • 검색 결과가 없을 경우 ValueError를 발생시켜 예외를 처리합니다.
  • get_real_current_weather(city_name: str) -> Dict[str, Any] (핵심 툴 함수)
    • Docstring & Type Hint: city_name (str) 입력과 Dict[str, Any] 반환 타입을 명확히 지정하여 LLM이 함수의 입출력 구조를 파악할 수 있게 합니다.
    • 앞서 얻은 위도/경도와 OPEN_WEATHER_API_KEY를 파라미터로 결합하여 OpenWeatherMap 엔드포인트([https://api.openweathermap.org/data/2.5/weather](https://api.openweathermap.org/data/2.5/weather))로 HTTP GET 요청을 보냅니다.
    • API 호출 성공 시 원본 JSON 데이터 전체를 반환하고, 실패 시 LLM이 오류 원인을 이해할 수 있도록 디버깅용 예외 메시지를 전달합니다.
  • real_weather_agent 및 instruction
    • tools=[get_real_current_weather]를 통해 직접 만든 함수를 에이전트에 장착합니다.
    • 프롬프트 응답 가이드: Tool이 복잡한 JSON 구조를 반환했을 때, LLM이 그 중 어떤 필드(weather[0].description, main.temp)를 추출하여 사용자에게 최종적으로 답변해야 하는지 구체적인 후처리 지침을 제공합니다.
 
    import os
    import requests
    from typing import Dict, Any
    from dotenv import load_dotenv
    from google.adk import Agent

    # 1. 환경 설정
    load_dotenv(override=True)



    # --- API 키 및 설정 ---
    # OpenWeatherMap 무료 API 키를 발급
    OPEN_WEATHER_API_KEY = os.getenv("OPEN_WEATHER_API_KEY", "")

    # 2. 좌표만들기
    def get_coordinates(location:str):
        """도시 이름을 받아 Open-Meteo Geocoding API에서 위도(latitude)와 경도(longitude)를 조회한다."""
        params = {
            "name":location,
            "count":1,
            "language":"en",
            "format":"json",
        }
        response = requests.get(url, params=params, timeout=10)
        # response:  <Response [200]>
        response.raise_for_status()
        data = response.json()

        if not data.get("results"):
            raise ValueError(f"도시를 찾을 수 없습니다. {location}")
        result = data["results"][0]
        return {
            "name":result["name"],
            "latitude":result["latitude"],
            "longitude":result["longitude"],
            "country":result.get("country",""),
        }
       
    # 3. [핵심] 실제 API를 호출하는 파이썬 함수를 'Tool'로 정의
    def get_real_current_weather(city_name:str)->Dict[str, Any]:
        """
        Open Weather API를 사용해 '현재' 날씨 정보를 JSON으로 조회합니다.
        Args:
            city_name (str): 도시 이름.
        Returns:
            Dict[str, Any]: API에서 반환된 원본 JSON 날씨 정보
        """
        city_key = get_coordinates(city_name)
        latitude=city_key["latitude"]
        longitude=city_key["longitude"]

        params = {        
            "lat":latitude,
            "lon":longitude,        
            "appid":OPEN_WEATHER_API_KEY,
        }
       
        try:
            # "https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={API key}"
            response = requests.get(endpoint, params=params)
            response.raise_for_status() # 오류 발생 시 예외 처리
            return response.json()
        except requests.RequestException as e:
            # LLM이 오류를 이해할 수 있도록 명확한 에러 메시지 반환
            raise ValueError(f"API 호출 실패: {e}")

    # 4. Agent에 'tools'로 등록
    real_weather_agent = Agent(
        model=os.getenv("GOOGLE_MODEL", "gemini-3.5-flash"),
        name ="real_weather_agent",
        description="실제 OpenWeather API로 날씨를 알려주는 에이전트입니다.",
        instruction="""
        사용자가 날씨를 물어보면, 'get_real_current_weather' Tool을 이용해 현재 날씨를 알려주세요.
        Tool이 JSON을 반환하면, 그 중에서 'weather'[0]['description'] (날씨 설명)과
        'main'['temp'] (현재 온도)를 뽑아서 자연스럽게 설명해주세요.
        """,
        tools=[get_real_current_weather]
    )
 
    root_agent = real_weather_agent
 

 

 

 

반응형