agent-ui について
agent-ui は、モデルを使う AI 製品のインターフェース設計者向けのガイドです。ストリーミング中の状態を正直に示し、ツール呼び出しや承認、エラー、中断可能な生成を扱います。
主な機能
- 01ストリーミングと部分出力の表示
- 02入力欄とキーボード操作の設計
- 03推論とツール呼び出しの表示
- 04インライン承認とソースの表示
- 05スクロール、失敗、復旧への対応
活用シーン
- 01ストリーミングチャット画面の設計
- 02エージェントのツール動作と承認の表示
- 03停止または失敗した生成への対応
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ paragonhq/ stealth-skills --skill agent-uiインストール後、Claude Code で/agent-uiを入力して読み込まれたか確認します。
詳細
agent-ui
モデルを背後に持つインターフェースには、ほかのすべてのものにはない状態がもう一つあります。処理中で、出力が一部表示され、長さがわからない状態です。ここにあるすべてのパターンは、その状態を誠実に扱うことから生まれています。
原則
- 作業内容は折りたたんで表示します。 推論、ツール呼び出し、ソースは必要に応じて確認できるようにし、隠したり、強制的に開いたりしません。
- ユーザーはいつでも停止できます。 すべての生成に、常に同じ場所にあり、Escapeで操作できる停止コントロールを設けます。
- 進捗を偽装しません。 意味のないスピナーや、タイマーにすぎない「考え中」、実際のストリームより遅いタイプライター効果は使いません。
- 入力欄は常に使えます。 現在のメッセージがストリーミング中に次のメッセージを作成するのは自然なことです。
- 出力はログではなくドキュメントです。 Markdownをレンダリングし、実際のコードブロックを使い、レイアウトを安定させます。
入力欄
- 既定では複数行にし、6~8行まで拡大してからスクロールします。モデル用の入力欄を単一行にしてはいけません。
- デスクトップでは
Enterで送信し、Shift+Enterで改行します。スマートフォンでは送信ボタンを設け、Enterで改行します。 - 添付ファイル、モデルやモードの選択、スラッシュコマンドは、テキストの下にある同じボックス内の行に配置し、あちこちに散らしません。
- ストリーミング中は送信ボタンを停止ボタンに切り替えます。位置とサイズは変えません。
- 下書きは再読み込みやルート変更後も保持されます。
- 送信後、停止後、ダイアログを閉じた後は、フォーカスを入力欄に戻します。
- 文字数やトークン数の上限は、上限の10%以内に近づいた場合にのみ表示します。
テキストのストリーミング
- トークンの到着に合わせてDOMに追加し、トークンごとにメッセージ全体を再レンダリングしません。ストリームがそれより速い場合は、アニメーションフレーム(約16ms)ごとにまとめて処理します。
- 文字を一つずつアニメーション表示しません。現在の行末に控えめなカーソルブロックを表示するだけで、「まだ続いている」ことが伝わります。
- Markdownは、閉じられていないブロックを許容するパーサーで逐次レンダリングします。閉じられていないコードフェンスは、バッククォートの段落ではなくコードブロックとして表示します。
- あらかじめ領域を確保しません。メッセージは伸びていきます。ただし、コンテナーのスクロール位置が急に飛ばないようにします(「スクロール」を参照)。
- 長い出力では、コードが約40行に達したら、ストリームが完了してから「さらに表示」で折りたたみます。ストリーム中には折りたたみません。
思考と推論
- 処理中は折りたたまれた1行で「思考中…」と表示し、2秒後に経過時間を表示します。段落をきらめかせる表示にはしません。
- 展開すると推論テキストを表示します。回答より小さいサイズで、等幅フォントまたは控えめな色を使います。
- 回答が始まったら、思考ブロックを所要時間付きの1行(「8秒間思考しました」)に折りたたみ、そのまま表示します。
- モデルが表示する内容を返さない場合、偽の「思考中」アニメーションは使いません。シンプルな経過時間表示を使います。
ツール呼び出し
各呼び出しは、メッセージの流れの中にコンパクトな行として表示します。
▸ Read src/components/Button.tsx 120ms ✓
▸ Search "focus-visible" in src/ 3 hits ✓
▸ Edit src/components/Button.tsx running…
- アイコンまたは動詞、対象、ステータスを表示します。ステータスには、実行中、完了(結果の要約付き)、失敗(エラー付き、展開可能)があります。
- カードではなくチップまたは行を使います。連続する呼び出しはグループ化し、10件の読み取りは「ファイルを10件読み取り ▸」のように折りたたみます。
- 展開すると、未加工の入力と出力を、コピー可能なスクロール式の等幅フォントで表示します。
- 実行中の呼び出しには、独自の行に小さな確定的または不確定的なインジケーターを表示します。メッセージ全体をスピナー表示にはしません。
- 失敗してもレイアウトを止めません。失敗した呼び出しはその場に残し、モデルの次のメッセージで説明します。
承認
エージェントが影響を伴う操作(ファイルの書き込み、メールの送信、コマンドの実行、金銭の支払いなど)を実行しようとするときは、次のようにします。
- モーダルではなく、流れの中にブロックを配置し、実行したい操作、正確な対象、許可/拒否を表示します。「このセッション中は許可する」は任意です。
- キーボード操作:ブロックにフォーカスがあるとき、Enterで許可し、Escapeで拒否します。ブロックの表示時にフォーカスを移します。
- 決定後、ブロックは「許可済み:
npm testを実行」のような1行に折りたたみます。 - ユーザーの反応が遅いからといって、自動承認してはいけません。タイムアウト時は拒否します。
- ファイルへの書き込みでは差分を、メッセージでは宛先を、支出では金額を表示します。
ソースと引用
- インラインマーカー(
[1])はメッセージ末尾のソース一覧にリンクします。マーカーにカーソルを合わせると、ソースをプレビューできます。 - ソース一覧にはファビコン、タイトル、ホストが表示されます。クリックすると新しいタブで開きます。
- ソースからの引用は、左側の境界線と控えめな色で視覚的に区別され、短く表示されます。
- ソースがなければ、ソースがあるかのように示しません。根拠のないテキストには引用 UI を表示しないでください。
メッセージの操作
ホバー時(タッチ操作では常時)に、コピー、再生成、編集して再送信(ユーザーメッセージ)、評価ボタンを表示します。メッセージの下に並ぶ小さなアイコンボタンは、押下領域を 28px とし、レイアウトをずらさずに表示されるよう、行の高さを確保してください。
コピーでは、レンダリングされたテキストではなく Markdown ソースをコピーし、アイコンの切り替えで完了を知らせます。
スクロール
- ストリーミング中に最下部へ固定するのは、ユーザーがすでに最下部にいる場合だけです。ユーザーが上へスクロールした時点で、固定を止めてください。
- 固定されていない状態で新しいコンテンツが届いたら、「↓ 最新へジャンプ」ピルを表示します。
- ユーザーの新しいメッセージは、そのメッセージがビューポートの先頭に来るようスクロールし、その下に返信が伸びる余地を残します。
- 画像やコードブロックのレンダリングによって古いコンテンツがずれないよう、ビューポートより上のコンテンツには
overflow-anchorと安定した高さを設定します。
レイテンシ
- 最初のトークンが届くまでに 400ms を超える場合は、カーソル付きの空の吹き出しをアシスタントのメッセージとしてすぐに表示します。ターンの開始を示すためにコンテンツの表示を待たないでください。
- ツールを多用するターンでは、ツールの行そのものが進行状況のインジケーターになります。
- レート制限やキューがある場合は、分かっていれば所要時間も含めて知らせます。「キュー内、約 20 秒」は、スピナーだけを表示するより適切です。
エラーと中断
- ユーザーが停止した場合:途中までのメッセージを残し、「停止」と表示します。続きから再開できます。
- ストリームの途中で失敗した場合:途中までのメッセージを残し、その下にエラーと、同じプロンプトを再送信する「再試行」を表示します。
- コンテキストの上限:到達後ではなく、到達前に警告します。要約するか、新しく始めるかを提案します。
- 失敗しても、ユーザーの最後のメッセージを消さないでください。
Markdown のレンダリング
- コードブロック:言語ラベル、コピー ボタン、横スクロール、折り返しなし、12.5〜13px の等幅フォントを使用し、ストリーム終了後は約 30 行を超える部分を折りたたみます。
- 表:画面が狭い場合は横スクロールにし、ヘッダー行を区別し、数値には等幅の数字を使用します。
- 返信内の見出しは、アプリの見出しより 1〜2 段階小さくします。返信はページではありません。
- リンクは外部リンクのマーカーを付けて新しいタブで開きます。
- サニタイズします。レンダリングされた出力は信頼できないものとして扱います。
マルチエージェントと長時間実行
- 実行には、ステータス、経過時間、停止操作を含むヘッダーを付けます。ステップはツール呼び出しの行で示し、フェーズごとにまとめます。
- バックグラウンド実行は、小さな永続インジケーター(ナビゲーション項目上のドット)で知らせ、完了時にはモーダルではなく通知を表示します。
- 履歴には、ステータスと 1 行の要約を付けた実行の一覧を表示し、検索できるようにします。
誠実さ
- 使用中のモデルとモードを明示します。メッセージが編集または再生成された場合は、そのことを表示します。
- エージェントが実行したことと、エージェントが実行したと述べていることを区別します。ツールの行が事実を示し、文章はあくまで文章です。
- 何も起きないまま「作業中…」が 30 秒続くのは不具合です。何が起きているのかを表示するか、行き詰まっていると伝えてください。
チェックリスト
- 停止操作は常に表示され、Escape キーが機能する
- 入力欄が伸縮し、入力内容が保持され、フォーカスが戻る
- ストリーミングはフレーム単位でまとめ、1 文字ごとのアニメーションを行わない
- 思考表示は所要時間を示す 1 行に折りたたまれる
- ツール呼び出しはステータス付きの行で表示され、グループを折りたためる
- 承認操作はインラインで、キーボードから操作でき、タイムアウト時は拒否される
- スクロール固定は最下部にいる場合のみ行い、それ以外ではジャンプ用ピルを表示する
- 停止や失敗の後も、途中までの出力が残る
- Markdown はサニタイズされ、コードブロックをコピーでき、表をスクロールできる
- ユーザーに理由が見えないまま、何かがスピナーを回し続けることがない
カタログから
- Beautiful UI — トレース、ツールチップ、承認をプリミティブとして提供します。
- AI Elements — AI SDK のチャット、推論、ソース用コンポーネントです。
- assistant-ui、prompt-kit — 組み合わせて使えるチャット用プリミティブです。
- AICSS — React、Vue、Svelte で思考状態、ツール呼び出し、引用を扱えます。
- Amelia Wattenberger — チャットボックスを超えた AI 向けインターフェースについての記事です。
- 詳しくは stealth.pm/components をご覧ください。
コメント
Markdown 対応