😺

今更ながらadkを使ってみた

に公開

今回はadkを使ってみました。すでに提供が開始されてからかなり日数が立っていますが使っていなかったことに気づきまして、今回Qucikstartを試してみました(エージェントを実装できる方法が他に色々ありすぎて漏れていましたw)。

adkとは?

adkとはAgent Development Kitの省略であり、エージェントを開発・デプロイするためのフレームワークになります。GeminiやGoogleのエコシステムに最適化されてはいますが利用するモデルについてはそれ以外のものも利用でき、他のフレームワークと互換性があるものとなっています。利用用途としてはadkをつかってエージェントをくみ、Vertex AI Agent EngineやCloud Run、GKEなどにデプロイされて運用されることが多いかと思います。また、もちろんMCPやfunction toolなどにも対応されており、今日のエージェントを取り巻く重要な要素は網羅されています。今回はQuickstartを通してまずは使い方を確認してみました。

https://google.github.io/adk-docs/

早速使ってみる

今回はQuickstartを利用して進めてみます。

https://google.github.io/adk-docs/get-started/python/

インストール

adkはコマンドラインツールとして利用できます。普段uvを利用しているので以下のようにしてインストールしました。

uv tool install google-adk

プロジェクトの作成

adkコマンドを使うとプロジェクトを簡単に作るこtができます。今回はquickstartと言う名前でプロジェクトを作ろうと思います。

adk create quickstart

このコマンドを実行すると実行フォルダにquickstartと言う名前でフォルダが作成され、その中に最小限のサンプル構成でエージェントが利用できる状態にされます。ファイル構成は以下のようになっています。

quickstart/
    agent.py
    .env
    __init__.py

なお、初期化時にはGeminiをGoogle AI Studioから利用するかVertex AI経由で利用するか聞かれます。私は前者を選択してAPIキーを指定しました。``

作成されたquickstartをみるといくつかファイルがあります。.envには先ほど設定したGeminiのAPIキーが、agent.pyには以下のサンプルコードが含まれています。

agent.py
from google.adk.agents.llm_agent import Agent


root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='A helpful assistant for user questions.',
    instruction='Answer user questions to the best of your knowledge',
)

サンプルコードだけでも実行できるので早速使ってみみましょう。以下のコマンドを実行するとやり取りをすることができます。

adk run quickstart

# 結果
## 起動時のログは省略
[user]: What is your profession?
[root_agent]: I am a large language model, an AI assistant. I don't have a profession in the human sense. My purpose is to help users by providing information and completing tasks.
[user]: What is large language model?
[root_agent]: A Large Language Model (LLM) is a type of artificial intelligence (AI) program that has been trained on a massive amount of text and code data. Its primary function is to understand, generate, and process human-like language.

Here's a breakdown of what that means:

1.  **"Large"**: This refers to two main things:
    *   **Parameters**: LLMs have billions, sometimes hundreds of billions, of parameters. These are the values the model learns during training that allow it to make predictions. More parameters generally mean the model can learn more complex patterns.
    *   **Training Data**: They are trained on incredibly vast datasets, often comprising a significant portion of the internet's text (books, articles, websites, conversations, code, etc.).

2.  **"Language Model"**: This means its core task is to model language. Essentially, it learns the statistical relationships between words and phrases. When given a prompt, it tries to predict the most probable next word or sequence of words based on everything it has learned.

**How they work (simplified):**

*   **Training**: During training, an LLM processes huge amounts of text. It learns grammar, facts, reasoning abilities, writing styles, and even some common sense from this data. It doesn't "understand" in a human sense, but rather it identifies complex patterns and relationships within the language.
*   **Prediction**: When you ask it a question or give it a prompt, it takes your input, processes it based on its learned patterns, and then generates a response by predicting the most statistically appropriate next word, and then the next, and so on, until it forms a complete answer.

**Key Capabilities and Applications:**

*   **Answering Questions**: Providing information on a wide range of topics.
*   **Generating Text**: Writing articles, summaries, creative stories, poems, code, emails, etc.
*   **Summarization**: Condensing long documents or conversations into shorter, key points.
*   **Translation**: Translating text from one language to another.
*   **Conversation**: Engaging in natural-sounding dialogue (like chatbots).
*   **Code Generation**: Writing or debugging programming code.
*   **Sentiment Analysis**: Determining the emotional tone of a piece of text.

I, for example, am a large language model.

結果をみると、[user]の部分でユーザの入力が受け付けられ、[root_agent]で返答が帰ってきていました。

ツールの実装

先ほどの例では素のGeminiに話しかけている感じになっているので、次はツールを作ってみます。Quickstartにある時間を尋ねるものと、ランダムでくじを引いてメッセージをもらえるツールの二つを追加してみます。

agent.py
from random import choice
from google.adk.agents.llm_agent import Agent

def get_current_time(city: str) -> dict:
    """Returns the current time in a specified city."""
    return {"status": "success", "city": city, "time": "10:30 AM"}


def get_messages() -> dict:
    """This is a fortune telling that returns random messages."""
    messages = [
        "Tomorrow will be a good day",
        "Tomorrow, be extra considerate to your friends."
    ]
    return {
        "status": "success",
        "message": choice(messages),
    }


root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='A helpful assistant for user questions.',
    instruction='Answer user questions to the best of your knowledge',
    tools=[get_current_time, get_messages]
)

ツールの実装ですが、通常の関数を実装する時と同じように実装します。docstringはツールの利用目的のために明確に記載しておきましょう。get_current_timeは固定時間を返すようにし、get_messagesでは事前定義した二つのメッセージのいずれかが帰るようにしています。

def get_current_time(city: str) -> dict:
    """Returns the current time in a specified city."""
    return {"status": "success", "city": city, "time": "10:30 AM"}


def get_messages() -> dict:
    """This is a fortune telling that returns random messages."""
    messages = [
        "Tomorrow will be a good day",
        "Tomorrow, be extra considerate to your friends."
    ]
    return {
        "status": "success",
        "message": choice(messages),
    }

ツールをエージェントから実行できるようにするにはtoolsに関数一覧を指定します。

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='A helpful assistant for user questions.',
    instruction='Answer user questions to the best of your knowledge',
    tools=[get_current_time, get_messages]  # <- こちらを追加
)

それでは早速こちらを実行してみましょう。

adk run quickstart

# 結果
## 起動時のログは省略
[user]: What time is it in Japan?
[root_agent]: The current time in Tokyo, Japan is 10:30 AM.
[user]: What time is it in New York?
[root_agent]: The current time in New York is 10:30 AM.
[user]: Perform fortune telling
[root_agent]: Tomorrow, be extra considerate to your friends.
[user]: Perform fortune telling
[root_agent]: Tomorrow will be a good day.

結果をみると、まずは時刻については10:30 AMに固定されているのが確認できます。実際にはdatetimeモジュールなどを使ってリアルタイムの情報を取るべきですが、今回は固定時間にしており、動作としては所望の内容となっています。またPerform fortune tellingとしてランダムなメッセージを要求したところ、事前に定義したメッセージのいずれかを返してくれることを確認できました。

サブエージェントを実装してみた

Quickstartにはないですが、サブエージェントを使ってみました。今回は先ほど定義した2つの機能をroot_agent経由ではなくそのサブエージェントから呼び出すようにしてみました。

agent.py
from random import choice
from google.adk.agents.llm_agent import Agent
from google.adk.agents import LlmAgent

def get_current_time(city: str) -> dict:
    """Returns the current time in a specified city."""
    return {"status": "success", "city": city, "time": "10:30 AM"}


def get_messages() -> dict:
    """This is a fortune telling that returns random messages."""
    messages = [
        "Tomorrow will be a good day",
        "Tomorrow, be extra considerate to your friends."
    ]
    return {
        "status": "success",
        "message": choice(messages),
    }


tool_call_agent = LlmAgent(
    model='gemini-2.5-flash',
    name="tool_call_agent",
    description="Assistant who is specialized in callint tools.",
    instruction="Call tools based on the request from parent agent.",
    tools=[get_current_time, get_messages],
)

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='A helpful assistant for user questions.',
    instruction='Answer user questions to the best of your knowledge',
    sub_agents=[tool_call_agent]
)

まずはサブエージェントを定義します。基本的な定義は同じですが、google.adk.agents.LlmAgentを利用して定義します。

tool_call_agent = LlmAgent(
    model='gemini-2.5-flash',
    name="tool_call_agent",
    description="Assistant who is specialized in callint tools.",
    instruction="Call tools based on the request from parent agent.",
    tools=[get_current_time, get_messages],
)

次に、サブエージェントをルートエージェントに紐付けます。sub_agentsにリストとして定義することでサブエージェントを登録できます。なお、ツールはサブエージェントから呼び出されるのでルートエージェントからは削除しています。

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='A helpful assistant for user questions.',
    instruction='Answer user questions to the best of your knowledge',
    sub_agents=[tool_call_agent]  # <- 追加したところ
)

それではこちらを実行してみます。結果を見ると、先ほどまでは[root_agent]が返答していましたが、今回は[tool_call_agent]が返答しています。[root_agent]はツールの呼び出しができないので、ツールを呼び出すためにサブエージェントに依頼していることになります。

adk run quickstart

# 結果
## 起動時のログは省略
[user]: What time is it in Tokyo?
[tool_call_agent]: The current time in Tokyo is 10:30 AM.
[user]: Perform fortune telling
[tool_call_agent]: Tomorrow, be extra considerate to your friends.

まとめ

今回はadkを利用してQuickstartを通して簡単な使い方をキャッチアップしてみました。実際にはもっと複雑な実装がなされ、MCPなどと組み合わせることでサービスを構築することになります。次回以降でMCPとの連携を初め、Agent Engineへのデプロイなどを試してみようと思います。

Discussion