Title Image

Agent Development Kitを触ってみる #1

投稿日

つい最近公開されたAgent Development Kitを試してみようと思います。

この記事ではQuickstartとTutorialの2章までやっていきます。

Quickstart

まずは以下のQuickstartを試してみます。

環境構築

uvを使います。簡単に環境構築ができるので便利です。

以下のコマンドで環境を作ります。

uv init adk_test -p 3.11
cd adk_test
uv add google-adk

ファイルの作成

以下の手順でファイルを作っていきます。

まずはmulti_tool_agentというフォルダを作成し、__init__.pyを作ります。

mkdir multi_tool_agent/
echo "from . import agent" > multi_tool_agent/__init__.py

次に、multi_tool_agentの中にagent.pyを作り、以下を書き込みます。

multi_tool_agent/agent.py
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 AI StudioからAPIキーを取得します。

multi_tool_agent.envというファイルを作り、取得したAPIキーを以下の形式で貼り付けます。

multi_tool_agent/.env
GOOGLE_GENAI_USE_VERTEXAI=FALSE
GOOGLE_API_KEY={取得したAPIキー}

動かしてみる

以下のコマンドでWEBのUIが立ち上がります。

uv run adk web

この状態でブラウザからhttp://localhost:8000にアクセスすると以下のようなUIが表示されます。

UIを立ち上げた際の初期状態

左上の[Select an agent]から「multi_tool_agent」を選択すると以下のようなチャット画面が表示されます。

チャット画面

試しにニューヨーク(New York)の天気と時間を聞いた結果、以下のようになりました。天気と時間を取得できていることがわかります。

New Yorkの天気と時間を聞いた結果

次に、パリ(Paris)の天気と時間を聞いた結果は以下のようになりました。パリの時間と天気は取得できていないことがわかります。

Parisの天気と時間を聞いた結果

Quickstartは以上で終了です。コピー&ペーストだけでニューヨークの天気と時間を答えてくれるエージェントができました。

少し深掘り

以下のチュートリアルを見ながらQuickstartで何をしていたのかを見ていきます。

ツールの定義

例として、agent.pyの中では以下の部分で天気情報を取得するツールの定義を行っています。

multi_tool_agent/agent.py (一部抜粋)
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.",
        }

文字列で以下の情報を示すことが重要です。

LLMはこの文字列を基にツールを使用するため、適切にツールの説明を記述しなければなりません。

エージェントの定義

エージェントの定義をします。エージェントのインスタンスを作成するにはfrom google.adk.agents import AgentAgentをインポートします。

Quickstartでエージェントの定義に該当する部分は以下の部分です。

multi_tool_agent/agent.py (一部抜粋)
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],
)

重要な引数は以下の通りです。

これらの引数を書くうえで重要な点は以下の2つです。

LiteLlm

ADKに統合されているLiteLLMを使うことで、様々なLLMをベースとしたAgentを定義できます。

LiteLLMを使う前に以下のコマンドでインストールします。

uv add litellm

おそらく統合元のLiteLLMで利用可能なモデルは全て使うことができると思われます。以下にLiteLLMで利用可能なProviderの一覧を見ることができます。OpenAIをはじめ、Hugging FaceやOllamaなど、様々なインターフェースがサポートされています。

LiteLLMをimportするには、以下の文を書きます。

from google.adk.models.lite_llm import LiteLLM

さらに、Agentを定義している部分を以下のように書き換えます。このとき、必要に応じてAPIキーなどを環境変数に置いておく必要がありますpython-dotenv等を用いて.envファイルで管理できるとよさそうです。

また、try...except構文を使うことで、エラーハンドリングすることが推奨されているようです。

try:
    root_agent = Agent(
        name="weather_time_agent",
        model=LiteLlm("provider/model_name"),
        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],
    )
except Exception as e:
    print(f"Counld not create Agent. Error: {e}")

コードベースで対話する

Quickstartでは、WebUIの機能によって(?)自動でSessionの管理などを行ってくれていたのですが、コードベースで書く場合はSessionやRunnerを自分で作成して管理します。

Session

各セッションにおける会話を管理し履歴や状態を保存することができます。

セッションを扱うためには、InMemorySessionServiceを使います。以下の文でimportできます。

from google.adk.sessions import InMemorySessionService

セッションは以下のようにして作成できます。

session_service = InMemorySessionService()

session = session_service.create_session(
    app_name="weather_time_agent",
    user_id="user_1",
    session_id="session_1"
)

チュートリアルに記載されている各引数は以下のようになっています。 app_name: (必須)アプリケーションの名前 user_id: (必須)ユーザーのID(文字列) session_id: セッションのID(文字列)

Runner

Runnerはユーザ入力の受け取りやLLMやツールの呼び出し、セッションなどを管理します。

Runnerを使うには以下の文でimportします。

from google.adk.runners import Runner

Runnerは以下のようにして作成できます。

runner = Runner(
    agent=root_agent,
    app_name="weather_time_agent",
    session_service=session_service,
)

チュートリアルに記載されている各引数は以下のようになっています。ここに書かれているのは全て必須です。 agent: エージェント app_name: アプリケーション名 session_service: セッションを管理するインスタンス(InMemorySessionServiceなど)

なぜSessionとRunnerの両方にapp_nameの引数があるのかはわかりませんが、チュートリアルでは同じ名前を入れていました。

エージェントと対話する

ここまでの作業を基に、エージェントとやり取りをするためのヘルパー関数を定義します。非同期関数となっていますが、これはLLMなどの外部APIを叩く操作に時間がかかるためです。非同期関数にすることで他の処理をブロッキングすることなく処理することができます。

import asyncio
from google.genai import types

async def call_agent_async(query: str):
    """Sends a query to the agent and prints the final response."""
    print(f"\n>>> User Query: {query}")

    content = types.Content(role='user', parts=[types.Part(text=query)])

    final_response_text = "Agent did not produce a final response." # Default

    # 最終的な回答が得られるまで反復
    async for event in runner.run_async(user_id="user_1", session_id="session_1", new_message=content):
        # 以下をアンコメントすることで全てのログを出力可能
        # print(f"  [Event] Author: {event.author}, Type: {type(event).__name__}, Final: {event.is_final_response()}, Content: {event.content}")

        # is_final_response() で最後のレスポンスかを判定
        if event.is_final_response():
            if event.content and event.content.parts:
                # 最初のpartに応答があると仮定
                final_response_text = event.content.parts[0].text
            elif event.actions and event.actions.escalate: # 応答を得られない場合
                final_response_text = f"Agent escalated: {event.error_message or 'No specific message.'}"
            break # 終了

    print(f"<<< Agent Response: {final_response_text}")

上記の関数を実行する以下のプログラムを実行します。

async def run_conversation():
    await call_agent_async("What is the weather like in London?")
    await call_agent_async("How about Paris?")
    await call_agent_async("Tell me the weather in New York")

await run_conversation()

実行結果は以下のようになりました。しっかり使えていそうです。

>>> User Query: What is the weather like in London?
<<< Agent Response: I am sorry, I cannot get the weather information for London. The weather information for 'London' is not available.

>>> User Query: How about Paris?
<<< Agent Response: I am sorry, I cannot get the weather information for Paris. The weather information for 'Paris' is not available.

>>> User Query: Tell me the weather in New York
<<< Agent Response: OK. The weather in New York is sunny with a temperature of 25 degrees Celsius (41 degrees Fahrenheit).

コードベースでの対話(まとめ)

ここまで、コードベースでの対話方法を説明していきました。ここまでで、ツールを使うことのできるLLMエージェントを作成できるようになりました。

次回の記事では、エージェントのチームを作る方法などを見ていきます。

一連のプログラムは以下を参照してください。

一連のプログラム

Jupyterなどのノートブックで実行することを想定しています。

同階層にノートブックファイルと.envを置いてください。

APIキーのロード

必要なAPIキーと環境変数名などはこのページから調べてください。

Gemini(Google AI Studio)の場合はGEMINI_API_KEYが必要です。Quickstartにおいて、GOOGLE_API_KEYに書いたAPIキーを以下のように書いてください。

.env
GEMINI_API_KEY = {APIキー}

以下のコードで.envを読み込みます。

from dotenv import load_dotenv
load_dotenv()

エージェントが使うツールの定義

以下のコードでエージェントが使うツールを定義します。この部分はQuickstartと同じです。

import datetime
from zoneinfo import ZoneInfo

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}

エージェントの定義

LiteLLMを使ってQuickstartと同じようなエージェントを定義します。

from google.adk.agents import Agent
from google.adk.models.lite_llm import LiteLlm

try:
    root_agent = Agent(
        name="weather_time_agent",
        model=LiteLlm("gemini/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],
    )
except Exception as e:
    print(f"Counld not create Agent. Error: {e}")

セッションサービスの作成

セッションを管理するためにInMemorySessionServiceのインスタンスを作ります。

変数sessionは今後使いませんが、user_idとsession_idで紐づけてエージェントを実行するため、session_service.create_sessionの実行は必須です。

from google.adk.sessions import InMemorySessionService

session_service = InMemorySessionService()

session = session_service.create_session(
    app_name="weather_time_agent",
    user_id="user_1",
    session_id="session_1"
)

Runnerの作成

以下のコードでRunnerを作成します。

from google.adk.runners import Runner

runner = Runner(
    agent=root_agent,
    app_name="weather_time_agent",
    session_service=session_service,
)

ヘルパー関数の定義

クエリを与えてエージェントを実行するためのヘルパー関数を以下のように定義します。

import asyncio
from google.genai import types

async def call_agent_async(query: str):
    """Sends a query to the agent and prints the final response."""
    print(f"\n>>> User Query: {query}")

    # Prepare the user's message in ADK format
    content = types.Content(role='user', parts=[types.Part(text=query)])

    final_response_text = "Agent did not produce a final response." # Default

    # Key Concept: run_async executes the agent logic and yields Events.
    # We iterate through events to find the final answer.
    async for event in runner.run_async(user_id="user_1", session_id="session_1", new_message=content):
        # You can uncomment the line below to see *all* events during execution
        # print(f"  [Event] Author: {event.author}, Type: {type(event).__name__}, Final: {event.is_final_response()}, Content: {event.content}")

        # Key Concept: is_final_response() marks the concluding message for the turn.
        if event.is_final_response():
            if event.content and event.content.parts:
                # Assuming text response in the first part
                final_response_text = event.content.parts[0].text
            elif event.actions and event.actions.escalate: # Handle potential errors/escalations
                final_response_text = f"Agent escalated: {event.error_message or 'No specific message.'}"
            # Add more checks here if needed (e.g., specific error codes)
            break # Stop processing events once the final response is found

    print(f"<<< Agent Response: {final_response_text}")

エージェントの実行

以下のコードでエージェントを実行します。

async def run_conversation():
    await call_agent_async("What is the weather like in London?")
    await call_agent_async("How about Paris?") # Expecting the tool's error message
    await call_agent_async("Tell me the weather in New York")
    await call_agent_async("What time is it in New York?")

# Execute the conversation using await in an async context (like Colab/Jupyter)
await run_conversation()

一連のコードを実行して得られる結果は以下のようになりました。

ニューヨークの天気や時間を正しく回答していて、ツールによって情報を得られない場合はその旨を表示しています。

>>> User Query: What is the weather like in London?
<<< Agent Response: I am sorry, I cannot get the weather information for London. There was an error.

>>> User Query: How about Paris?
<<< Agent Response: I am sorry, I cannot get the weather information for Paris. There was an error.

>>> User Query: Tell me the weather in New York
<<< Agent Response: OK. The weather in New York is sunny with a temperature of 25 degrees Celsius (41 degrees Fahrenheit).


>>> User Query: What time is it in New York?
<<< Agent Response: The current time in New York is 2025-04-20 11:30:19 EDT-0400.

おわりに

ADKの最低限の動かし方を学びました。次回は複数のエージェントを使ったエージェントチームの作成などをやります。