Streaming ist das Kernfeature des Vercel AI SDK — es verwandelt langsame LLM-Responses in interaktive, sofort sichtbare Ausgaben. In dieser Lektion vertiefen wir Server-Side Streaming, React Server Components und Generative UI.
Das AI SDK nutzt den Web Streams API-Standard:
Client (useChat) → HTTP POST → Route Handler → AI SDK → LLM Provider
← ReadableStream ← streamText ← Token-Stream
import { streamText } from 'ai'
import { anthropic } from '@ai-sdk/anthropic'
export async function POST(req: Request) {
const { messages } = await req.json()
const result = streamText({
model: anthropic('claude-sonnet-4-20250514'),
system: 'Du bist ein hilfreicher Assistent für deutsche Nutzer.',
messages,
maxTokens: 2000,
temperature: 0.7,
onFinish: async ({ text, usage }) => {
// Logging, Datenbank-Speicherung, Analytics
console.log(`Tokens: ${usage.totalTokens}`)
await saveToDatabase(text)
},
})
return result.toDataStreamResponse()
}
Das AI SDK bietet granulare Callbacks für den Stream-Lebenszyklus:
React Server Components ermöglichen Server-Side-Rendering mit Streaming:
// app/[locale]/ai/page.tsx
import { generateText } from 'ai'
import { openai } from '@ai-sdk/openai'
export default async function AIPage() {
const { text } = await generateText({
model: openai('gpt-4.1'),
prompt: 'Erstelle eine Zusammenfassung der neuesten AI-Trends.',
})
return (
<article>
<h1>AI-Trends 2026</h1>
<div>{text}</div>
</article>
)
}
Für progressive Loading-Erfahrungen:
import { Suspense } from 'react'
export default function Page() {
return (
<div>
<h1>Dashboard</h1>
<Suspense fallback={<LoadingSkeleton />}>
<AIInsights />
</Suspense>
</div>
)
}
Statt nur Text zu streamen, generiert das AI SDK React-Komponenten als Antwort:
import { streamUI } from 'ai/rsc'
import { openai } from '@ai-sdk/openai'
const result = await streamUI({
model: openai('gpt-4.1'),
prompt: 'Zeige mir das aktuelle Wetter in Berlin.',
tools: {
getWeather: {
description: 'Zeigt das aktuelle Wetter für eine Stadt an',
parameters: z.object({ city: z.string() }),
generate: async function*({ city }) {
yield <WeatherSkeleton />
const weather = await fetchWeather(city)
return <WeatherCard data={weather} />
},
},
},
})
Der Nutzer sieht: Erst ein Loading-Skeleton, dann eine fertige Wetter-Karte — nicht nur Text "Es ist 15°C in Berlin", sondern eine interaktive UI-Komponente.
| Strategie | UX | Implementierung |
|---|---|---|
| Skeleton | Platzhalter-Layout | CSS/Tailwind Animate |
| Typing Indicator | "AI tippt..." | Einfacher Indikator |
| Progressive Rendering | Text erscheint wortweise | Stream-basiert (Standard) |
| Optimistic UI | Sofortige Platzierung, Update bei Antwort | React Optimistic |
'use client'
import { useChat } from 'ai/react'
export function Chat() {
const { messages, error, reload } = useChat()
if (error) {
return (
<div className="text-red-500">
<p>Fehler: {error.message}</p>
<button onClick={reload}>Erneut versuchen</button>
</div>
)
}
// ... Chat-UI
}
Wrappen Sie AI-Komponenten in Error Boundaries:
UX-Regel: Der Nutzer sollte niemals eine leere Seite sehen. Jeder Zustand — Loading, Error, Empty, Success — braucht ein dediziertes UI. Streaming macht die Loading-Phase angenehm, aber Error States müssen Sie selbst designen.