🎨

[ADK][AG-UI] AG-UI(CopilotKit)を利用してADKのChat UIを楽に作成する

に公開

こんにちは、サントリーこと大橋です。

2025年9月25日、Agent Development Kit (ADK)で開発されたAIエージェントのフロントエンド構築を容易にする、AG-UI Protocolのミドルウェアがリリースされました。

https://www.copilotkit.ai/blog/build-a-frontend-for-your-adk-agents-with-ag-ui
https://developers.googleblog.com/en/delight-users-by-combining-adk-agents-with-fancy-frontends-using-ag-ui/

これまでADKには、エージェントの動作をテスト・デバッグするための開発UI(adk web)は同梱されていましたが、本格的なアプリケーションに組み込むためのUIコンポーネントは提供されていませんでした。今回のリリースは、その課題に対する一つの解決策となります。

この記事では、AG-UI (Agent-UI Protocol)とCopilotKitとは何か、そしてそれらとADKを連携するためのミドルウェアを使い、どのようにADK AgentのチャットUIを構築するのかを、導入方法から具体的な使用例まで解説していきます。

対象

  • ADKを触ったことがあるPythonユーザー
  • AIエージェント向けのUIを作成したいと思っている開発者

なお本ドキュメント中ではADKのAgentをAgent、それ以外のAIエージェントをエージェントと表記します。

課題: AIエージェントのUI開発という「最後の壁」

ADKのようなフレームワークを使えば、ツール連携やマルチエージェントシステムといった強力なバックエンド機能を持つAIエージェントを効率的に開発できます。しかし、そのエージェントをエンドユーザーが実際に触れる「アプリケーション」として完成させるには、もう一つの大きな壁がありました。それがUI(ユーザーインターフェース)の開発です。

  • 通信の標準化: エージェントのバックエンドとフロントエンドのUIは、どのように通信すればよいのでしょうか?リアルタイムな思考プロセスや、ツール実行の状況、ユーザーからの承認要求(Human-in-the-Loop)などをどうやってUIに表示し、インタラクションを実現するか。これまで、この通信プロトコルには業界標準が存在せず、開発者は自前で設計・実装する必要がありました。
  • UIコンポーネント: 洗練されたチャットUI、思考プロセスを可視化するコンポーネント、ツール実行の承認ボタンなどをゼロから作るのは大変な手間がかかります。

これらの課題により、高機能なエージェントを開発しても、それをユーザーに届けるまでには多大な労力が必要でした。

AG-UI、CopilotKit、AG-UI ADK-Middlewareとは

この課題を解決するのが、CopilotKitが提供する技術スタックです。

CopilotKitとは

CopilotKitは、アプリケーション内にAI Copilot(アシスタント)機能を組み込むためのオープンソースフレームワークです。特にフロントエンドに焦点を当てており、React製のUIコンポーネントやフックを提供することで、開発者が迅速に高品質なAIチャット体験を実装できるように設計されています。

https://www.copilotkit.ai/

Copilotとついているので、Microsoft(Github) Copilotなど、Microsoft製品感が出ていますが、関係は無いようです。
CopilotKitは元Meta社でインフラチームに在籍していたAtai Barkai氏が共同創業者兼CEOを務めるCopilotKit社(?)が開発を進めています。

AG-UIとは

AG-UI (Agent-UI Protocol) は、CopilotKitチームによって開発された、AIエージェントのバックエンドとフロントエンド間の通信を標準化するためのオープンプロトコルです。このプロトコルが、前述の「通信の標準化」という課題を解決します。AG-UIは、エージェントの思考プロセス、ツールの呼び出し、ユーザーへの情報表示といった複雑なやり取りを、標準化されたイベントストリームとして定義します。

AG-UIとCopilotKitの関係

CopilotKitは、このAG-UIプロトコルを実装した具体的なUIライブラリと考えることができます。開発者はCopilotKitが提供するReactコンポーネント(<CopilotPopup />など)を使うだけで、AG-UIプロトコルに準拠した通信を意識することなく、チャットUIをアプリケーションに組み込めます。

ADK Middleware for AG-UI Protocolとは

そして今回リリースされたのが、ADKとAG-UIを繋ぐためのPython製ミドルウェアです。このミドルウェアがADK AgentのイベントをAG-UIプロトコルに変換し、CopilotKit製のフロントエンドと通信できるようにします。
このミドルウェアの登場により、ADK開発者はフロントエンドの複雑さを気にすることなく、エージェントのコアロジック開発に集中できるようになりました。

導入方法

このミドルウェアはPythonパッケージとしてPyPIに公開されており、pipを使って簡単にインストールできます。ADK AgentをWebサーバーとして公開するために、FastAPIとUvicornも一緒にインストールします。

pip install ag_ui_adk uvicorn fastapi

これだけで、ADKのAgentをAG-UIプロトコルに対応させる準備が整います。

使用例

ミドルウェアを利用してADKのAgentを公開するサーバーサイドのコードは、PythonのWebフレームワークであるFastAPIを使って簡単に記述できます。

バックエンド(AI Agent)

まず、ADKのAgentを定義します。

adk create time_agent

作成されたagent.pyを編集します。
Agent自体はツールを利用して、現在時刻を取得する簡単なAgentです。
さらに、ag_ui_adk パッケージから ADKAgent をインポートしてADK Agentをラップし、add_adk_fastapi_endpoint を使ってFastAPIアプリケーションにエンドポイントとして追加します。

agent.py
import datetime

from ag_ui.core import RunAgentInput
from ag_ui_adk import ADKAgent, add_adk_fastapi_endpoint
from fastapi import FastAPI
from google.adk.agents.llm_agent import Agent
import dotenv

dotenv.load_dotenv()

async def now_tool():
    """
    Return the current date time.
    """
    return datetime.datetime.now(tz=datetime.timezone.utc).isoformat()

root_agent = Agent(
    model='gemini-2.5-flash',
    name='root_agent',
    description='The Clock Agent',
    instruction="""
    You are clock agent. Your task is return current time using `now_tool`.
    """,
    tools=[now_tool]
)

# ユーザーIDの取得
def extract_user(input: RunAgentInput) -> str:
    # Extract from context
    for ctx in input.context:
        if ctx.description == "user":
            return ctx.value
    return f"anonymous_{input.thread_id}"

adk_agent_sample = ADKAgent(
    adk_agent=root_agent,
    app_name="demo_app",
    user_id_extractor=extract_user,
    session_timeout_seconds=3600,
    use_in_memory_services=True
)

app = FastAPI(title="Time Agent App")
add_adk_fastapi_endpoint(app, adk_agent_sample, path="/")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="localhost", port=8000)

これでAgent側は完成です。
このバックエンドサーバーを起動しておきます。

uv run agent.py

INFO:     Started server process [15303]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)

フロントエンド

次に Copilotkit を利用してチャットUIを作成します。

セットアップ

簡単に試すために、npx create-next-app@latestNext.jsの環境を構築します。

npx create-next-app@latest

次に必要なライブラリインストールします。

npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/runtime

実装

CopilotKit Runtimeの実装

まず フロントエンド(ブラウザ)とAgent(サーバー)の通信を安全に行うためにCopilotKit Runtimeを準備します。
アプリケーションの開発を進めていく中で、セットアップスレッドや認証といった処理はここで行われることになります。
今回で言えば、Next.js上で動くWeb APIとして定義します。

src/app/api/copilotkit/route.tsに以下を実装します。

app/api/copilotkit/route.ts


import {
  CopilotRuntime,
  ExperimentalEmptyAdapter,
  copilotRuntimeNextJSAppRouterEndpoint,
} from "@copilotkit/runtime";
import { HttpAgent } from "@ag-ui/client";
import { NextRequest } from "next/server";
// 1. マルチエージェントサポートのために、任意のサービスアダプタを使用できます。
// エージェントは1つだけなので、空のアダプタを使用します。
const serviceAdapter = new ExperimentalEmptyAdapter();
// 2. CopilotRuntime インスタンスを作成し、ADK AG-UI 統合を利用して接続をセットアップします。
const runtime = new CopilotRuntime({
  agents: {
    // Our AG-UI endpoint URL
    "myAgent": new HttpAgent({ url: "http://localhost:8000/" }),
  }
});
// 3. Next.js APIを実装
export const POST = async (req: NextRequest) => {
  const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime,
    serviceAdapter,
    endpoint: "/api/copilotkit",
  });
  return handleRequest(req);
};

チャットUIの実装

フロントエンドの実装は、CopilotKitが提供するReactコンポーネントを使います。
まずCopilotKitを利用するための設定を行うために、layout.tsxを編集します。

layout.tsx
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import {CopilotKit} from "@copilotkit/react-core";

const geistSans = Geist({
  variable: "--font-geist-sans",
  subsets: ["latin"],
});

const geistMono = Geist_Mono({
  variable: "--font-geist-mono",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body>
        {/* 上記で設定したCopilot RuntimeのURLを指定 またCopilot Runtimeで設定したAgent名も設定 */}
        <CopilotKit runtimeUrl="/api/copilotkit" agent="myAgent">
          {children}
        </CopilotKit>
      </body>
    </html>
  );
}

次にチャットUIを作成します。今回は面倒なので解説を簡単にするために直接page.tsxに設定しましょう。
今回はサイドバーからチャットUIが表示されるCopilotSidebarを利用します。

page.tsx
import "@copilotkit/react-ui/styles.css";
import {CopilotSidebar} from "@copilotkit/react-ui";

export default function Home() {
  return (
    <main>
    <h1>Your main content</h1>
    <CopilotSidebar
        labels={{
            title: "Popup Assistant",
            initial: "こんにちは",
        }}
    />
    </main>
  );
}

実行結果

ではフロントエンドも起動して画面を確認してみましょう。

npm run dev

画面を確認してみましょう。

右下にチャットUIを表示するためのボタンが表示されているので、クリックします。

するとチャットUIが表示されました。かなり実装自体は簡単にできましたね。

まとめ

今回は、CopilotKitチームが提供するADK連携ミドルウェアについて解説しました。

この連携により、ADK開発者はバックエンドのエージェントロジックに集中し、フロントエンド開発者はCopilotKitのUIコンポーネントを活用して、ユーザー体験を迅速に構築できるようになりました。ADKを使ったAIアプリケーション開発が、また一段と身近なものになったと言えるでしょう。

AG-UIとCopilotKitの連携では、Stateを利用した状態やUIのカスタム表示や、ツール呼び出し用のUI、HITL用の制御処理やUIなど
AIエージェントを実装するのに必要な機能がある程度揃っていそうです。

ただ認証周りやユーザーIDはどうするべきなのか等、ドキュメントがまだ不十分な点が少し気になります。

ちなみにですが、このAG-UI公式のADK-Middlewareが発表された付近でトレンドマイクロ社もADK向けのAG-UIミドルウェアをリリースしていて、こちらは認証周りのことをドキュメントに記載していたり、ユーザーIDを取得するための関数でrequestオブジェクトが利用できたりと実際のプロジェクトでの利用を想定しているような印象を受け、個人的には扱いやすそうな気がしています。
ただAG-UI側にこのミドルウェアのリリースを報告したところ「公式も最近出したよ」という話になり、今後どうなっていくのか気になるところです。

https://github.com/trendmicro/adk-agui-middleware
https://github.com/ag-ui-protocol/ag-ui/issues/409

AG-UI自体はオープンなプロトコルなので今後AG-UIをサポートしたUIフレームワークがもう少し出てくると嬉しい限りですね


お知らせ/宣伝

ADK開発者が集う日本語のDiscordコミュニティが誕生しました。ADKに関する情報交換や議論に興味がある方は、ぜひご参加ください!

https://discord.gg/BKpGRzjtqZ

また、ADKの最新のコミットログやリリースノートを分かりやすく解説するPodcastを、月・水・金に配信しています。ADKの動向を追いかけたい方は、ぜひ聴いてみてください。

https://www.youtube.com/playlist?list=PL0Zc2RFDZsM_MkHOzWNJpaT4EH5fQxA8n

Discussion