nikkie-ftnextの日記

イベントレポートや読書メモを発信

Agent Development Kit でどのようなプロンプトが Gemini に送られているのか知りたくログを読む(AgentToolを使うYouTube Shorts Agentを例に)

はじめに

七尾百合子さん、お誕生日 152日目 おめでとうございます! nikkieです。

Agent Development Kit (ADK) でロギング1やOpenTelemetry2を頻繁に素振りしてきましたが、いよいよどのようなプロンプトがGeminiに送られているのか見ていきます。

目次

YouTube Shorts Agent

当ブログでADKの素振りの際に大変お世話になっております。

プロンプトを読むうえで確認しておきたいエージェントの構成はこちら(理解優先の簡略版です)

root_agent = LlmAgent(
    model="gemini-2.5-pro",
    # 省略
    tools=[
        AgentTool(scriptwriter_agent),
        AgentTool(visualizer_agent),
        AgentTool(formatter_agent),
    ],
)

ログ(やテレメトリ)を見ると、root_agentは次のような軌跡をたどっています。

  1. System Instruction + ツール定義 + userからの「write me a script on how to build AI agents」でroot_agent呼び出し
    • -> ShortsScriptwriter 呼び出し
  2. ShortsScriptwriterの返したテキストをコンテキストに追加して、root_agent再呼び出し
    • -> ShortsVisualizer 呼び出し
  3. ShortsVisualizerの返したテキストをコンテキストに追加して、root_agent再呼び出し
    • -> ConceptFormatter 呼び出し
  4. ConceptFormatterの返したテキストをコンテキストに追加して、root_agent再呼び出し
    • -> ユーザに返答する出力

軌跡の理解には、ADK User Groupの資料が参考になりました。

ログをファイルに出力するために、agent.pyに次のようなコードを追加しています。

logging.basicConfig(
    force=True,  # adk webで設定されてしまうルートロガーの設定を無に帰す
    level=logging.DEBUG,
    format="%(asctime)s | %(levelname)s | %(name)s:%(funcName)s:%(lineno)d - %(message)s",
    filename="agent.log"
)
logging.getLogger().handlers[0].addFilter(logging.Filter("google_adk"))

root_agentのプロンプト

一番最初のログがroot_agentのプロンプトをつかみやすいと思います。

LLM Request:
-----------------------------------------------------------
System Instruction:
You are the Shorts Content Orchestrator. Your role is to manage the creation of YouTube Shorts content by coordinating specialized child agents (ScriptWriter, VisualCreator, MarkdownFormatter).

< https://github.com/google/adk-docs/blob/551e563ebd9dee647e741c61cd3a2a6b27fa93ce/examples/python/agent-samples/youtube-shorts-assistant/shorts_agent_instruction.txt の内容 >

You are an agent. Your internal name is "youtube_shorts_agent".

 The description about you is "You are an agent that can write scripts, visuals and format youtube short videos. You have subagents that can do this"
-----------------------------------------------------------
Contents:
{"parts":[{"text":"write me a script on how to build AI agents"}],"role":"user"}
-----------------------------------------------------------
Functions:
ShortsScriptwriter: {'request': {'type': <Type.STRING: 'STRING'>}} 
ShortsVisualizer: {'request': {'type': <Type.STRING: 'STRING'>}} 
ConceptFormatter: {'request': {'type': <Type.STRING: 'STRING'>}} 
-----------------------------------------------------------

「You are an agent.」以降は LlmRequestProcessor によってnamedescriptionから追加されていました。
https://github.com/google/adk-python/blob/v1.11.0/src/google/adk/flows/llm_flows/identity.py#L37-L39
冒頭の「You are the Shorts Content Orchestrator.」と近い内容がADKにより自動で入ることで、『LLMのプロンプトエンジニアリング』36章で見かけた「サンドイッチ」を実現できているように思えます。

Functionsにあるツール(AgentTool)とは別に、「System Instruction」(LlmAgentのinstruction)にもAgentToolを匂わす情報を入れているのが意外でした。
function callingの例の素振りでは、ツールの情報を追加するだけで、システムプロンプトでの言及までやっていませんでした。
この例ではinstructionをファイルに外出しして、協働するエージェントや、どのような手順で進めるかをはっきりと記述しています(協働するエージェントは名前を合わせてあげるともっとよさそうです)

AgentTool呼び出し

root_agentがツールを呼び出すとき、このようなJSONが返されています。

{
    "parts": [
        {
            "thought_signature": "<略>",
            "function_call": {
                "args": {
                    "request": "Write a script for a YouTube Short on how to build AI agents. The script should be engaging, easy to understand for a beginner audience, and approximately 30-45 seconds long. It needs a strong hook to grab attention, a simplified explanation of the steps involved, and a clear call to action."
                },
                "name": "ShortsScriptwriter"
            }
        }
    ],
    "role": "model"
}

これをADK側でツールのAgentに送ります。

LLM Request:
-----------------------------------------------------------
System Instruction:
You are 'Pro Short', 
< https://github.com/google/adk-docs/blob/551e563ebd9dee647e741c61cd3a2a6b27fa93ce/examples/python/agent-samples/youtube-shorts-assistant/scriptwriter_instruction.txt の内容 >

You are an agent. Your internal name is "ShortsScriptwriter".
-----------------------------------------------------------
Contents:
{"parts":[{"text":"Write a script for a YouTube Short on how to build AI agents. The script should be engaging, easy to understand for a beginner audience, and approximately 30-45 seconds long. It needs a strong hook to grab attention, a simplified explanation of the steps involved, and a clear call to action."}],"role":"user"}
-----------------------------------------------------------
Functions:

-----------------------------------------------------------

ツールのAgentが返したレスポンスは、root_agentのコンテキストに入ります。

AgentToolとなっているLlmAgentは、root_agentが「write me a script on how to build AI agents」とユーザからのリクエストを受けたことは知らないわけですね。
root_agentのコンテキストを消費しないサブエージェントになっていそうです。

終わりに

AgentToolを使ったADKのエージェントのログを読んだところ、プロンプトやLLMのコンテキストについて以下が分かりました

  • root_agentは、ユーザ入力や、AgentToolの呼び出し・返答内容、すべてをコンテキストに持つ
  • AgentTool(のLlmAgent)はroot_agentから送られてきたプロンプトにだけ返答する
    • root_agentとユーザのやり取りは知らない
  • ADKでは、nameinstruction冒頭に書くことで、システムプロンプトにおけるサンドイッチができる

宿題事項も挙げておきます

  • ログのFunctionsがそのままGeminiに入力されているのだろうか?
    • Gemini APIへの生の入力を見たい
    • (「LLMアプリケーションにおいて全てとも言えるプロンプトを見たい」というニーズに対しては、ADKは何層も余計なレイヤを入れて把握しにくくしている印象)
  • ADKのLlmRequestProcessorの実装に、参考論文や比較実験といった根拠はあるのだろうか?
    • descriptionで謎の1字下げはなぜやっている?
    • サンドイッチとして使えればメリットになりそうだが、実装の詳細を理解していないと罠にもなりそう(間違えるほうがむしろ簡単になっちゃってるかも)
  • 今回ログでたびたび見かけた event_generator が少し気になる

P.S. エージェント実装はPythonよりJavaScript

調査不足なのかもですが、ADKの情報、全然見かけないんですよね


  1. ADKが依存するgoogle-genaiにOpenTelemetryの計装を実装したライブラリがあることを利用します