Back
intermediate

Modern AI Development

AI SDK: streaming without pretending the answer is finished

Understand text deltas, completion and errors, and keep provider credentials on the server.

Lesson 39 of 44About 30 min with practice

Words begin appearing in a chat window, then the connection drops halfway through a sentence. Was the answer successful? Streaming makes output visible sooner, but your application still needs to know whether generation completed.

Before you begin: Know JavaScript async functions and the browser/server boundary. The optional example uses Node.js.

Separate three responsibilities

Vercel's AI SDK is a TypeScript toolkit with provider integrations, generation functions, and UI utilities. A provider adapter translates an application request into a model API request. Core functions manage generation. The interface presents the resulting events to a person.

Streaming sends output incrementally. A chunk of streamed text is often called a delta, meaning the new piece since the previous event. A delta is not guaranteed to be a whole word, sentence, or model token. The transport may buffer data, and the first visible text depends on the workload and network. There is no universal sub-second guarantee.

Observe a stream before building a chat screen

This complete Node.js module is an external integration example. Install compatible releases of ai and @ai-sdk/openai, set OPENAI_API_KEY and OPENAI_MODEL, and save it as stream.mjs. Use a Node version supported by the resolved packages. Run it with node stream.mjs. No paid provider execution is claimed here.

The API review on September 10, 2026 used the official repository's stream function and result interfaces because the documentation site was unavailable during review. Keep an exact lockfile; repository main can include changes beyond your installed release.

javascript
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

if (!process.env.OPENAI_MODEL) {
  throw new Error('Set OPENAI_MODEL to an available model ID');
}
let streamFailed = false;
try {
  const result = streamText({
    model: openai(process.env.OPENAI_MODEL),
    prompt: 'Explain why capacity does not mean remaining seats.',
    maxOutputTokens: 200,
    maxRetries: 0,
    abortSignal: AbortSignal.timeout(30000),
    onError: () => { streamFailed = true; },
  });
  for await (const delta of result.textStream) {
    process.stdout.write(delta);
  }
  process.stdout.write('\n');
  if (streamFailed) throw new Error('Stream reported an error');
  console.error('Text stream ended; inspect the answer before using it.');
} catch {
  console.error('Generation failed or was interrupted. Output may be partial.');
  process.exitCode = 1;
}

The error callback matters because a text-only stream does not represent every non-text event. Finishing iteration also does not prove factual correctness or sufficient output length. A full application should inspect completion metadata and any truncation or refusal outcome supported by its provider integration.

Carry those distinctions into the interface

Use visible states for submitting, streaming, completed, interrupted, and failed. Preserve the question when a request fails. Offer retry as a new attempt tied to the same user intent. Keep partially received text clearly marked when it may be incomplete.

On phones, allow ordinary text wrapping, avoid forcing the page to jump while someone reads earlier content, and keep a reachable stop control. Announce meaningful status changes to assistive technology without reading every arriving character aloud.

Provider keys belong on the server. UI message objects and model input messages may use different shapes; use the conversion utilities for your installed SDK version. Do not paste a legacy ai/react example beside a current UI package and assume the contracts match.

Diagnose the false success

The screen displays “Saved” as soon as the first text arrives. The server later fails and never stores a final answer. What should change?

Follow the two independent operations

Track generation and persistence separately. First text means generation has started producing output. “Saved” requires a confirmed storage write. Use a stable message ID and persist the final status so a returning user sees whether the answer completed, failed, or remained partial.

Your next project will connect that interface to authenticated storage and source-backed answers.

Sources

AI SDK repository, streamText implementation, and stream result interface are the reviewed references.

Continue to the next lesson.

Practice for this lesson

Stream without pretending the answer is finished

Separate transport, state, and interface, and diagnose a false success.

About 11 min55 points3 checks and one written task
Loading your lesson progress...