[開発者向け]A2UIとCopilotKitで作る生成UIエージェント:仕組みと導入手順

目次

はじめに

 Google Developers Blogで2026年10月29日、生成UI(Generative UI)アプリの構築方法が紹介されました。Googleのオープン標準「A2UI」と、エージェント統合基盤「CopilotKit」を組み合わせる方法です。この記事では、仕組みと導入手順、試す際の注意点を解説します。

参考記事

要点

  • A2UIは、エージェントがUIをデータとして記述し、アプリ側の既存コンポーネントで描画するGoogleのオープン標準である
  • CopilotKitはAG-UIを基盤とし、Google ADKやLangChainなどのエージェントとA2UI対応のフロントエンドを接続する
  • 導入は、エージェントのAG-UIエンドポイント化と、クライアント側でのコンポーネントカタログ定義の2つで構成される
  • A2UIの画面は双方向で、ユーザーの入力値が同じストリームでエージェントに戻り、複数ステップの手続きを1つの画面で扱える
  • スターターアプリは `npx copilotkit@latest create –name my-app –framework a2ui` で作成できる

詳細解説

生成UIとA2UI:UIを「データ」として記述する

 これまでのエージェントは、旅行の計画まではできても、結果を長い文章で返すだけでした。選べるパッケージ一覧や日付ピッカーを、会話内に描く標準的な方法がなかったためです。

 生成UIは、リクエストに合わせてエージェントが実行時に画面を組み立てる層です。ユーザーは文章を読んで入力し直す代わりに、ボタンやフォームを操作できます。予約や申し込みなど、入力項目が多い業務ほど効果が出やすいとみられます。

 A2UI(Agent-to-UI)は、Googleが策定した生成UI向けのオープン標準です。UIフレームワークにも通信方式にも依存しません。エージェントは画面をデータとして記述し、アプリは手持ちのコンポーネントで描画します。主な特徴は次の3点です。

  • セキュリティ優先:実行可能なコードではなく宣言的なデータ形式。カタログ外の部品は画面に届く前に弾かれる
  • ストリーミング対応:小さなJSONメッセージをIDで参照し合うフラットな形式。届いた順に描画できる
  • 移植しやすい:同じ応答をReact、Lit、Angular、SwiftUI、Jetpack Compose(Android)、Flutterで描画できる

 最も広く使われているのは宣言的モードです。エージェントは、事前に宣言された部品と関数を組み合わせてUIを作ります。HTMLを丸ごと生成させる方式より、スクリプト混入などのリスクを抑えやすい設計です。

 部品の一覧は「カタログ」と呼ばれます。A2UIには、レイアウト、表示、入力、コンテナの4分野で18個の基本部品を持つBasic Catalogがあります。Basic Catalogは意図的に最小限のため、本番アプリの多くは独自のカスタムカタログを定義します。社内のデザインシステムを登録すれば、生成画面の見た目も揃えやすくなります。

まず試す:スターターアプリ

 A2UIとCopilotKitを組み合わせたアプリ一式は、次のコマンドで作成できます。npx(Node.jsのパッケージを取得して実行するツール)で、エージェント統合済みのスターターを生成します。

npx copilotkit@latest create --name my-app --framework a2ui

  • `–name my-app`:作成するアプリの名前
  • `–framework a2ui`:A2UI向けの構成を選ぶ指定

 CopilotKit Dojoでは、実行できるデモが公開されています。固定スキーマ、カスタムカタログでの動的スキーマ、エラー回復の3種類です。ほかにA2UI ComposerやCopilotKit A2UI Docsも案内されています。

CopilotKitとAG-UIの役割分担

 CopilotKitは、利用者向けエージェントアプリの統合スタックです。LangChain、AWS Strands、Google ADKなどとつながります。チャット画面、ランタイム、A2UIレンダラーをReactとAngular向けに提供します。

 土台はAG-UI(Agent-User Interaction Protocol)です。データは次のように流れます。

  1. エージェントがA2UIの操作(オペレーション)を出力する
  2. AG-UIがそれを型付きイベントとしてクライアントへ届ける
  3. ユーザーの操作値が、同じストリームでエージェントへ戻る

 A2UIは「何を描くか」、AG-UIは「どう運ぶか」を担います。Google ADK、LangChain、Mastra、StrandsはいずれもAG-UI互換で、セットアップは共通です。

 AG-UIで統合すると、次の機能を自前で作らずに済みます。

  • カタログはセットアップ時にエージェントへ届き、サーバー側の設定が最小限で済む
  • 専用のサブエージェントが生成するため、メインのコンテキストを圧迫しない
  • 不正な生成は検出され、エラー内容を差し戻して自己修復する
  • 再試行の上限に達すると短いメッセージに置き換わり、会話は続く

セットアップ1:ADKエージェントをエンドポイントとして公開する

 Google ADKでは、`ag_ui_adk` パッケージでエージェントを包み、FastAPI上のAG-UIエンドポイントとして公開します。次は航空券検索エージェントの例です。

from fastapi import FastAPI
from google.adk.agents import LlmAgent
from ag_ui_adk import ADKAgent, add_adk_fastapi_endpoint

root_agent = LlmAgent(
    name="flight_agent",
    model="gemini-3.8-flash",
    instruction="Help users find and book flights. Call generate_a2ui to show results.",
)

adk_agent = ADKAgent(
    adk_agent=root_agent,
    app_name="flights",
    user_id="demo_user",
    use_in_memory_services=True,
)

app = FastAPI()
add_adk_fastapi_endpoint(app, adk_agent, path="/")
  • `LlmAgent`:エージェント本体。結果の表示に `generate_a2ui` を呼ぶよう指示している
  • `ADKAgent`:AG-UI向けのラッパー
  • `add_adk_fastapi_endpoint`:`path=”/”` にエンドポイントを追加する

 `generate_a2ui` はコード内にありません。A2UIの設定をクライアントからリクエストと一緒に送る、動的設定を使うためです。

 `user_id` や `use_in_memory_services` はデモ向けの値とみられます。実運用では、ユーザーとの対応づけやセッションの保存先を別途設計します。モデル名も利用環境に合わせて変えてください。

 アプリ側では、このエンドポイントをCopilotKitランタイムの `/api/copilotkit` に登録します。手順はGoogle ADKクイックスタートにあります。

セットアップ2:クライアント側でカタログを登録する

 クライアント側では、部品を定義し、レンダラーを対応づけ、カタログをプロバイダーに渡します。次は `FlightCard` を登録する例です。

import { CopilotKit, CopilotChat } from '@copilotkit/react-core/v2';
import {
  createCatalog,
  type CatalogDefinitions,
  type CatalogRenderers,
} from '@copilotkit/a2ui-renderer';
import { z } from 'zod';

const catalogDefinitions = {
  FlightCard: {
    description: 'A flight result with airline, times, and stops.',
    props: z.object({
      airline: z.string(),
      departs: z.string(),
      arrives: z.string(),
      stops: z.number(),
    }),
  },
} satisfies CatalogDefinitions;

const catalogRenderers = {
  FlightCard: MyFlightCard, // your React component
} satisfies CatalogRenderers<typeof catalogDefinitions>;

const catalog = createCatalog(catalogDefinitions, catalogRenderers, {
  catalogId: 'flight-catalog',
  includeBasicCatalog: true,
});

<CopilotKit runtimeUrl="/api/copilotkit" a2ui={{ catalog }}>
  <CopilotChat />
</CopilotKit>
  • `description`:エージェントのプロンプトに入り、モデルが部品を選ぶ手がかりになる
  • `props`:Zodのスキーマで、エージェントが返した値を検証する
  • `catalogRenderers`:定義名と実際のReactコンポーネントを対応づける
  • `includeBasicCatalog: true`:Basic Catalogの部品もあわせて使える

 `description` には、用途や使う場面を具体的に書くのが良さそうです。CopilotKitを使わず、`@ag-ui/client` と @a2ui/react などで組む構成も可能です。

双方向の画面で複数ステップの手続きを組む

 A2UIの画面(サーフェス)は双方向で、部品は状態の変化に反応します。日付の選択や搭乗者情報の入力は、同じストリームでエージェントに戻ります。エージェントはその値で画面を出し直します。

 往復は、データパスにバインドした入力欄と、送り返すパスを指定したボタンで成り立ちます。次は2つの部品定義を並べた抜粋です。

{ "id": "cabin", "component": "ChoicePicker", "variant": "mutuallyExclusive",
  "options": [ { "label": "Economy", "value": "eco" },
               { "label": "Business", "value": "biz" } ],
  "value": { "path": "/booking/cabin" } },
{ "id": "confirm", "component": "Button", "child": "confirm_label",
  "action": { "event": { "name": "confirmBooking",
                         "context": { "cabin": { "path": "/booking/cabin" },
                                      "email": { "path": "/booking/email" } } } } }
  • `cabin`:客室クラスを排他選択させ、値を `/booking/cabin` に入れる
  • `confirm`:押すと `/booking/cabin` と `/booking/email` の値をまとめて送る

 検証はクライアント側で行われ、メールアドレスの誤りはモデルを呼ばずに表示されます。ボタンが押されると、エージェントは同じ `surfaceId` に画面を出し直します。航空便の検索から予約確定までを、1つの画面で扱えます。

導入時の注意点

  • 最初はスターターとBasic Catalogで動きをつかみ、その後に自社部品をカスタムカタログへ移す
  • 部品に渡す値はモデルが生成する。価格や予約内容など重要な値はサーバー側でも検証する
  • クライアント側の検証は入力の補助にすぎない。確定処理ではサーバーで改めて確認する
  • 自己修復や再試行は、裏でモデル呼び出しが増える。本番前にレイテンシーと料金への影響を測る
  • サンプルの引数名や関数名は、利用するバージョンのドキュメントと照合する

まとめ

 A2UIは、エージェントにUIをデータで記述させ、描画は手元のコンポーネントに任せる標準です。CopilotKitと組み合わせると、エンドポイント公開とカタログ登録の2つで双方向の画面を組めます。まずBasic Catalogで試作し、業務に合う部品を順に増やす進め方が現実的と言えます。

この記事が気に入ったら
フォローしてね!

  • URLをコピーしました!
  • URLをコピーしました!
目次