Ein Fintech-Client rief mich Ende 2023 an, echte Panik in seiner Stimme, weil sein Dev-Team sechs Wochen damit verbracht hatte, eine Streaming-Chat-Oberfläche auf OpenAIs API zu bauen und sie funktionierte immer noch nicht auf Mobile Safari. Race Conditions. Token-Chunking-Probleme. Die UI würde mitten in einer Antwort einfrieren. Sechs Wochen. Ich sah mir ihre Codebasis an und es war genau das, was man erwarten würde: eine handgerollte ReadableStream-Implementierung, eine maßgeschneiderte State-Management-Schicht für die Streaming-Tokens, Retry-Logik kopiert von einer drei Jahre alten Stack-Overflow-Antwort. Das Ding hielt zusammen mit Klebeband.ReadableStream implementation, a bespoke state management layer for the streaming tokens, retry logic copied from a three-year-old Stack Overflow answer. The thing was held together with tape.
Ich habe den Kern davon mit dem Vercel AI SDK in etwa zwei Tagen neu geschrieben. Streaming funktionierte. Mobile Safari funktionierte. Der Client hörte auf anzurufen.Vercel AI SDK in about two days. Streaming worked. Mobile Safari worked. The client stopped ringing.
Das ist kein Pitch. Das ist nur, was passiert ist. Und deshalb möchte ich durchgehen, was dieses SDK wirklich tut, wo es dir wirklich Zeit spart und wo du immer noch auf Mauern treffen wirst.
Was das Vercel AI SDK eigentlich ist
Menschen hören „Vercel AI SDK" und nehmen an, es ist in Vercel-Infrastruktur gesperrt. Das ist es nicht. Du kannst es auf jedem Node.js-Server ausführen, einschließlich deinem eigenen VPS, Railway, Render, überall. Was es eigentlich ist: eine TypeScript-Bibliothek, die die unangenehmsten Teile des Aufbaus von LLM-gestützten Features in eine Web-App abstrahiert.
Es gibt zwei Hauptpakete, auf die du zugreifen wirst. ai ist die Core Runtime. @ai-sdk/openai (oder @ai-sdk/anthropic, @ai-sdk/google, etc.) sind die Provider-Adapter. Das SDK nutzt eine einheitliche Schnittstelle, sodass der Wechsel von GPT-4o zu Claude 3.5 Sonnet in den meisten Fällen wirklich eine Einzeiler-Änderung ist. Ich habe das getestet. Es funktioniert.ai is the core runtime. @ai-sdk/openai (or @ai-sdk/anthropic , @ai-sdk/google, etc.) are the provider adapters. The SDK uses a unified interface so switching from GPT-4o to Claude 3.5 Sonnet is genuinely a one-line change in most cases. I've tested this. It holds up.
Die Core Primitives
Drei Dinge bilden das Herz des SDK:
streamText streamt eine Textantwort Token für Token, ideal für Chat-Interfaces, streams a text response token by token, ideal for chat interfacesgenerateText wartet auf die vollständige Antwort, gut für Hintergrund-Jobs oder wenn du keine Streaming-UX brauchst, waits for the full response, good for background jobs or when you don't need streaming UXgenerateObject gibt strukturiertes JSON zurück, das gegen ein Zod-Schema validiert wird – das ist der Punkt, an dem es richtig interessant wird, returns structured JSON validated against a Zod schema, which is where things get properly interesting
streamText ist das, was die meisten Leute zuerst wollen. Es kümmert sich um die ReadableStream-Installationen, die Kodierung und das Chunking. Dieser sechswöchige Fintech-Albtraum, den ich erwähnt habe? Das ist genau das, was streamText vom ersten Tag an gelöst hätte. is what most people want first. It handles the ReadableStream plumbing, the encoding, and the chunking. That six-week fintech nightmare I mentioned? That's exactly what streamText would have solved on day one.
Die Einrichtung Ohne den Verstand zu Verlieren
Angenommen, du bist auf Next.js 14 oder 15 mit dem App Router (was du wahrscheinlich bist, wenn du das 2025 liest), ist die Einrichtung wirklich schnell.
- Installiere die Pakete: npm install ai @ai-sdk/openai
npm install ai @ai-sdk/openai - Erstelle einen Route Handler unter app/api/chat/route.ts
app/api/chat/route.ts - Importiere streamText und deinen Provider, übergebe dein Modell und die Messages, gib das Ergebnis als StreamingTextResponse zurück
streamTextand your provider, pass in your model and messages, return the result as aStreamingTextResponse - Auf dem Client nutze den useChat Hook aus dem ai/react Package
useChathook from theai/reactpackage
Das war's. Du wirst in unter einer Stunde einen funktionierenden Streaming Chat haben, wenn du Next.js einigermaßen beherrschst. Der useChat Hook verwaltet das Message Array, den Loading State, die Input Field Bindung und die Streaming Updates. Du schreibst nichts davon selbst.useChat hook manages the message array, the loading state, the input field binding, and the streaming updates. You don't write any of that yourself.
Was ich sofort zu jedem Production Setup hinzufügen würde: einen ordentlichen System Prompt, Rate Limiting (ich verwende Upstash dafür, ihr Redis-gestützter Rate Limiter funktioniert perfekt mit Edge Functions), und eine Art Token Usage Logging. Das SDK stellt Usage Daten auf dem Response Objekt bereit, sodass du Prompt Tokens und Completion Tokens ohne zusätzliche API Calls in deine Datenbank loggen kannst.Upstash for this, their Redis-backed rate limiter plays nicely with Edge Functions), and some kind of token usage logging. The SDK exposes usage data on the response object, so you can log prompt tokens and completion tokens to your database without any extra API calls.
generateObject Ist das Feature, das du verschläfst
Ehrlich gesagt: streamText bekommt alle Aufmerksamkeit, aber generateObject ist das, das verändert hat, wie ich AI Features architekturiere.streamText gets all the press but generateObject is the one that's changed how I architect AI features.
Die Idee ist einfach. Du definierst ein Zod Schema, übergibst es generateObject, und das SDK instruiert das Modell, JSON zurückzugeben, das dem Schema entspricht. Du bekommst ein typed Object zurück, keine String, den du parsen und beten musst.generateObject, and the SDK instructs the model to return JSON that conforms to it. You get back a typed object, not a string you have to parse and pray over.
Seahawk hatte letztes Jahr ein Projekt für ein Immobilienverwaltungsunternehmen. Sie wollten strukturierte Daten aus hochgeladenen Mietverträgen extrahieren, Mieternamen, Mietbeträge, Break Clauses, Verlängerungsdaten. Der alte Ansatz hätte gelautet: das Modell prompten, Text zurückbekommen, einen Regex Parser schreiben, weinen. Mit generateObject definierten wir ein LeaseSchema mit Zod, und das Modell gab bei jedem Durchlauf saubere typed Daten zurück. Wir pushten extrahierte Mietverträge innerhalb einer Woche in eine Postgres Tabelle.generateObject , we defined a LeaseSchema with Zod, and the model returned clean typed data on every run. We were pushing extracted leases into a Postgres table within a week.
Das, das Menschen verwirrt: nicht alle Modelle unterstützen Structured Output gleich gut. GPT-4o und Claude 3.5 Sonnet handhaben es zuverlässig. Einige kleinere oder ältere Modelle werden Fields halluzinieren oder das Schema komplett ignorieren. Halte dich für diese Anwendung an die Flagship Modelle, zumindest bis du deinen Use Case validiert hast.
Tool Calling: Wo die echte Kraft liegt
Wenn generateObject untergenutzt ist, wird Tool Calling aktiv missverstanden. Die meisten Entwickler denken, „Tool Calling" bedeutet, dass die KI im Internet browsen oder Code ausführen kann. Manchmal tut sie das. Aber in der Praxis sind Tools nur Funktionen, die du definierst und die das Modell während einer Antwort aufrufen kann.generateObject is underused, tool calling is actively misunderstood. Most developers think "tool calling" means the AI can browse the internet or run code. Sometimes it does. But in practice, tools are just functions you define that the model can choose to invoke during a response.
Wie man darüber denkt
Sagen wir, du baust einen Support-Bot für ein SaaS-Produkt. Der Benutzer fragt „Welchen Abonnementplan habe ich aktuell?". Das kann das Modell nicht wissen. Aber du kannst ein getUserSubscription-Tool definieren, das eine Benutzer-ID nimmt und die Plan-Daten aus deiner Datenbank zurückgibt. Das Modell erkennt die Absicht, ruft das Tool auf, erhält die Daten zurück und bezieht sie in die Antwort ein. Der Benutzer sieht nur eine kohärente Antwort.getUserSubscription tool that takes a user ID and returns the plan data from your database. The model recognises the intent, calls the tool, gets the data back, and incorporates it into the response. The user just sees a coherent answer.
Der tools-Parameter des SDK auf streamText und generateText nimmt ein Objekt, bei dem jeder Schlüssel ein Tool-Name ist und jeder Wert eine description (die das Modell nutzt, um zu entscheiden, wann es aufgerufen wird), ein parameters-Schema (wieder Zod) und eine execute-Funktion hat. Die execute-Funktion läuft serverseitig, sicher, weg vom Client.tools parameter on streamText and generateText takes an object where each key is a tool name, and each value has a description (which the model uses to decide when to call it), a parameters schema (Zod again), and an execute function. The execute function runs server-side, safely, away from the client.
Ich habe Multi-Step-Agents auf diese Weise gebaut. Das SDK unterstützt maxSteps, sodass das Modell Tool-Aufrufe verketten kann – ein Tool aufrufen, das Ergebnis nutzen, ein anderes Tool aufrufen, alles zusammenführen, antworten. Es ist keine Magie. Du musst dich trotzdem sorgfältig um deine Tool-Beschreibungen und deinen System-Prompt kümmern. Aber die Verkabelung wird dir abgenommen.maxSteps so the model can chain tool calls, call one tool, use the result, call another tool, synthesise everything, respond. It's not magic. You still need to think carefully about your tool descriptions and your system prompt. But the wiring is all handled for you.
Middleware, Wrapping und das Pipeline-Modell
Eine Sache, die ich erst bei tieferem Lesen der Dokumentation schätzte: Das SDK hat ein Middleware-Konzept, das dir erlaubt, Modell-Aufrufe zu wrappen, um Logging, Caching oder benutzerdefiniertes Verhalten hinzuzufügen, ohne deinen eigentlichen Feature-Code zu berühren.
wrapLanguageModel nimmt ein Modell und ein Middleware-Objekt. Du kannst Anfragen abfangen, bevor sie die API treffen, Parameter modifizieren, Responses cachen. Ich habe das bei einem Content-Generation-Tool genutzt, das wir für einen Publisher bauten – ihr Use-Case hatte viele wiederholte Prompts (dieselbe Artikel-Zusammenfassung wurde mehrmals am Tag angefordert), und wir haben Responses in Redis mit der Middleware-Layer gecacht. Die Kosten sind im ersten Monat um etwa 35% gesunken. takes a model and a middleware object. You can intercept requests before they hit the API, modify parameters, cache responses. I used this on a content generation tool we built for a publisher, their use case had a lot of repeated prompts (same article summary being requested multiple times a day), and we cached responses in Redis using the middleware layer. Cost dropped by about 35% in the first month.
Das ist die Art von Sache, die du normalerweise umständlich um deine API-Aufrufe herum anbringen würdest. Sie als First-Class-Konzept im SDK zu haben bedeutet, dass sie zusammensetzbar und testbar ist.
Was es nicht tut (Sei ehrlich zu dir selbst)
Okay. Lass mich dir etwas Schmerz ersparen.
Das SDK übernimmt nicht die Speicherverwaltung oder die Verlaufshistorie längerer Konversationen für dich. useChat behält das Message-Array im Client-State, aber sobald der Nutzer aktualisiert, ist es weg. Wenn du persistente Konversationen brauchst, musst du das selbst bauen. Postgres oder MongoDB für die Nachrichtenspeicherung, beim Mount abrufen, um den Chat neu zu laden – nichts davon wird bereitgestellt. Das ist tatsächlich das richtige Verhalten. Das SDK sollte nicht deine Datenschicht besitzen. Aber Anfänger erwarten das oft.useChat maintains the message array in client state, but the moment the user refreshes, that's gone. If you need persistent conversations, you're building that yourself. Postgres or MongoDB for message storage, fetch on mount to rehydrate the chat, none of that is provided. This is correct behaviour, actually. The SDK shouldn't own your data layer. But newcomers often expect it to.
Es behandelt auch multimodale Eingaben nicht nativ auf eine Weise, die die ganze Komplexität abstrahiert. Du kannst Bild-URLs im Messages-Array übergeben und Modelle wie GPT-4o werden sie prima verarbeiten, aber einen ordentlichen Image-Upload-Flow mit Vorschau, Kompression und Speicherung zu bauen, ist immer noch deine Aufgabe. Ich nutze Uploadthing dafür, wenn ich auf Next.js arbeite, dauert etwa 30 Minuten zum Einbinden.Uploadthing for this when I'm on Next.js, takes about 30 minutes to wire up.
RAG (retrieval-augmented generation) ist auch nicht enthalten. Es gibt keine eingebaute Vektorsuche, keine Embedding-Pipeline, keine Chunking-Logik. Dafür greifst du zu etwas wie pgvector auf Postgres oder einen dedizierten Service wie Pinecone. Das SDK übernimmt den LLM-Call. Den Rest der Retrieval-Architektur musst du selbst bauen.pgvector on Postgres or a dedicated service like Pinecone. The SDK handles the LLM call. The rest of the retrieval architecture is yours to build.
Bereitstellung: Vercel vs. überall sonst
Ja, das SDK funktioniert am besten auf Vercel. StreamingTextResponse funktioniert mit Vercels Edge Runtime sofort, und Cold Starts bei Edge Functions sind viel niedriger als bei serverlosen Node.js-Funktionen. Wenn deine Chat-Antworten langsam wirken, spielt die Latenz bis zum ersten Token eine große Rolle, und Edge reduziert das.StreamingTextResponse works with Vercel's Edge Runtime out of the box, and cold starts on Edge Functions are much lower than on serverless Node.js functions. If your chat responses feel sluggish, the latency until the first token matters a lot, and Edge cuts that down.
Aber ich habe es auf Railway (Node.js, nicht Edge) deployed und es funktioniert einwandfrei. Du nutzt einfach Response mit korrekten Streaming-Headern statt der Vercel-spezifischen Helfer, und das SDK dokumentiert das. Lass dich von „Vercel AI SDK" nicht denken, dass du gebunden bist.Response with proper streaming headers instead of the Vercel-specific helpers, and the SDK docs cover this. Don't let "Vercel AI SDK" make you think you're locked in.
Eine Sache, die ich wirklich empfehlen würde: Halte deine AI-Route-Handler dünn. Mach nicht Datenbankabfragen, Authentifizierungschecks und LLM-Calls alle in einer Funktion. Middleware (Next.js-Middleware, nicht die SDK-Middleware) sollte Auth vor der Anfrage handeln, bevor sie überhaupt deine AI-Route erreicht. Hält die Dinge schnell, hält die Dinge debuggbar.
FAQ
Ist das Vercel AI SDK kostenlos nutzbar?
Das SDK selbst ist Open Source und kostenlos. Du zahlst für die zugrundeliegenden Model-APIs – OpenAI, Anthropic, Google, wen auch immer du aufrufst. Diese Kosten musst du selbst verwalten. Das SDK schlägt nichts auf.
Kann ich es mit anderen Modellen als OpenAI verwenden?
Ja, und das ist einer seiner echten Stärken. Es gibt offizielle Adapter für Anthropic, Google (Gemini), Mistral, Groq, Cohere und mehr. Die Community hat auch Adapter für Ollama gebaut, falls du lokale Modelle ausführen möchtest. Die einheitliche Schnittstelle bedeutet, dass dein Feature-Code sich nicht ändert, wenn du den Provider wechselst.
Funktioniert es mit React Server Components?
Teilweise. generateText und generateObject können in Server Components ohne Probleme ausgeführt werden – es sind einfach asynchrone Funktionen. streamText mit dem useChat Hook benötigt Client-seitigen State, also lebt dieser Teil in einer Client Component. Das ist Standard-Next.js-Architektur und sollte dir keine Probleme bereiten, wenn du die Grenze verstehst.generateText and generateObject can run in Server Components without issues, they're just async functions. streamText with the useChat hook requires client-side state, so that part lives in a Client Component. This is standard Next.js architecture and shouldn't cause you any grief if you understand the boundary.
Wie gehe ich mit Fehlern um, wenn die API ausfällt?
Das SDK wirft typisierte Fehler, die du fangen und behandeln kannst. In der Praxis umhülle ich meine LLM-Aufrufe mit einem try/catch und gebe eine freundliche Fallback-Nachricht zurück, anstatt den Stream-Fehler als kaputte Teilantwort bis zur UI durchblubbern zu lassen. Die SDK-Dokumentation zum Fehlerhandling behandelt die Fehlertypen im Detail und lohnt sich, vor dem Go-Live zu lesen.SDK docs on error handling cover the error types in detail and are worth reading before you go to production.
Wie sieht es mit dem Token-Limit aus?
Das SDK verwaltet Context-Window-Limits nicht für dich. Wenn du ein langlaufendes Gespräch aufbaust und die Nachrichtenverlauf nicht kürzt, wirst du das Context-Window des Modells erreichen und bekommst einen Fehler. Eine einfache Lösung: Behalte die letzten N Nachrichten (ich nehme normalerweise 20) plus einen angehefteten System-Prompt. Für die meisten Chat-Anwendungen ausreichend.
---
Schau, das Vercel AI SDK ist kein Wunder. Es ist eine gut durchdachte Abstraktion über etwas wirklich mühsame Rohrleitungen. Es handhabt Streaming korrekt, es gibt dir typisierte strukturierte Ausgaben, es macht Tool-Aufrufe zugänglich und es funktioniert über Provider hinweg. Für 80% der AI-Feature-Arbeiten, die ich übernehme, ist es der richtige Ausgangspunkt.
Der Fintech-Kunde ist übrigens zwei Wochen nach meinem Rewrite mit dem erneuerten Chat live gegangen. Keine Probleme auf Mobile Safari. Keine Race Conditions. Sechs Wochen wurden zwei Tage. Manchmal ist die richtige Abstraktion eine Menge wert.
