0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AG-UIで大事なのは「画面を生成すること」ではなく「Agentとユーザー体験をイベントでつなぐこと」

0
Posted at

先に結論

を一通り読んで、一番強く感じたのはこれです。

AG-UI、つまり Agent User Interaction Protocol は、単なる「AIチャットUIの作り方」ではありません。
また、「AIが画面を生成するための仕様」そのものでもありません。

もっと本質的には、

AI Agent とユーザー向けアプリケーションの間で、状態・メッセージ・ツール実行・人間の介入をリアルタイムにやり取りするためのイベントベースプロトコル

です。

公式ドキュメントでも、AG-UI は AI agents と user-facing applications を接続する open / lightweight / event-based protocol であり、agentic backend と frontend application の間の双方向接続を標準化するものだと説明されています。(AG-UI)

短く言うと、

MCP が Agent と Tool/Data をつなぎ、A2A が Agent と Agent をつなぐなら、AG-UI は Agent と User Interface をつなぐ

ということです。

AG-UIとは何か

AG-UI は、AI Agent の実行結果をフロントエンドに流すためのプロトコルです。

ただのテキストストリーミングではありません。

AG-UI が扱うのは、たとえば次のようなものです。

  • Agent の実行開始・終了
  • テキストのストリーミング
  • ツール呼び出し
  • ツール引数のストリーミング
  • ツール実行結果
  • フロントエンドとの共有状態
  • 人間の承認待ち
  • reasoning 表示や暗号化された reasoning continuity
  • activity / progress 表示
  • generative UI との接続
  • セッションの復元、分岐、time travel

つまり、AG-UI は「チャット欄に文字を出す」ためだけのものではありません。

Agent が何をしているのか。
どの状態にいるのか。
どのツールを呼ぼうとしているのか。
ユーザーの承認が必要なのか。
UI 側がどう反応すべきなのか。

これらをイベントとして扱うための仕組みです。

公式ドキュメントでは、AG-UI は agent state、UI intents、user interactions が model / agent runtime と frontend application の間を流れる方法を標準化すると説明されています。(AG-UI)

なぜAG-UIが必要なのか

従来のWebアプリは、だいたいこうでした。

Client → Request
Server → Response
Client → Render

シンプルです。

でも、Agentic application ではこれが崩れます。

Agent はすぐに答えないことがあります。
途中経過を出します。
ツールを呼びます。
状態を更新します。
人間に確認を求めます。
場合によっては sub-agent に委任します。
ユーザーが途中で介入します。

公式ドキュメントでも、agentic applications は従来の request/response モデルを壊すと説明されています。理由として、agent は long-running で intermediate work を stream し、nondeterministic に UI を制御し、structured / unstructured I/O を混ぜ、sub-agent などの user-interactive composition を必要とすると整理されています。(AG-UI)

ここがかなり大事です。

Agent を本気でアプリに組み込むと、問題は「モデルから文字を受け取ること」ではなくなります。

問題は、

Agent の進行中の状態を、ユーザーが理解・介入・修正できるUIとしてどう表現するか

になります。

そのためのプロトコルが AG-UI です。

Skills / MCP / Plugin / A2A / AG-UI の関係

これまでの流れと合わせると、役割はこう整理できます。

技術 本質 何をつなぐか
Agent Skills 作業手順 Agent ↔ 手順・判断基準
MCP 外部接続 Agent ↔ Tools / Data
Codex Plugin 配布 Skills / Apps / MCP を配布可能にする
A2A Agent間通信 Agent ↔ Agent
AG-UI ユーザー体験 Agent ↔ User-facing App

AG-UI 公式サイトでも、MCP、A2A、AG-UI は相互補完的な3つの agentic protocols として整理されています。MCP は Agent と tools/context、A2A は Agent と Agent、AG-UI は Agent と users through user-facing applications をつなぐものと説明されています。(AG-UI)

もう少し実務っぽく言うと、こうです。

Agent Skills:
  この仕事はこう進める

MCP:
  この外部ツール・データにはこう接続する

Codex Plugin:
  それらを配布可能な形にまとめる

A2A:
  他のAgentに仕事を委任する

AG-UI:
  Agentの進行状況・状態・承認・結果をユーザーUIに出す

この5つは競合しません。

むしろ、組み合わせるものです。

たとえば、契約レビューAgentならこうなります。

契約レビューAgent
  - Skills: 契約レビューの観点
  - MCP: 契約DB、社内規程、過去案件に接続
  - Plugin: チーム向けに配布
  - A2A: 法務Agentや営業Agentに確認を依頼
  - AG-UI: レビュー進捗、差分、承認、修正案をUIに表示

AG-UI は最後の「ユーザーにどう見せるか」を担当します。

ここが抜けると、Agent は裏側では賢く動いていても、ユーザーから見るとただの黒箱になります。

AG-UIはGenerative UI仕様そのものではない

ここは誤解しやすいです。

AG-UI という名前を見ると、「AIがUIを生成する仕様かな」と思います。

でも違います。

公式ドキュメントでは、A2UI、MCP-UI、Open-JSON-UI は generative UI specification であり、agent が dynamic UI components を返せるようにするものだと説明されています。一方で、AG-UI は generative UI specification ではなく、agent と application の間の bidirectional runtime connection を提供する User Interaction protocol だと説明されています。(AG-UI)

つまり、

Generative UI spec:
  AgentがどんなUI部品を返すか

AG-UI:
  Agentとアプリがどう双方向にやり取りするか

です。

AG-UI は generative UI をサポートできます。
でも、AG-UI 自体は「UI部品のJSON仕様」ではありません。

もっと下の実行レイヤーです。

AG-UIの基本構造

AG-UI のアーキテクチャは、かなり素直です。

User-facing Application
  ↓
AG-UI Client
  ↓
Agent / Agent Backend

公式ドキュメントでは、AG-UI は client-server architecture に従い、Application、AG-UI Client、Agents、Secure Proxy などの構成要素で整理されています。Application は chat や AI-enabled application、AG-UI Client は HttpAgent などの通信クライアント、Agents は backend AI agents です。(AG-UI)

中心にあるのはイベントです。

Agent は実行中にイベントを emit します。
Client はそのイベントを受け取ります。
Frontend はイベントを見て UI を更新します。

type RunAgent = () => Observable<BaseEvent>

公式ドキュメントでも、AG-UI の primary abstraction は run(input: RunAgentInput) -> Observable<BaseEvent> のように、agent を実行して event stream を受け取る形で説明されています。(AG-UI)

この設計がかなり良いです。

なぜなら、Agent の実行は「1回の返答」ではなく「イベント列」だからです。

イベントがAG-UIの中心

AG-UI では、すべての通信が typed events に基づいています。

公式ドキュメントでは、Events は agents と frontends の間の fundamental units of communication であり、real-time structured interaction を可能にすると説明されています。(AG-UI)

主なイベントカテゴリはこうです。

カテゴリ 役割
Lifecycle Events Agent run の開始・終了・エラー
Text Message Events テキストのストリーミング
Tool Call Events ツール呼び出しと引数ストリーミング
State Management Events Agent と UI の状態同期
Activity Events 進行中の作業や進捗表示
Reasoning Events reasoning の可視化・継続
Special Events RAW / CUSTOM などの拡張

たとえば、普通のテキスト出力でも、単なる文字列ではなくこういう流れになります。

RUN_STARTED
TEXT_MESSAGE_START
TEXT_MESSAGE_CONTENT
TEXT_MESSAGE_CONTENT
TEXT_MESSAGE_END
RUN_FINISHED

ツール呼び出しならこうです。

TOOL_CALL_START
TOOL_CALL_ARGS
TOOL_CALL_ARGS
TOOL_CALL_END
TOOL_CALL_RESULT

公式ドキュメントでも、text message は Start → Content → End、tool call は Start → Args → End の streaming pattern として説明されています。(AG-UI)

ここが本質です。

AG-UI は「結果」を受け取るのではなく、Agent の実行プロセスをイベントとして受け取ります。

だから UI 側は、

  • ローディングを出す
  • ステップを表示する
  • ツール呼び出しを見せる
  • 承認ボタンを出す
  • 状態をリアルタイム更新する
  • エラーから復旧する

といったことができます。

State ManagementはAG-UIの強いところ

AG-UI の中でかなり重要なのが State Management です。

Agentic UI では、会話ログだけでは足りません。

たとえば、旅行計画アプリなら、

{
  "destination": "Tokyo",
  "dates": ["2026-07-10", "2026-07-15"],
  "budget": 200000,
  "selectedHotel": null,
  "approvalStatus": "pending"
}

のような状態があります。

これは frontend も見たいし、agent も見たい。

AG-UI では、state は structured data object として扱われ、agent と frontend の両方からアクセスでき、interaction の進行に合わせてリアルタイム更新されます。公式ドキュメントでは、shared state architecture によって、agent は application の現在状態を見て判断し、frontend は agent の内部状態変化に反応でき、双方が state を変更できると説明されています。(AG-UI)

状態同期には2種類あります。

STATE_SNAPSHOT:
  完全な状態を渡す

STATE_DELTA:
  JSON Patchで差分だけ渡す

STATE_DELTA は JSON Patch、つまり RFC 6902 の形式を使います。公式ドキュメントでも、snapshot は全体状態、delta は JSON Patch による incremental updates と説明されています。(AG-UI)

これはかなり実務的です。

毎回 state 全体を送ると重い。
でも差分だけなら軽い。
接続が切れたら snapshot で復旧できる。

Agent と UI が協調するには、この共有 state がかなり重要になります。

Toolsは「フロントエンド側の能力」をAgentに渡す

AG-UI の Tools も面白いです。

MCP の tools は、Agent が外部ツールやデータにアクセスするためのものです。

一方で AG-UI の tools は、特に frontend-defined tools が重要です。

公式ドキュメントでは、AG-UI は backend-defined tools と client-defined tools を区別し、client-defined tools は RunAgentInput.tools で agent に渡されると説明されています。これにより、UI actions、approvals、user-mediated workflows のような application-specific frontend behavior を agent が呼び出せます。(AG-UI)

たとえば、フロントエンドがこういう tool を渡します。

const confirmAction = {
  name: "confirmAction",
  description: "Ask the user to confirm a specific action before proceeding",
  parameters: {
    type: "object",
    properties: {
      action: { type: "string" },
      importance: {
        type: "string",
        enum: ["low", "medium", "high", "critical"]
      }
    },
    required: ["action"]
  }
}

Agent はこれを呼び出します。

Frontend は確認ダイアログを出します。

ユーザーが承認または拒否します。

その結果を Agent に返します。

公式ドキュメントでも、frontend-defined tools の利点として、frontend が利用可能な能力を決められること、ユーザー権限や application state に応じて tools を増減できること、agent は reasoning に集中し frontend が tool implementation を扱えること、sensitive operations を application 側で制御できることが説明されています。(AG-UI)

これはかなり大事です。

Agent に全部の権限を渡すのではなく、UI 側が「今このユーザーに許可できる操作」だけを tool として渡す。

これが Human-in-the-loop な Agent UI の基本になります。

Interruptsは「人間の介入」をプロトコル化する

Agent が実務で使われると、必ずこういう場面が出ます。

  • このメールを本当に送ってよいか
  • このデータを削除してよいか
  • この見積もりで進めてよいか
  • この契約条項を修正してよいか
  • 追加情報がないと続行できない

こういう時、Agent は勝手に進むべきではありません。

AG-UI では、これを Interrupts として扱います。

公式ドキュメントでは、Interrupts は human-in-the-loop pauses and resumes の仕組みであり、Agent が sensitive action の前に承認を求めたり、structured input を要求したり、policy decision を待つために pause できると説明されています。(AG-UI)

AG-UI の interrupt は、普通の一時停止ではありません。

Run が RUN_FINISHED で終わるときに、

{
  "outcome": {
    "type": "interrupt",
    "interrupts": [...]
  }
}

のように「interrupt outcome」として終了します。

その後、client は同じ thread で resume を含む新しい run を開始します。

公式ドキュメントでは、RunFinishedoutcomesuccess または interrupt を持ち、interrupt の場合は client が次の RunAgentInputresume array を含めて再開すると説明されています。(AG-UI)

ここがかなりよくできています。

Agent の実行を無理に同じ run に閉じ込めない。
人間の入力を受けたら、新しい run として再開する。
でも threadId と interruptId でつなぐ。

この設計なら、監査ログも取りやすいです。

Capabilitiesは「このAgentは何ができるか」をUIが知る仕組み

UI 側が Agent に接続するとき、何に対応しているか分からないと困ります。

この Agent は streaming できるのか。
tools を呼べるのか。
state delta を出せるのか。
reasoning を出せるのか。
multimodal input を受けられるのか。
human-in-the-loop に対応しているのか。

AG-UI では、これを capability discovery で扱います。

公式ドキュメントでは、agents は runtime に getCapabilities() を通じて自分が何をサポートしているか宣言でき、client はそれを見て UI や挙動を適応できると説明されています。(AG-UI)

たとえば、こういう判断ができます。

const capabilities = await agent.getCapabilities?.()

if (capabilities?.reasoning?.supported) {
  showReasoningPanel()
}

if (capabilities?.humanInTheLoop?.approvals) {
  enableApprovalWorkflow()
}

if (capabilities?.multimodal?.input?.image) {
  showImageUploadButton()
}

公式ドキュメントでも、capabilities は identity、transport、tools、output、state、multi-agent、reasoning、multimodal、execution、human-in-the-loop などのカテゴリに整理されています。(AG-UI)

これも実務ではかなり重要です。

Agent ごとにできることが違うなら、UI も変わるべきです。

対応していない機能を表示して、実行時に失敗するより、最初から capabilities を見て UI を出し分ける方が自然です。

Reasoningは「そのまま見せる」ではなく「見せ方と継続性を設計する」

AG-UI には Reasoning のサポートもあります。

ただし、これは「chain-of-thought を全部ユーザーに見せよう」という話ではありません。

公式ドキュメントでは、AG-UI の reasoning support は、reasoning visibility、state continuity、privacy compliance の3つの課題に対応するものだと説明されています。具体的には、raw chain-of-thought を露出せずに reasoning signals を見せること、encrypted reasoning items で会話ターンをまたいだ状態継続を可能にすること、zero data retention などの enterprise privacy requirements を支えることが挙げられています。(AG-UI)

つまり、AG-UI 的には reasoning も UI の一部です。

ただし、見せ方を選べます。

Full visibility:
  reasoningをそのまま表示する

Summary only:
  要約だけ表示し、詳細はencryptedValueで保持する

Hidden:
  reasoningは表示せず、encryptedValueだけで継続性を保つ

公式ドキュメントでも、visibility control として full visibility、summary only、hidden の考え方が説明されています。(AG-UI)

これはかなり現実的です。

ユーザーには「今なにをしているか」は見せたい。
でも raw chain-of-thought をそのまま出すべきではない。
一方で、モデル側には reasoning continuity が必要になる。

この間を埋めるのが AG-UI の Reasoning support です。

Serializationは「Agent UIを復元・分岐できる」ようにする

Agent UI は長く続くことがあります。

ページをリロードする。
接続が切れる。
途中から再開する。
別案を試す。
前の run から分岐する。

こういうことをするには、event stream を保存できる必要があります。

AG-UI では Serialization がその役割を持ちます。

公式ドキュメントでは、AG-UI の serialization は agent–UI session を駆動する event stream を persist / restore する標準的方法であり、chat history や UI state の復元、running agent への再接続、過去 run からの branching / time travel、history compaction を可能にすると説明されています。(AG-UI)

ここで面白いのは、parentRunId です。

parentRunId を使うと、同じ thread の中で git-like な lineage を作れます。

run1:
  東京旅行を計画して

run2:
  run1から分岐して、大阪旅行に変更して

run3:
  run1から分岐して、予算を半分にして

公式ドキュメントでも、parentRunId によって git-like append-only log を作り、branching / time travel を可能にすると説明されています。(AG-UI)

これは、Agent UI にとってかなり重要です。

なぜなら、Agent との作業は「1本の会話」ではなく、複数の試行錯誤になるからです。

MiddlewareはAG-UIを既存システムに合わせるための層

AG-UI を採用するとき、既存の Agent framework を全部作り直す必要はありません。

Middleware を使えば、既存の event stream を変換・フィルタ・拡張できます。

公式ドキュメントでは、AG-UI の middleware は agent を流れる event streams を transform、filter、augment する仕組みであり、logging、authentication、rate limiting、event filtering のような cross-cutting concerns を core agent logic を変えずに追加できると説明されています。(AG-UI)

たとえば、

  • ログを追加する
  • 特定の tool call をフィルタする
  • metadata を追加する
  • error handling を差し込む
  • rate limit をかける
  • debug mode のときだけ詳細イベントを出す

こういうことが middleware でできます。

公式ドキュメントでは、middleware は chain として動き、agent execution と event consumer の間でイベントを順番に処理すると説明されています。(AG-UI)

これは、実務導入でかなり効きます。

最初から完璧な AG-UI native agent を作らなくてもよい。
既存 framework の出力を middleware で AG-UI 互換にできる。

この柔軟さは大事です。

実装は2パターンある

AG-UI integration を作る方法は、大きく2つあります。

Server Implementation:
  AgentやserverがAG-UI eventsを直接emitする

Middleware Implementation:
  既存protocolや既存アプリをAG-UI eventsに変換する

公式の Quickstart でも、AG-UI integration は agent を AG-UI protocol で話せるようにするものであり、custom API を client ごとに作る代わりに、AG-UI を一度実装すれば compatible application と接続できると説明されています。また、実装方法として server implementation と middleware implementation の2つが整理されています。(AG-UI)

自分なら、こう判断します。

状況 選ぶもの
新しくAgent backendを作る Server Implementation
AG-UI eventsを細かく制御したい Server Implementation
既存Agent frameworkがある Middleware Implementation
既存APIをAG-UI対応させたい Middleware Implementation
直接イベントを出せない外部システムをつなぎたい Middleware Implementation

公式の server guide でも、server implementation は新しい agent を scratch から作る場合や、agent capabilities 専用サービスを作りたい場合に向いていると説明されています。(AG-UI)

まず触るなら何から始めるか

AG-UI を触るなら、いきなり大規模な Agent UI を作らなくていいと思います。

まずは、最小の event stream を出すところから始めるのがよいです。

RUN_STARTED
TEXT_MESSAGE_CHUNK
TEXT_MESSAGE_CHUNK
RUN_FINISHED

公式 Quickstart でも、AG-UI compatible server は request を受け取り、OpenAI の GPT-4o に接続し、AG-UI events として response を stream し、tool calls と state management を扱う例が示されています。(AG-UI)

アプリ側は、scaffold から始められます。

公式ドキュメントでは、AG-UI は npx create-ag-ui-app@latest による application scaffold を提供していると説明されています。(AG-UI)

個人的には、順番はこうです。

  1. 最小の chat streaming を作る
  2. text events を UI に表示する
  3. tool call events を表示する
  4. frontend-defined tool を1つ作る
  5. approval interrupt を入れる
  6. state snapshot / delta を入れる
  7. capabilities を実装する
  8. serialization で restore / branching を試す

この順番なら、AG-UI の本質がかなり分かりやすいです。

AG-UIで失敗しやすいところ

1. ただのチャットストリーミングとして扱う

AG-UI を TEXT_MESSAGE_CONTENT だけで使うと、かなりもったいないです。

それなら普通の SSE チャットでもできます。

AG-UI の価値は、

  • state
  • tools
  • interrupts
  • activity
  • reasoning
  • capabilities
  • serialization

まで含めて、Agent UI をイベントとして設計できるところにあります。

2. frontend-defined tools を何でも渡す

frontend-defined tools は便利ですが、渡しすぎると危険です。

ユーザー権限。
現在の画面。
業務コンテキスト。
承認が必要な操作。

これらに応じて、渡す tool を変えるべきです。

AG-UI では client-defined tools によって frontend が利用可能な能力を制御できるため、ここを設計しないと安全性が崩れます。(AG-UI)

3. shared state に機密情報を入れる

State は便利ですが、何でも入れてよいわけではありません。

公式ドキュメントの best practices でも、shared state に sensitive information を保存しないよう注意されています。(AG-UI)

UI と Agent の両方が見る state なので、入れる情報は慎重に選ぶべきです。

4. interrupt を UI の都合だけで実装する

Interrupt は単なる modal 表示ではありません。

interruptId、threadId、resume、responseSchema、expiresAt、audit trail まで含めて設計する必要があります。

公式ドキュメントでも、resume は同じ threadId で行うこと、すべての open interrupts を address すること、payload validation や idempotency を考慮することなどの contract rules が示されています。(AG-UI)

5. capabilities を実装しない

最初は固定 UI でも動きます。

でも、Agent が増えると capabilities がないとつらくなります。

この Agent は画像入力に対応しているのか。
この Agent は approval を出せるのか。
この Agent は reasoning を表示できるのか。

これを hardcode し始めると、すぐ壊れます。

Capabilities を使って UI を適応させる方がよいです。

まとめ

AG-UI は、AI Agent とユーザー向けアプリケーションをつなぐためのイベントベースプロトコルです。

ただし、本質は「AIチャットUIを作ること」ではありません。

本当に大事なのは、

  • Agent の実行をイベント列として扱う
  • text、tool、state、activity、reasoning を分けて流す
  • frontend-defined tools で UI 側の能力を Agent に渡す
  • shared state で Agent と UI を同期する
  • interrupts で human-in-the-loop をプロトコル化する
  • capabilities で UI を Agent ごとに適応させる
  • serialization で復元・分岐・time travel を可能にする
  • generative UI specs と競合せず、それらを運ぶ runtime connection になる

という点です。

Agent Skills は、AI に仕事のやり方を渡します。
MCP は、AI と外部 tools/data をつなぎます。
Codex Plugin は、それらを配布可能にします。
A2A は、Agent 同士をつなぎます。
AG-UI は、Agent とユーザー体験をつなぎます。

これから AI Agent を実務アプリに組み込むなら、モデルの回答品質だけでは足りません。

重要になるのは、

Agent が今何をしていて、ユーザーがどこで介入できて、UI がどう状態を共有するか

を設計する力です。

AG-UI は、そのためのかなり重要なレイヤーになると思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?