UI ツール
adk-ui crate により、AI エージェントはツール呼び出しを通じてリッチなユーザーインターフェースを動的に生成できます。エージェントは、フォーム、カード、アラート、テーブル、チャートなどを、フロントエンドで利用できる JSON にシリアライズされる、型安全な Rust API を介して描画できます。
構築するもの

主な概念:
- フォーム - さまざまなフィールドタイプでユーザー入力を収集
- カード - アクションボタン付きで情報を表示
- テーブル - 行と列で構造化データを提示
- チャート - 棒グラフ、折れ線グラフ、エリアチャート、円グラフでデータを可視化
- アラート - 通知やステータスメッセージを表示
- モーダル - 確認ダイアログや集中したインタラクション
- トースト - 簡潔なステータス通知
- プロトコル相互運用 - A2UI、AG-UI、または MCP Apps のペイロードとして UI を出力
例: 分析ダッシュボード

例: 登録フォーム

仕組み
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 1: User requests something │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ User: "I want to register for an account" │
│ │
│ ↓ │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ AI AGENT (LLM) │ │
│ │ "I should show a registration form" │ │
│ └──────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 2: Agent calls render_form tool │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 📞 Tool Call: render_form({ │
│ title: "Registration", │
│ fields: [ │
│ {name: "email", type: "email"}, │
│ {name: "password", type: "password"} │
│ ] │
│ }) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 3: Frontend renders the form │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 📋 Registration │ │
│ │ ──────────────────────────────────────────── │ │
│ │ Email: [________________________] │ │
│ │ Password: [________________________] │ │
│ │ │ │
│ │ [ Register ] │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ ✅ User sees an interactive form, fills it out, clicks Register │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────────────────┐
│ STEP 4: Form submission sent back to agent │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 📩 Event: { │
│ type: "form_submit", │
│ data: { email: "user@example.com", password: "***" } │
│ } │
│ │
│ Agent: "Great! I'll process your registration and show a success alert" │
│ │
│ 📞 Tool Call: render_alert({ │
│ title: "Registration Complete!", │
│ variant: "success" │
│ }) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
概要
UI ツールを使用すると、エージェントは次のことができます。
- textarea をサポートする動的フォームでユーザー入力を収集
- カード、アラート、通知で情報を表示
- テーブルやインタラクティブなチャート(Recharts)でデータを提示
- 進行状況や読み込み状態(スピナー、スケルトン)を表示
- 複数のコンポーネントでダッシュボードレイアウトを作成
- モーダルでユーザーの確認を要求
- ステータス更新用のトースト通知を表示
クイックスタート
Cargo.toml に追加します。
[dependencies]
adk-ui = { git = "https://github.com/zavora-ai/adk-ui" }
adk-agent = "2.1.0"
adk-model = "2.1.0"
基本的な使い方
use adk_rust::prelude::*;
use adk_ui::UiToolset;
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let model = Arc::new(GeminiModel::from_env("gemini-3.7-flash")?);
// Get all 10 UI tools
let ui_tools = UiToolset::all_tools();
// Create AI agent with UI tools
let mut builder = LlmAgentBuilder::new("ui_agent")
.model(model)
.instruction(r#"
You are a helpful assistant that uses UI components to interact with users.
Use render_form for collecting information.
Use render_card for displaying results.
Use render_alert for notifications.
Use render_modal for confirmation dialogs.
Use render_toast for brief status messages.
"#);
for tool in ui_tools {
builder = builder.tool(tool);
}
let agent = builder.build()?;
Ok(())
}
A2UI JSONL(render_screen / render_page / render_kit)
これらのツールは、A2UI レンダラーとの互換性のために A2UI v0.9 JSONL を出力します。
render_screen(単一サーフェス)
{
"surface_id": "main",
"components": [
{ "id": "root", "component": "Column", "children": ["title", "cta"] },
{ "id": "title", "component": "Text", "text": "Welcome", "variant": "h1" },
{ "id": "cta_label", "component": "Text", "text": "Continue", "variant": "body" },
{ "id": "cta", "component": "Button", "child": "cta_label", "action": { "event": { "name": "continue" } } }
]
}
render_page(複数セクションのページ)
{
"title": "Release Notes",
"description": "Highlights for the latest launch.",
"sections": [
{
"heading": "What’s new",
"body": "Three big improvements shipped this week.",
"bullets": ["Faster onboarding", "Better search", "New dashboards"],
"actions": [{ "label": "View details", "action": "view_details", "variant": "borderless" }]
}
]
}
render_kit(カタログ + トークン + テンプレート)
{
"name": "Fintech Pro",
"version": "0.1.0",
"brand": { "vibe": "trustworthy", "industry": "fintech" },
"colors": { "primary": "#2F6BFF" },
"typography": { "family": "Source Sans 3" },
"templates": ["auth_login", "dashboard"]
}
React renderer を使用して A2UI JSONL を利用します:
import {
A2uiStore,
A2uiSurfaceRenderer,
applyParsedMessages,
parseJsonl,
} from "@zavora-ai/adk-ui-react";
const store = new A2uiStore();
const parsed = parseJsonl(jsonl);
applyParsedMessages(store, parsed);
export function App() {
return <A2uiSurfaceRenderer store={store} surfaceId="main" />;
}
利用可能なツール
render_form
ユーザー入力を収集するインタラクティブなフォームをレンダリングします。
{
"title": "Registration Form",
"description": "Create your account",
"fields": [
{"name": "username", "label": "Username", "type": "text", "required": true},
{"name": "email", "label": "Email", "type": "email", "required": true},
{"name": "password", "label": "Password", "type": "password", "required": true},
{"name": "newsletter", "label": "Subscribe to newsletter", "type": "switch"}
],
"submit_label": "Register"
}
レンダリング結果:
┌─────────────────────────────────────────────────┐
│ 📋 Registration Form │
│ Create your account │
│ ───────────────────────────────────────────── │
│ │
│ Username * │
│ ┌─────────────────────────────────────────┐ │
│ │ │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Email * │
│ ┌─────────────────────────────────────────┐ │
│ │ │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Password * │
│ ┌─────────────────────────────────────────┐ │
│ │ •••••••• │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Subscribe to newsletter [○] │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Register │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────┘
フィールドタイプ:text、email、password、number、date、select、multiselect、switch、slider、textarea
render_card
オプションのアクションボタン付きで情報カードを表示します。
{
"title": "Order Confirmed",
"description": "Order #12345",
"content": "Your order has been placed successfully. Expected delivery: Dec 15, 2025.",
"actions": [
{"label": "Track Order", "action_id": "track", "variant": "primary"},
{"label": "Cancel", "action_id": "cancel", "variant": "danger"}
]
}
ボタンのバリエーション:primary、secondary、danger、ghost、outline
render_alert
通知とステータスメッセージを表示します。
{
"title": "Payment Successful",
"description": "Your payment of $99.00 has been processed.",
"variant": "success"
}
バリエーション:info、success、warning、error
render_confirm
アクションを実行する前にユーザーの確認を求めます。
{
"title": "Delete Account",
"message": "Are you sure you want to delete your account? This action cannot be undone.",
"confirm_label": "Delete",
"cancel_label": "Keep Account",
"variant": "danger"
}
render_table
表形式のデータを表示します。
{
"title": "Recent Orders",
"columns": [
{"header": "Order ID", "accessor_key": "id"},
{"header": "Date", "accessor_key": "date"},
{"header": "Amount", "accessor_key": "amount"},
{"header": "Status", "accessor_key": "status"}
],
"data": [
{"id": "#12345", "date": "2025-12-10", "amount": "$99.00", "status": "Delivered"},
{"id": "#12346", "date": "2025-12-11", "amount": "$149.00", "status": "Shipped"}
]
}
render_chart
データの可視化を作成します。
{
"title": "Monthly Sales",
"chart_type": "bar",
"x_key": "month",
"y_keys": ["revenue", "profit"],
"data": [
{"month": "Jan", "revenue": 4000, "profit": 2400},
{"month": "Feb", "revenue": 3000, "profit": 1398},
{"month": "Mar", "revenue": 5000, "profit": 3800}
]
}
チャートタイプ:bar、line、area、pie
render_progress
オプションのステップ付きでタスクの進捗を表示します。
{
"title": "Installing Dependencies",
"value": 65,
"description": "Installing package 13 of 20...",
"steps": [
{"label": "Download", "completed": true},
{"label": "Extract", "completed": true},
{"label": "Install", "current": true},
{"label": "Configure", "completed": false}
]
}
render_layout
複数のセクションを含むダッシュボードレイアウトを作成します。
{
"title": "System Status",
"description": "Current system health overview",
"sections": [
{
"title": "Services",
"type": "stats",
"stats": [
{"label": "API Server", "value": "Healthy", "status": "operational"},
{"label": "Database", "value": "Degraded", "status": "warning"},
{"label": "Cache", "value": "Down", "status": "error"}
]
},
{
"title": "Recent Errors",
"type": "table",
"columns": [{"header": "Time", "key": "time"}, {"header": "Error", "key": "error"}],
"rows": [{"time": "10:30", "error": "Connection timeout"}]
}
]
}
セクションタイプ:stats、table、chart、alert、text
render_modal
確認や集中したインタラクションのためのモーダルダイアログを表示します。
{
"title": "Confirm Deletion",
"message": "Are you sure you want to delete this item? This action cannot be undone.",
"size": "medium",
"closable": true,
"confirm_label": "Delete",
"cancel_label": "Cancel",
"confirm_action": "delete_confirmed"
}
サイズ:small、medium、large、full
render_toast
ステータス更新用の短いトースト通知を表示します。
{
"message": "Settings saved successfully",
"variant": "success",
"duration": 5000,
"dismissible": true
}
バリエーション:info、success、warning、error
フィルタリングされたツール
エージェントに必要なツールのみを選択します:
let toolset = UiToolset::new()
.without_chart() // Disable charts
.without_table() // Disable tables
.without_progress() // Disable progress
.without_modal() // Disable modals
.without_toast(); // Disable toasts
// Or use forms only
let forms_only = UiToolset::forms_only();
UI イベントの処理
ユーザーがレンダリングされた UI を操作すると(フォームの送信、ボタンのクリックなど)、イベントがエージェントに送り返されます:
use adk_ui::{UiEvent, UiEventType};
// UiEvent structure
pub struct UiEvent {
pub event_type: UiEventType, // FormSubmit, ButtonClick, InputChange
pub action_id: Option<String>,
pub data: Option<HashMap<String, Value>>,
}
// Convert to message for agent
let message = ui_event.to_message();
UI 更新のストリーミング
リアルタイム UI 更新には、UiUpdateを使用して ID によりコンポーネントにパッチを適用します。
use adk_ui::{UiUpdate, UiOperation};
let update = UiUpdate {
target_id: "progress-bar".to_string(),
operation: UiOperation::Patch,
payload: Some(Component::Progress(Progress {
id: Some("progress-bar".to_string()),
value: 75,
label: Some("75%".to_string()),
})),
};
操作: Replace、Patch、Append、Remove
コンポーネントスキーマ
28 種類すべてのコンポーネントタイプは、ストリーミング更新用のオプションの id フィールドをサポートします。
Atoms: Text、Button、Icon、Image、Badge
Inputs: TextInput、NumberInput、Select、MultiSelect、Switch、DateInput、Slider、Textarea
Layouts: Stack、Grid、Card、Container、Divider、Tabs
Data: Table、List、KeyValue、CodeBlock
Visualization: Chart(Recharts による bar、line、area、pie)
Feedback: Alert、Progress、Toast、Modal、Spinner、Skeleton
React クライアント
スタンドアロンの adk-ui リポジトリに、React のリファレンス実装が提供されています。
npm install @zavora-ai/adk-ui-react
React クライアントには以下が含まれます。
- Rust スキーマに対応する TypeScript 型
- 28 種類すべてのタイプに対応するコンポーネントレンダラー
- インタラクティブなチャートのための Recharts 統合
- Markdown レンダリングのサポート
- ダークモードのサポート
- フォーム送信の処理
- モーダルおよびトーストコンポーネント
アーキテクチャ
Agent ──[render_* tool]──> UiResponse (JSON)
│
│ SSE
▼
Client (React)
│
└──> UiEvent (user action) ──> Agent
プロトコル相互運用性
13 種類すべてのレンダリングツールは、protocol 引数を通じてプロトコル対応の出力をサポートします。
| プロトコル | 説明 |
|---|---|
a2ui | A2UI v0.9 準拠の JSONL サーフェス(render_screen、render_page のデフォルト) |
ag_ui | ハイブリッド AG-UI サポート:デフォルトでは互換性ラッパーに加え、adk-server クライアント向けのプロトコルネイティブなランタイムトランスポートを追加提供 |
mcp_apps | MCP Apps ペイロードと ui:// リソースの互換性、追加的なブリッジヘルパー、通知フロー、ランタイムリクエストフィールド、および HTML/リソースアダプター |
protocol が省略されている場合、ツールはデフォルトの出力形式を使用します(ほとんどのツールでは従来の UiResponse JSON、render_screen/render_page/render_kit では A2UI)。
プロトコル選択の例:
{
"protocol": "mcp_apps",
"mcp_apps": {
"resource_uri": "ui://demo/surface"
}
}
相互運用アダプター
adk-ui には、プロトコル変換のためのアダプター基本機能が含まれています。
A2uiAdapter— 正規化されたサーフェスを A2UI JSONL に変換しますAgUiAdapter— AG-UI イベントペイロードに変換しますMcpAppsAdapter— MCP Apps リソースペイロードに変換します
これらは共有 UiProtocolAdapter トレイトを実装し、すべてのツールで一貫した変換を実現します。
非推奨化のタイムライン
従来の adk_ui ランタイムプロファイルには、非推奨化メタデータが含まれています。
| 日付 | マイルストーン |
|---|---|
| 2026-02-07 | 非推奨化の発表 |
| 2026-12-31 | 廃止目標日 |
置換: a2ui、ag_ui、mcp_apps
このメタデータは UI_PROTOCOL_CAPABILITIES 定数を通じて公開され、adk-server によって /api/ui/capabilities で提供されます。
この機能レスポンスでは、クライアントがハイブリッドまたは互換性サブセットと、完全なネイティブプロトコルサポートを区別できるよう、implementationTier、specTrack、summary、および limitations も報告されます。
adk-server がホスト向け境界である場合、/api/ui/initialize、/api/ui/message、/api/ui/update-model-context、/api/ui/notifications/poll、/api/ui/notifications/resources-list-changed、および /api/ui/notifications/tools-list-changed で、追加の MCP Apps ブリッジヘルパーも公開します。これらのエンドポイントは既存の ADK ランタイム契約を維持し、直接のリクエストボディ、または ui/... メソッドを持つ JSON-RPC 形式のエンベロープのいずれかを受け入れます。
ランタイムコンシューマー向けに、adk-server は次もサポートします。
- AG-UI ネイティブの SSE シリアル化用の
x-adk-ui-transport: protocol_nativeまたはuiTransport: "protocol_native" - 既存の
newMessageと並行した、input/agUiInputによる AG-UI デュアルパスリクエスト入力 mcpAppsInitialize、mcpAppsRequest、およびmcpAppsInitializedを介した/api/run_sse内の MCP Apps ブリッジエンベロープ
これらの追加機能はオプトインです。既存の /api/run および /api/run_sse コンシューマーは、ネイティブ AG-UI トランスポートモードを明示的に要求しない限り、引き続き汎用の ADK ラッパーを受け取ります。
フレームワークが所有する MCP Apps ツールレスポンスについて、adk-server::ui_types は次を公開するようになりました。
- 型付きホスト/アプリブリッジ状態用の
McpUiBridgeSnapshot - 追加のレスポンスエンベロープ用の
McpUiToolResult - ブリッジメタデータ用の
McpUiToolResultBridge(protocolVersion、structuredContent、hostInfo、hostCapabilities、hostContext、appInfo、appCapabilities、initialized)
ブリッジ/セッション状態をツールレスポンスに昇格させる場合は、McpUiBridgeSnapshot::build_tool_result(...) を優先してください。これによりツール結果の形式が標準化される一方、互換性を重視するホスト向けに resourceUri とインライン html のフォールバックも維持されます。
組み込みまたはブラウザホストのマッピングでは、追加の HTTP ブリッジはホスト/アプリのフローに次のように対応します。
ui/initialize->/api/ui/initializeui/message->/api/ui/messageui/update-model-context->/api/ui/update-model-contextnotifications/resources/list_changed->/api/ui/notifications/resources-list-changednotifications/tools/list_changed->/api/ui/notifications/tools-list-changed- キューに入れられたホスト通知 ->
/api/ui/notifications/poll
直接の /api/ui/* ブリッジエンドポイントは、MCP Apps ホストに推奨されるライフサイクルパスです。ランタイム側の MCP Apps リクエストフィールドは、混在クライアントまたはレガシークライアント向けの追加の互換性パスとして引き続き利用できます。
例
スタンドアロンの adk-ui リポジトリには、実行可能な UI の例が含まれています。
| 例 | 説明 | 実行コマンド |
|---|---|---|
ui_agent | コンソールデモ | cargo run --bin ui_agent |
ui_server | HTTP サーバーと SSE | cargo run --bin ui_server |
ui_react_client | React フロントエンド | cd ui_react_client && npm run dev |
adk-ui リポジトリからそれらの例を実行して、Rust パッケージと React パッケージが同じリリース系列に保たれるようにします。
サンプルプロンプト
次のプロンプトで UI ツールをテストします。
# Forms
"I want to register for an account"
"Create a contact form"
"Create a feedback form with a comments textarea"
# Cards
"Show me my profile"
"Display a product card for a laptop"
# Alerts
"Show a success message"
"Display a warning about expiring session"
# Modals
"I want to delete my account" (shows confirmation modal)
"Show a confirmation dialog before submitting"
# Toasts
"Show a success toast notification"
"Display an error toast"
# Tables
"Show my recent orders"
"List all users"
# Charts
"Show monthly sales chart"
"Display traffic trends as a line chart"
"Show revenue breakdown as a pie chart"
# Progress & Loading
"Show upload progress at 75%"
"Display a loading spinner"
"Show skeleton loading state"
# Dashboards
"Show system status dashboard"