AI SDK 7 streams a terminal response with streamText

1 month ago

A one-file Node script can print the first words before the full answer exists. This was run on AI SDK 7, Vercel’s TypeScript toolkit for calling AI models from an app. The function is `streamText`, and the terminal starts writing while the answer is still being produced. That early movement tells the user the chat UI is alive.

Ask about this presentation

Chapters

  1. 0:00streamText starts moving
  2. 0:22Install prerequisites
  3. 0:48Runtime packages
  4. 1:26TypeScript runner
  5. 1:51One streamText call
  6. 2:22The stream shape
  7. 2:55The stdout loop
  8. 3:26Save the message
  9. 3:53Gateway auth
  10. 4:25onError
  11. 4:50Fallbacks
Show transcript
  1. A one-file Node script can print the first words before the full answer exists. This was run on AI SDK 7, Vercel’s TypeScript toolkit for calling AI models from an app. The function is `streamText`, and the terminal starts writing while the answer is still being produced. That early movement tells the user the chat UI is alive.

    Slide text
    `streamText` prints while the answer is still arriving
    assets/terminal/04-mock-stream-run.txt
    You: Explain streamText in one sentence.
    
    Assistant: streamText returns text chunks as the model writes.
    
    Saved assistant message: streamText returns text chunks as the model writes.
    AI SDK 7
    first visible responsestdout writes each text delta
    no key in this captureofficial AI SDK testing helper
    Local run with AI SDK 7 testing helper
  2. The official Node.js quickstart asks for Node twenty-two or newer, pnpm, and a Vercel AI Gateway API key. Vercel AI Gateway is the hosted gateway the quickstart uses to reach a model with one key. The local run used Node twenty-five and pnpm through npx, so the runtime meets the docs’ floor. The missing piece on this machine was the AI Gateway key. The docs put that key in `.env`, and that setup choice shows up again in the gotchas.

    Slide text
    01
    Install
    01 Install follows the Node.js quickstart
    node version 25
    pnpm through npx current CLI
    AI_GATEWAY_API_KEY missing
    The docs ask for Node 22 or newer, pnpm, and an AI Gateway API key.
    AI SDK Node.js quickstart
  3. The first install command adds three runtime packages. The `ai` package is the AI SDK itself. Zod handles schemas later in the quickstart, even though this first script only needs text. Dotenv loads environment variables from `.env`, including the Gateway key. In the code, `import 'dotenv/config'` runs before the model call, so the Gateway key is available when the AI SDK reads the environment. The local transcript shows those packages being added, then the lab pinned the AI SDK package to the current AI SDK 7 build checked from npm.

    Slide text
    01
    Install
    The quickstart installs runtime packages first
    assets/terminal/01-pnpm-add-runtime.txt
    dependencies:
    + ai
    + dotenv
    + zod
    
    Done in 2.1s using pnpm
    ai
    zod
    dotenv
    pinned to AI SDK 7 in the lab
    AI SDK docs and local pnpm output
  4. The second install command adds the TypeScript runner side. `tsx` runs the TypeScript file directly, TypeScript checks the code, and `@types/node` gives the editor Node’s types. Pnpm also reported that it ignored the esbuild build script. The typecheck still passed in this lab, so that warning did not stop the first-response path. After this step, the project has enough machinery to run `pnpm tsx index.ts`.

    Slide text
    01
    Install
    TypeScript runs through `tsx`
    assets/terminal/02-pnpm-add-dev.txt
    devDependencies:
    + @types/node
    + tsx
    + typescript
    
    Error: ERR_PNPM_IGNORED_BUILDS
    Ignored build scripts: esbuild
    `tsx`runs the TypeScript file directly
    TypeScriptchecks the code path
    @types/nodegives the editor Node types
    Local pnpm output
  5. The smallest program imports `ModelMessage` and `streamText` from `ai`, then opens a readline prompt. Readline is Node’s built-in terminal question API. `ModelMessage` is the AI SDK message type for chat history. The script stores every user and assistant turn in a `messages` array. When the user types a prompt, the script calls `streamText` with the rendered quickstart model string, `xai/grok-4.7`, and the current messages. `streamText` starts the generation and returns a result object.

    Slide text
    02
    First run
    02 First run is one `streamText` call
    `ModelMessage[]`stores the chat history
    `xai/grok-4.7`rendered quickstart model string
    `streamText(...)`starts generation and returns a result
    Runnable source: assets/lab/index.ts
  6. The docs split the two text-generation shapes. `generateText` is the sibling function that waits for a complete text answer. `streamText` exposes the answer as pieces. The property is `result.textStream`, which is the stream of text deltas on the result object. The docs say that `textStream` is both a ReadableStream and an async iterable. A ReadableStream is the web stream shape that browser and server runtimes already understand. An async iterable is a value Node can loop over with `for await` as new pieces arrive.

    Slide text
    03
    Shape
    03 `generateText` waits, and `streamText` exposes chunks
    `generateText`waits for complete text
    `streamText`exposes text deltas
    `textStream`ReadableStream and async iterable
    AI SDK Core, generating text
  7. The loop is the visible payoff. The script creates `fullResponse`, prints the assistant label, then loops over `result.textStream`. Each delta is one new text piece. `process.stdout.write(delta)` sends each piece straight to the terminal. That is why the answer can appear word by word while the final newline is still ahead. The lab output uses AI SDK’s official testing helper with three text chunks. It proves the stream consumption path. A live provider response needs the Gateway key from the quickstart.

    Slide text
    04
    Real thing
    04 The loop writes each delta to stdout
    assets/terminal/04-mock-stream-run.txt
    Assistant: streamText returns text chunks as the model writes.
    
    Saved assistant message:
    streamText returns text chunks as the model writes.
    Local AI SDK streamText run
  8. After the stream finishes, the script saves the full assistant response back into `messages`. That saved assistant message is what turns the first run into a terminal chat. The next user message carries the previous turns with it, so the model sees the conversation so far. The quickstart also shows the current Gateway default as Grok four point seven with the model string `xai/grok-4.7`. If you copy the docs today, that is the model string the rendered page shows.

    Slide text
    The chat loop saves the finished assistant message
    `messages`user and assistant turns
    `fullResponse`completed assistant text
    `messages.push`keeps context for the next turn
    AI SDK Node.js quickstart
  9. This is the part people get wrong with Gateway auth. The quickstart depends on `AI_GATEWAY_API_KEY` in `.env`. When that key is missing, the local Gateway check raises `GatewayAuthenticationError` before there is useful model output to stream. The captured error also says zero variables were injected from `.env`, which is the clue to follow first. Issue thirteen three oh two is the same class of error in the AI SDK repository. Check `.env` first, then check that the shell running `tsx` can actually read the key.

    Slide text
    05
    Gotchas
    05 Gotcha: Gateway auth fails before streaming helps
    assets/terminal/06-gateway-auth-check.txt
    injected env (0) from .env
    onError: Error [GatewayAuthenticationError]:
    Unauthenticated request to AI Gateway.
    
    To authenticate, set the
    AI_GATEWAY_API_KEY environment variable
    with your API key.
    vercel/ai issue 13302 and local auth check
  10. This is the part people get wrong with stream errors. The docs say `streamText` starts streaming immediately, and stream errors are surfaced through the error path so the server can stay up. `onError` is the callback where those failures can be logged. Put `onError` into the first version of the script. The `textStream` loop is for successful text deltas. The error callback is for provider, network, and authentication failures.

    Slide text
    05
    Gotchas
    Gotcha: stream errors belong in `onError`
    first version of index.ts
    onError({ error }) {
      console.error(
        "\nStream error:",
        error
      );
    }
    AI SDK troubleshooting, streamText errors
  11. This is the part people get wrong after the first response works. Provider failures still happen, and issue twenty-six thirty-six is the long-running thread about retry strategies and fallbacks. For the first script, keep the shape provider-simple: one Gateway model, one messages array, one stream loop, and one `onError` logger. The reusable path is small. Call `streamText`, loop over `result.textStream`, write each delta to stdout, then save the completed assistant message back into `messages`.

    Slide text
    05
    Gotchas
    Gotcha: provider failures need a planned fallback
    assets/lab/index.ts
    const result = streamText({
      model: 'xai/grok-4.7',
      messages,
      onError({ error }) {
        console.error('\nStream error:', error);
      },
    });
    
    let fullResponse = '';
    for await (const delta of result.textStream) {
      fullResponse += delta;
      process.stdout.write(delta);
    }
    
    messages.push({ role: 'assistant', content: fullResponse });
    vercel/ai issue 2636 and runnable source

What happened in AI today, in your inbox

One short email each evening. Read it and you’re caught up.

Built with ❤️ in New York