Start und Finish Parts
Überblick
Abschnitt betitelt „Überblick“In einem Multi-Step-Szenario (z.B. Tool-Call-Loop mit maxSteps) durchlaeuft streamText mehrere Generierungsschritte. Jeder Schritt wird durch step-start und step-finish Stream Parts begrenzt. Der step-start Part liefert die messageId, Request-Metadaten und Warnings. Der step-finish Part liefert finishReason, usage (Token-Verbrauch), isContinued, Response-Metadaten und optional Log Probabilities.
Zusätzlich gibt es zwei Callbacks: onStepFinish feuert nach jedem einzelnen Schritt und liefert per-Step-Daten. onFinish feuert einmalig nach Abschluss aller Schritte und liefert aggregierte Daten wie totalUsage und das steps-Array.
Hinweis zur Benennung: Im fullStream heissen die Part-Types step-start und step-finish (TextStreamPart). Im Stream-Protokoll (Data Stream Protocol) werden sie als f: (Start Step) und e: (Finish Step) Zeilen uebertragen. In der UIMessage existiert nur ein StepStartUIPart mit type: 'step-start' — ein entsprechendes step-finish Part gibt es in UIMessage nicht, da die UI nur die Schritt-Grenzen markiert, nicht deren Abschluss.
Callbacks
Abschnitt betitelt „Callbacks“import { streamText } from 'ai';import { anthropic } from '@ai-sdk/anthropic';
const result = streamText({ model: anthropic('claude-sonnet-4-5-20250514'), prompt: 'Wie ist das Wetter in Berlin und Muenchen?', tools: { weather: weatherTool }, maxSteps: 5,
// Feuert nach JEDEM Schritt onStepFinish({ stepType, finishReason, usage, text, toolCalls, toolResults, isContinued }) { console.log(`Step (${stepType}) finished: ${finishReason}`); console.log(`Tokens: ${usage.totalTokens}`); },
// Feuert nach ALLEN Schritten onFinish({ text, totalUsage, steps, finishReason, sources }) { console.log(`Fertig. Total tokens: ${totalUsage.totalTokens}`); console.log(`Schritte: ${steps.length}`); },});Stream-Konsum
Abschnitt betitelt „Stream-Konsum“for await (const part of result.fullStream) { switch (part.type) { case 'step-start': console.log(`--- Neuer Schritt (messageId: ${part.messageId}) ---`); break; case 'text-delta': process.stdout.write(part.textDelta); break; case 'tool-call': console.log(`Tool: ${part.toolName}(${JSON.stringify(part.args)})`); break; case 'tool-result': console.log(`Ergebnis: ${JSON.stringify(part.result)}`); break; case 'step-finish': console.log(`Schritt fertig: ${part.finishReason}`); console.log(`Tokens: ${part.usage.totalTokens}`); console.log(`Weiter: ${part.isContinued}`); break; }}finishReason-Werte
Abschnitt betitelt „finishReason-Werte“| Wert | Bedeutung |
|---|---|
'stop' | LLM hat normal aufgehoert |
'length' | Max-Token-Limit erreicht |
'content-filter' | Content-Filter hat gestoppt |
'tool-calls' | LLM will Tools aufrufen (naechster Schritt folgt) |
'error' | Fehler aufgetreten |
'other' | Sonstiger Grund |
Callback-Vergleich
Abschnitt betitelt „Callback-Vergleich“| Eigenschaft | onStepFinish | onFinish |
|---|---|---|
| Wann | Nach jedem Schritt | Nach allen Schritten |
usage | Token-Verbrauch dieses Schritts | Token-Verbrauch des letzten Schritts |
totalUsage | Nicht verfügbar | Aggregiert über alle Schritte |
steps | Nicht verfügbar | Array aller Schritte |
stepType | 'initial', 'continue', 'tool-result' | Nicht verfügbar |
isContinued | true wenn der nächste Schritt folgt | Nicht verfügbar |
StepStartUIPart
Abschnitt betitelt „StepStartUIPart“In der UIMessage erscheint StepStartUIPart mit { type: 'step-start' } als Part. Ein step-finish UIMessage Part existiert nicht — nur der Beginn eines Schritts wird in der UI abgebildet. Damit kannst Du im Frontend visuelle Grenzen zwischen Schritten rendern — z.B. ein Trennzeichen oder eine Schritt-Anzeige.
{m.parts.map((part, i) => { if (part.type === 'step-start') { return <hr key={i} className="step-divider" />; } if (part.type === 'text') { return <p key={i}>{part.text}</p>; } return null;})}Siehe auch
Abschnitt betitelt „Siehe auch“- Challenge 3.4: Tool Loop Agent — Multi-Step Tool-Ausfuehrung
- Level 8: Workflows — Fortgeschrittene Multi-Step Patterns