ai-sdk-ui について
ai-sdk-ui は、Vercel AI SDK を使う React 開発者向けの UI スキルです。ストリーミングチャット、ツール承認、構造化出力、移行時のトラブル対応を扱います。
主な機能
- 01React のチャット・補完フック
- 02ストリーミングと構造化出力
- 03ツール呼び出しと承認フロー
- 04ファイル添付とメッセージ保存
- 05移行ガイドとエラー対処
活用シーン
- 01React や Next.js の AI チャット UI 構築
- 02ストリーミング応答やツール呼び出しの表示
- 03ツール実行前のユーザー承認
- 04useChat 連携の問題解決
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill ai-sdk-uiインストール後、Claude Code で/ai-sdk-uiを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.md.claude-plugin/plugin.jsonreferences/links-to-official-docs.mdnextjs-integration.mdstreaming-patterns.mdtop-ui-errors.mduse-chat-migration.mdrules/ai-sdk-ui.mdscripts/check-versions.shtemplates/custom-message-renderer.tsxmessage-persistence.tsxnextjs-api-route.tsnextjs-chat-app-router.tsxnextjs-chat-pages-router.tsxpackage.jsonuse-chat-attachments.tsxuse-chat-basic.tsxuse-chat-tools.tsxuse-completion-basic.tsxuse-object-streaming.tsx詳細
AI SDK UI - フロントエンド React フック
Vercel AI SDK v6 を使用した、AI 搭載ユーザーインターフェース向けのフロントエンド React フックです。
バージョン:AI SDK v6.0.42(安定版) フレームワーク:React 18+/19、Next.js 14+/15+ 最終更新日:2026-01-20
AI SDK v6 安定版(2026年1月)
**ステータス:**安定版リリース **最新バージョン:**[email protected]、@ai-sdk/[email protected]、@ai-sdk/[email protected] **移行:**v5 から v6 への破壊的変更は最小限です
v6 の新しい UI 機能
1. メッセージパーツ構造(破壊的変更)
v6 では、メッセージの内容は .content ではなく .parts 配列から取得します。
// ❌ v5 (OLD)
{messages.map(m => (
<div key={m.id}>{m.content}</div>
))}
// ✅ v6 (NEW)
{messages.map(m => (
<div key={m.id}>
{m.parts.map((part, i) => {
if (part.type === 'text') return <span key={i}>{part.text}</span>;
if (part.type === 'tool-invocation') return <ToolCall key={i} tool={part} />;
if (part.type === 'file') return <FilePreview key={i} file={part} />;
return null;
})}
</div>
))}
パーツの種類:
text-.textプロパティを持つテキストコンテンツtool-invocation-.toolName、.args、.resultを持つツール呼び出しfile-.mimeType、.dataを持つファイル添付reasoning- モデルの推論(利用可能な場合)source- ソースの引用
3. エージェントとの連携
InferAgentUIMessage<typeof agent> を使った型安全なエージェントとのメッセージング:
import { useChat } from '@ai-sdk/react';
import type { InferAgentUIMessage } from 'ai';
import { myAgent } from './agent';
export default function AgentChat() {
const { messages, sendMessage } = useChat<InferAgentUIMessage<typeof myAgent>>({
api: '/api/chat',
});
// messages are now type-checked against agent schema
}
4. ツール承認ワークフロー(Human-in-the-Loop) ツールを実行する前にユーザーの確認を求めます。
import { useChat } from '@ai-sdk/react';
import { useState } from 'react';
export default function ChatWithApproval() {
const { messages, sendMessage, addToolApprovalResponse } = useChat({
api: '/api/chat',
});
const handleApprove = (toolCallId: string) => {
addToolApprovalResponse({
toolCallId,
approved: true, // or false to deny
});
};
return (
<div>
{messages.map(message => (
<div key={message.id}>
{message.toolInvocations?.map(tool => (
tool.state === 'awaiting-approval' && (
<div key={tool.toolCallId}>
<p>Approve tool call: {tool.toolName}?</p>
<button onClick={() => handleApprove(tool.toolCallId)}>
Approve
</button>
<button onClick={() => addToolApprovalResponse({
toolCallId: tool.toolCallId,
approved: false
})}>
Deny
</button>
</div>
)
))}
</div>
))}
</div>
);
}
5. 自動送信機能 承認を処理した後、会話を自動的に続行します。
import { useChat, lastAssistantMessageIsCompleteWithApprovalResponses } from '@ai-sdk/react';
export default function AutoSubmitChat() {
const { messages, sendMessage } = useChat({
api: '/api/chat',
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,
// Automatically resubmit after all approval responses provided
});
}
6. チャットでの構造化出力
ツール呼び出しと同時に構造化データを生成します(以前は useObject でのみ利用可能でした)。
import { useChat } from '@ai-sdk/react';
import { z } from 'zod';
const schema = z.object({
summary: z.string(),
sentiment: z.enum(['positive', 'neutral', 'negative']),
});
export default function StructuredChat() {
const { messages, sendMessage } = useChat({
api: '/api/chat',
// Server can now stream structured output with chat messages
});
}
useChat フック - v4 から v5 への破壊的変更
重要:v5 では useChat が入力状態を管理しなくなりました!
v4(旧版 - 使用しないでください):
const { messages, input, handleInputChange, handleSubmit, append } = useChat();
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
</form>
v5(新版 - 正しい使用方法):
const { messages, sendMessage } = useChat();
const [input, setInput] = useState('');
<form onSubmit={(e) => {
e.preventDefault();
sendMessage({ content: input });
setInput('');
}}>
<input value={input} onChange={(e) => setInput(e.target.value)} />
</form>
v5 の変更点の概要:
- 入力管理の削除:
input、handleInputChange、handleSubmitはなくなりました append()からsendMessage()へ:メッセージを送信する新しいメソッドですonResponseの削除:代わりにonFinishを使用しますinitialMessagesから制御モードへ:完全に制御するにはmessagesプロパティを使用しますmaxStepsの削除:サーバー側でのみ処理してください
完全な移行ガイドについては、references/use-chat-migration.md を参照してください。
useAssistant フック(非推奨)
⚠️ 非推奨のお知らせ:
useAssistantは AI SDK v5 で非推奨になりました。OpenAI Assistants API v2 は 2026 年 8 月 26 日に提供終了となります。新しいプロジェクトでは、代わりにカスタムのバックエンドロジックとuseChatを使用してください。 移行方法については、openai-assistants スキルを参照してください。
UI の状態を自動管理しながら、OpenAI 互換のアシスタント API とやり取りします。
インポート:
import { useAssistant } from '@ai-sdk/react';
基本的な使い方:
'use client';
import { useAssistant } from '@ai-sdk/react';
import { useState, FormEvent } from 'react';
export default function AssistantChat() {
const { messages, sendMessage, isLoading, error } = useAssistant({
api: '/api/assistant',
});
const [input, setInput] = useState('');
const handleSubmit = (e: FormEvent) => {
e.preventDefault();
sendMessage({ content: input });
setInput('');
};
return (
<div>
{messages.map(m => (
<div key={m.id}>
<strong>{m.role}:</strong> {m.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
disabled={isLoading}
/>
</form>
{error && <div>{error.message}</div>}
</div>
);
}
ユースケース:
- OpenAI Assistant を活用した UI の構築
- アシスタントのスレッドと実行の管理
- UI の状態を管理しながらアシスタントの応答をストリーミング
- ファイル検索やコードインタープリターとの連携
完全な API リファレンスについては、公式ドキュメントを参照してください:https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-assistant
UI でよくあるエラーと解決方法
詳細については、references/top-ui-errors.md を参照してください。簡易リファレンス:
1. useChat でストリームの解析に失敗する
エラー:SyntaxError: Unexpected token in JSON at position X
原因:API ルートが適切なストリーム形式を返していません。
解決方法:
// ✅ CORRECT
return result.toDataStreamResponse();
// ❌ WRONG
return new Response(result.textStream);
2. useChat が応答しない
原因:API ルートが正しくストリーミングしていません。
解決方法:
// App Router - use toDataStreamResponse()
export async function POST(req: Request) {
const result = streamText({ /* ... */ });
return result.toDataStreamResponse(); // ✅
}
// Pages Router - use pipeDataStreamToResponse()
export default async function handler(req, res) {
const result = streamText({ /* ... */ });
return result.pipeDataStreamToResponse(res); // ✅
}
3. デプロイ後にストリーミングが機能しない
原因:デプロイプラットフォームが応答をバッファリングしています。
解決方法:Vercel はストリーミングを自動検出します。他のプラットフォームでは設定が必要な場合があります。
4. useChat で body の値が古いままになる
原因:body オプションが初回のレンダー時にのみ取得されています。
解決方法:
// ❌ WRONG - body captured once
const { userId } = useUser();
const { messages } = useChat({
body: { userId }, // Stale!
});
// ✅ CORRECT - use controlled mode
const { userId } = useUser();
const { messages, sendMessage } = useChat();
sendMessage({
content: input,
data: { userId }, // Fresh on each send
});
5. React の最大更新深度エラー
原因:useEffect で無限ループが発生しています。
解決方法:
// ❌ WRONG
useEffect(() => {
saveMessages(messages);
}, [messages, saveMessages]); // saveMessages triggers re-render!
// ✅ CORRECT
useEffect(() => {
saveMessages(messages);
}, [messages]); // Only depend on messages
よくあるエラーをさらに 13 件(合計 18 件)掲載しています。詳細については、references/top-ui-errors.md を参照してください。
ストリーミングのベストプラクティス
パフォーマンス
より良い UX のため、常にストリーミングを使用してください:
// ✅ GOOD - Streaming (shows tokens as they arrive)
const { messages } = useChat({ api: '/api/chat' });
// ❌ BAD - Non-streaming (user waits for full response)
const response = await fetch('/api/chat', { method: 'POST' });
UX パターン
読み込み状態を表示する:
{isLoading && <div>AI is typing...</div>}
停止ボタンを用意する:
{isLoading && <button onClick={stop}>Stop</button>}
最新のメッセージまで自動スクロールする:
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
読み込み中は入力を無効にする:
<input disabled={isLoading} />
包括的なベストプラクティスについては、references/streaming-patterns.md を参照してください。
React Strict Mode に関する考慮事項
React Strict Mode では、バグを検出するため、意図的にエフェクトを二重に呼び出します。エフェクト内で useChat または useCompletion を使用する場合(自動再開、初期メッセージなど)は、重複した API 呼び出しやトークンの浪費を防ぐため、二重実行をガードしてください。
問題:
'use client';
import { useChat } from '@ai-sdk/react';
import { useEffect } from 'react';
export default function Chat() {
const { messages, sendMessage, resumeStream } = useChat({
api: '/api/chat',
resume: true,
});
useEffect(() => {
// ❌ Triggers twice in strict mode → two concurrent streams
sendMessage({ content: 'Hello' });
// or
resumeStream();
}, []);
}
解決策:
// ✅ Use ref to track execution
import { useRef } from 'react';
const hasSentRef = useRef(false);
useEffect(() => {
if (hasSentRef.current) return;
hasSentRef.current = true;
sendMessage({ content: 'Hello' });
}, []);
// For resumeStream specifically:
const hasResumedRef = useRef(false);
useEffect(() => {
if (!autoResume || hasResumedRef.current || status === 'streaming') return;
hasResumedRef.current = true;
resumeStream();
}, [autoResume, resumeStream, status]);
発生する理由: React Strict Mode は、副作用を明らかにするため、エフェクトを二重に呼び出します。SDK は同時リクエストをガードしないため、どちらの呼び出しも個別のストリームを作成し、状態更新を取り合います。
影響: メッセージの重複、トークン使用量の倍増、TypeError: "Cannot read properties of undefined (reading 'state')" を引き起こす競合状態。
出典: GitHub Issue #7891、Issue #6166
このスキルを使用する場合
ai-sdk-ui を使用する場合:
- React のチャットインターフェースを構築する
- UI に AI 補完機能を実装する
- AI の応答をフロントエンドにストリーミングする
- Next.js の AI アプリケーションを構築する
- チャットメッセージの状態を処理する
- UI にツール呼び出しを表示する
- AI でファイル添付を管理する
- v4 から v5 に移行する(UI フック)
- useChat/useCompletion のエラーが発生している
使用しない場合:
- バックエンドの AI 機能が必要 → ai-sdk-core を使用してください
- React 以外のフロントエンド(Svelte、Vue)を構築する → 公式ドキュメントを確認してください
- Generative UI / RSC が必要 → https://ai-sdk.dev/docs/ai-sdk-rsc を参照してください
- ネイティブアプリを構築する → 別の SDK が必要です
関連スキル:
- ai-sdk-core - バックエンドのテキスト生成、構造化出力、ツール、エージェント
- フルスタックの AI アプリケーションには、両方を組み合わせてください
パッケージのバージョン
安定版(v6 - 推奨):
{
"dependencies": {
"ai": "^6.0.8",
"@ai-sdk/react": "^3.0.6",
"@ai-sdk/openai": "^3.0.2",
"react": "^18.3.0",
"zod": "^3.24.2"
}
}
レガシー版(v5):
{
"dependencies": {
"ai": "^5.0.99",
"@ai-sdk/react": "^1.0.0",
"@ai-sdk/openai": "^2.0.68"
}
}
バージョンに関する注意事項:
- AI SDK v6.0.6(安定版、2026年1月) - 新規プロジェクトに推奨
- AI SDK v5.x(レガシー) - 引き続きサポートされていますが、新機能は追加されません
- React 18.3 以降 / React 19 をサポート
- Next.js 14 以降 / 15 以降を推奨
- スキーマ検証には Zod 3.24.2 以降
公式ドキュメントへのリンク
コア UI フック:
- AI SDK UI の概要:https://ai-sdk.dev/docs/ai-sdk-ui/overview
- useChat:https://ai-sdk.dev/docs/ai-sdk-ui/chatbot
- useCompletion:https://ai-sdk.dev/docs/ai-sdk-ui/completion
- useObject:https://ai-sdk.dev/docs/ai-sdk-ui/object-generation
高度なトピック(リンクのみ):
- Generative UI(RSC):https://ai-sdk.dev/docs/ai-sdk-rsc/overview
- ストリームプロトコル:https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocols
- メタデータを含むメッセージ:https://ai-sdk.dev/docs/ai-sdk-ui/message-metadata
Next.js との連携:
- Next.js App Router:https://ai-sdk.dev/docs/getting-started/nextjs-app-router
- Next.js Pages Router:https://ai-sdk.dev/docs/getting-started/nextjs-pages-router
移行とトラブルシューティング:
- v4→v5 の移行:https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
- トラブルシューティング:https://ai-sdk.dev/docs/troubleshooting
- よくある問題:https://ai-sdk.dev/docs/troubleshooting/common-issues
Vercel へのデプロイ:
- Vercel Functions:https://vercel.com/docs/functions
- Vercel でのストリーミング:https://vercel.com/docs/functions/streaming
テンプレート
このスキルには、templates/ に以下のテンプレートが含まれています。
- use-chat-basic.tsx - 手動入力による基本的なチャット(v5 のパターン)
- use-chat-tools.tsx - ツール呼び出し UI のレンダリングに対応したチャット
- use-chat-attachments.tsx - ファイル添付のサポート
- use-completion-basic.tsx - 基本的なテキスト補完
- use-object-streaming.tsx - 構造化データのストリーミング
- nextjs-chat-app-router.tsx - Next.js App Router の完全な例
- nextjs-chat-pages-router.tsx - Next.js Pages Router の完全な例
- nextjs-api-route.ts - App Router と Pages Router の両方に対応する API ルート
- message-persistence.tsx - チャット履歴の保存と読み込み
- custom-message-renderer.tsx - Markdown に対応したカスタムメッセージコンポーネント
- package.json - 依存関係のテンプレート
参考ドキュメント
references/ を参照してください。
- use-chat-migration.md - v4 から v5 への完全な移行ガイド
- streaming-patterns.md - UI ストリーミングのベストプラクティス
- top-ui-errors.md - よくある UI エラー 18 件と解決策
- nextjs-integration.md - Next.js のセットアップパターン
- links-to-official-docs.md - 公式ドキュメントへのリンク集
本番環境でのテスト済み:WordPress Auditor (https://wordpress-auditor.webfonts.workers.dev) 最終確認日:2026-01-20 | スキルのバージョン:3.1.0 | 変更点:AI SDK v6.0.42 に更新(+19 件のパッチ)。React Strict Mode のセクションを追加。Issue #7(stale body)に回避策を 3 件追加。新たな問題を 6 件追加:resume+onFinish での TypeError(#13)、concurrent sendMessage による state の破損(#14)、tool approval callback のエッジケース(#15)、早期停止時の ZodError(#16)、convertToModelMessages の tool approval バグ(#17)、undefined id による無限ループ(#18)。エラー数:12→18。