nikkie-ftnextの日記

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

AG-UI でエージェントに UI のテーマカラーを変更させる(Agent Development Kit (Python) & CopilotKit)

はじめに

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

AG-UI で、あの日かいま見た未来に挑みます(※そんなに大層な取り組みではないです)

目次

見なよ... あの日の未来を...

単なる Chat UI ではありません。
「UIを緑色にして」と伝えると、吹き出しの色やアイコンの色を緑色にしてくれるんです!
もちろん他の色にもできます。

先日の Chat UI を少しだけ拡張しました1(これでもまだチュートリアルの範囲です)

CopilotKit の UI を操作する ADK エージェント

GPT-5.2 deep research レポートと、調査中に見つけてきた Strands Agents 版の記事を元に取り組みました。

AG-UI https://docs.ag-ui.com/introduction をCopilotKit & ADKでPythonで触ってみています。
Chat UIはできたのですが、
https://docs.copilotkit.ai/adk/quickstart?agent=bring-your-own
ここからAgentが画面に変更をもたらすような実装が可能なのか知りたいです。
公式ドキュメントベースに調査してください

(画像込みで渡して deep research を依頼しました)

エージェントに tool を持たせる

ADK 側には tool を追加します。
https://google.github.io/adk-docs/tools-custom/function-tools/

+def set_theme_color(theme_color: str) -> None:
+    """Request a UI theme color change.
+
+    Args:
+        theme_color: CSS color (hex, name, or rgb) that the UI should apply
+    """
+    return None
+
+
root_agent = LlmAgent(
    name="assistant",
    model="gemini-2.5-flash",
    instruction="Be helpful and fun!",
+    tools=[set_theme_color],
)

LlmAgentは呼び出す(tool use)必要があるので、型ヒントや docstring でどんな tool かを示しています。
呼び出した後はフロントエンド(CopilotKit)側で処理をするので、tool の処理は何も実装していません。

フロントエンド(CopilotKit側)にも同名 tool

React の知識が欠乏しているので、ぼんやりとした理解なのですが

  • useState – React
    • themeColor(state 変数)の初期値を設定、set 関数も用意
    • returnする<main>要素のstyleで参照(CSS 変数2!)
  • useFrontendTool
    • ADK エージェントが呼ぶ set_theme_color と同じシグネチャの tool がフロントエンドにも!
    • handlerで、themeColorを更新している!
    • -> <main>要素のstyleが変わって、UIが変わる!(のだと思っています)

ADK 側の動作ログより

「UIを緑色にして」が届きました

LLM Request:
-----------------------------------------------------------
System Instruction:
Be helpful and fun!

You are an agent. Your internal name is "assistant".
-----------------------------------------------------------
Config:
{'http_options': {'headers': {'x-goog-api-client': 'google-adk/1.22.1 gl-python/3.13.8', 'user-agent': 'google-adk/1.22.1 gl-python/3.13.8'}}, 'tools': [{}]}
-----------------------------------------------------------
Contents:
{"parts":[{"text":"こんにちは。何をしてくれますか?"}],"role":"user"}
{"parts":[{"text":"こんにちは!私はAIアシスタントです。\n\nできることの一部をご紹介します。\n\n*   **情報の検索**: 質問に答えたり、調べ物をしたりできます。\n*   **文章の作成**: ストーリー、詩、コード、スクリプト、音楽作品、メール、手紙など、さまざまな種類のクリエイティブなコンテンツを作成できます。\n*   **要約**: 長い文章を短く要約できます。\n*   **翻訳**: いろいろな言語に翻訳できます。\n*   **プログラミングのお手伝い**: コードを書いたり、デバッグしたりするのを手伝えます。\n*   **UIテーマカラーの変更**: 画面のテーマカラーを好きな色に変えることもできます。例えば、「UIを青色にして」とお願いしてみてください。\n\n何かお手伝いできることはありますか?"}],"role":"model"}
{"parts":[{"text":"UIを緑色にして"}],"role":"user"}
-----------------------------------------------------------
Functions:
set_theme_color: {'theme_color': {'type': <Type.STRING: 'STRING'>}} 
-----------------------------------------------------------

ADK エージェントが set_theme_color 呼び出し。
対応するように、フロントエンドの tool 呼び出しもされて、画面が変わっているんですかね?(要調査)

LLM Response:
-----------------------------------------------------------
Text:
None
-----------------------------------------------------------
Function calls:
name: set_theme_color, args: {'theme_color': 'green'}
-----------------------------------------------------------
Raw response:
(略)
-----------------------------------------------------------

Python 側の tool 呼び出し結果が ADK エージェントに送られています

Contents:
{"parts":[{"text":"こんにちは。何をしてくれますか?"}],"role":"user"}
{"parts":[{"text":"こんにちは!私はAIアシスタントです。\n\nできることの一部をご紹介します。\n\n*   **情報の検索**: 質問に答えたり、調べ物をしたりできます。\n*   **文章の作成**: ストーリー、詩、コード、スクリプト、音楽作品、メール、手紙など、さまざまな種類のクリエイティブなコンテンツを作成できます。\n*   **要約**: 長い文章を短く要約できます。\n*   **翻訳**: いろいろな言語に翻訳できます。\n*   **プログラミングのお手伝い**: コードを書いたり、デバッグしたりするのを手伝えます。\n*   **UIテーマカラーの変更**: 画面のテーマカラーを好きな色に変えることもできます。例えば、「UIを青色にして」とお願いしてみてください。\n\n何かお手伝いできることはありますか?"}],"role":"model"}
{"parts":[{"text":"UIを緑色にして"}],"role":"user"}
{"parts":[{"function_call":{"args":{"theme_color":"green"},"name":"set_theme_color"},"thought_signature":"(略)"}],"role":"model"}
{"parts":[{"function_response":{"name":"set_theme_color","response":{"result":null}}}],"role":"user"}

この tool 呼び出し結果を受けた返答が「UIを緑色に変更しました。いかがでしょうか?」です。

フロントエンドで赤いメッセージが出ているのですが、

No function call event found for function responses ids:

DEBUG | google_adk.google.adk.flows.llm_flows.contents:_rearrange_events_for_latest_function_response:189 - No function call event found for function responses ids: {'adk-3867e3e5-d2c7-4497-aa2c-b48015fd9870'} in event list: (略)

「UIを緑色に変更しました。いかがでしょうか?」の後にフロントエンドから Event が届いているのですが、

Event(model_version=None, content=Content(
  parts=[
    Part(
      function_response=FunctionResponse(
        id='adk-3867e3e5-d2c7-4497-aa2c-b48015fd9870',
        name='set_theme_color',
        response={
          'result': None,
          'status': 'completed',
          'success': True
        }
      )
    ),
  ],
  role='user'
), (略))

その id が event list 内の function call にないので出たようです。
AG-UI というプロトコルの仕様を理解すると、直し方も分かるかもしれません(とはいえ、閉じて Chat を続けられました)

OpenAI DevDay 2023 で見た未来じゃん!

OpenAI DevDayのKeynoteアーカイブを見ました。エージェントが自然言語で作れる!アプリケーションにも組み込める! - nikkie-ftnextの日記

これ、フロントエンドでfunction calling使うと、GPTのレスポンスに対応して画面を変化させられるってことですよね。

このデモの衝撃がすごくて、Python でできる範囲で確認したりしました。

2023年の DevDay が示したエージェントによる UI 操作、AG-UI という実現方法がある(広まってきている)んですね。

終わりに

ADK (Python)・CopilotKit という構成で、Chat UI を通してエージェントにテーマカラー変更という UI 操作をさせられました!
未来ずら〜〜

AG-UI、CopilotKit(React)の知識が欠けており、思い描いたものをアプリケーション実装できる感覚はまだないですが、夢見た未来に近づいているので引き続き素振りしていこうと思います

コードの全体像はこちらです


  1. エージェントに UI を操作させられる??」を回収します
  2. ぜんぜん違うところで出会ってました:Vivliostyle にコラムを追加する(「Vivliostyleで技術同人誌を始めよう」より) - nikkie-ftnextの日記