Node.js Setup
Purpose and Scope
Use this page when you want to run the AI SDK from a plain Node.js project, command-line script, worker, or server process without first choosing a web framework. The repository’s Node.js quickstart presents Node as a first-class runtime for building an interactive streaming agent in TypeScript, while the package README frames the same package as a provider-agnostic toolkit for applications and agents across runtimes. In practice, a Node setup is the fastest way to learn the core call shape before adding HTTP routes, UI hooks, persistence, or framework-specific transports.
Sources: content/docs/02-getting-started/06-nodejs.mdx, packages/ai/README.md
The recommended baseline is modern Node with TypeScript. The quickstart requires Node.js 22 or newer and pnpm, then adds runtime dependencies for the SDK, schemas, and environment variables. The root package metadata also declares supported engine ranges beginning at Node 22, which matches the documentation’s expectation that local examples run on current Node releases. A plain script can still represent a real application architecture: it can read secrets from environment variables, hold conversation state, stream output incrementally, and call provider-backed models directly from server-side code.
Sources: content/docs/02-getting-started/06-nodejs.mdx, packages/ai/README.md
Relevant Source Files
- content/docs/02-getting-started/06-nodejs.mdx — The first-party Node.js quickstart that defines prerequisites, dependency installation, AI Gateway configuration, and an interactive terminal chat loop built with streamText.
- packages/ai/README.md — The package-level overview that documents installation, provider-agnostic usage, AI Gateway model strings, direct provider packages, generateText, structured output, agents, and UI integration context.
- examples/ai-functions/src/complex/semantic-router/main.ts — A concrete Node-oriented example that imports a direct provider package, constructs a semantic router with an embedding model, awaits a typed routing result, and handles the result in a switch statement.
Setup Flow
Start a Node project by creating a directory, initializing a package file, and installing the SDK. The quickstart installs the main ai package together with zod and dotenv, then adds TypeScript-oriented development dependencies such as @types/node, tsx, and typescript. This combination is important: ai provides the public generation APIs, zod provides schema definitions for structured output patterns, dotenv loads the AI Gateway key during local execution, and tsx lets you run a TypeScript entry point directly while you are iterating on a terminal program.
Sources: content/docs/02-getting-started/06-nodejs.mdx
mkdir my-ai-app
cd my-ai-app
pnpm init
pnpm add ai zod dotenv
pnpm add -D @types/node tsx typescriptAuthentication is handled through an environment variable rather than hard-coded application state. The quickstart instructs you to create a .env file and set AI_GATEWAY_API_KEY to a Vercel AI Gateway key. That matches the README’s provider story: by default, the SDK can use AI Gateway so a model can be passed as a provider-qualified string, such as an OpenAI, Anthropic, or Google model identifier. This keeps early Node examples small because you do not need to install and configure every provider package before making a first request.
Sources: content/docs/02-getting-started/06-nodejs.mdx, packages/ai/README.md
AI_GATEWAY_API_KEY=xxxxxxxxxCore Primitives
The central primitives in the Node quickstart are messages, a model, and a streaming result. A message is represented with the SDK’s ModelMessage type and carries a role plus content. The model is supplied to streamText, either as an AI Gateway model string or, in other examples, as a provider instance returned by a package such as @ai-sdk/openai. The streaming result exposes textStream, which is consumed with an asynchronous iterator so a command-line program can print deltas as they arrive instead of waiting for the entire response.
Sources: content/docs/02-getting-started/06-nodejs.mdx, packages/ai/README.md
The README shows the same core layer outside an interactive loop with generateText. That call returns a completed text result for prompt-style work, and it can also be configured for structured output with Output.object and a zod schema. For Node developers, this means the same project can contain a quick one-shot script, a typed data extraction job, and a long-running streaming assistant without changing packages. The runtime difference is mostly how you collect input and deliver output; the SDK call options remain recognizable across those use cases.
Sources: packages/ai/README.md
Local tools, MCP tools, and provider-defined tools are later extensions of this same model-call pattern rather than a replacement for it. The quickstart stays focused on a terminal chat loop, while the broader documentation and README show agents and tool use as additional layers. A local tool runs code you provide in the Node process or connected infrastructure; MCP tools connect through the Model Context Protocol to external tool servers or apps; provider-defined tools are exposed by specific model providers. Learn the direct generation path first, then add tools when the model needs action or external context.
Sources: packages/ai/README.md
Minimal Terminal Chat Application
The quickstart’s application structure is intentionally small but teaches the lifecycle of a server-side chat. It imports streamText and ModelMessage from ai, loads dotenv configuration, creates a readline interface from node:readline/promises, and stores the conversation in an in-memory messages array. Each loop iteration asks for user input, appends a user message, starts a streamText call with the current message history, prints response deltas to stdout, and finally appends the assistant’s full response back into the history for the next turn.
Sources: content/docs/02-getting-started/06-nodejs.mdx
import { ModelMessage, streamText } from 'ai';
import 'dotenv/config';
import * as readline from 'node:readline/promises';
const terminal = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
const messages: ModelMessage[] = [];
async function main() {
while (true) {
const userInput = await terminal.question('You: ');
messages.push({ role: 'user', content: userInput });
const result = streamText({
model: 'openai/gpt-5.4',
messages,
});
let fullResponse = '';
process.stdout.write('\nAssistant: ');
for await (const delta of result.textStream) {
fullResponse += delta;
process.stdout.write(delta);
}
process.stdout.write('\n\n');
messages.push({ role: 'assistant', content: fullResponse });
}
}
main().catch(console.error);There are two practical edge cases to understand before turning this into a service. First, the example keeps all messages in memory, which is appropriate for a learning script but not enough for multiple users, process restarts, or long conversations. Persist or trim history when the program becomes a server. Second, streaming output is consumed exactly once as it arrives. If you need both live terminal output and later persistence, follow the quickstart’s pattern of accumulating fullResponse while printing each delta, then store the final assistant message after the stream completes.
Sources: content/docs/02-getting-started/06-nodejs.mdx
Provider and Model Choices
The README documents two supported provider-selection styles. The shortest path is AI Gateway, where the model is a string that names a provider and model behind the gateway. This is ideal for early Node scripts because authentication is centralized through AI_GATEWAY_API_KEY and model changes can often be made by editing a single string. The direct-provider path installs provider packages such as @ai-sdk/openai, @ai-sdk/anthropic, or @ai-sdk/google, imports a provider helper, and passes the provider-created model object into generation calls.
Sources: packages/ai/README.md
The semantic router example illustrates the direct-provider style in a non-chat script. It imports openai from @ai-sdk/openai, creates a SemanticRouter with openai.embedding('text-embedding-3-small'), sets a similarity threshold, and defines typed route names with representative values. The script then awaits router.route for a new sentence and switches on sports, music, or null. Even though this example is not the quickstart chatbot, it is valuable for Node setup because it shows that AI SDK usage also covers embeddings, classification-style routing, and strongly typed control flow in ordinary async code.
Sources: examples/ai-functions/src/complex/semantic-router/main.ts
Direct Core Calls and Structured Workloads
Once the terminal chat runs, use direct core calls for workloads that do not require a user interface. The README’s generateText example asks a prompt and reads the returned text, which is useful for scripts, background jobs, and simple API handlers. Its structured data example uses Output.object with a zod schema so the model response is shaped as typed output rather than free text. The Node quickstart already installs zod, so you can evolve from chat to typed extraction, recipe generation, classification, or report-building without reworking the project foundation.
Sources: packages/ai/README.md, content/docs/02-getting-started/06-nodejs.mdx
Testing and Next Steps
For a local smoke test, confirm that Node is at least version 22, dependencies are installed, AI_GATEWAY_API_KEY is present, and the TypeScript entry point can be run with your chosen package script or tsx command. Then test three paths: a one-shot generateText call, the streaming terminal loop, and one provider-specific example if you plan to use direct provider packages. This sequence separates environment problems from streaming logic and provider selection, making failures easier to diagnose before you move into an HTTP server, Express, Hono, Fastify, Nest.js, or a framework UI.
Sources: content/docs/02-getting-started/06-nodejs.mdx, packages/ai/README.md
Next, read the pages on choosing a provider, generating text and streaming, structured data generation, tools and tool calling, and embeddings and reranking. If you are building an agent, continue to the agent overview after the Node quickstart so you can decide whether a simple loop around streamText is enough or whether you need ToolLoopAgent, tool execution, approvals, or memory. If you are adding a frontend, move to the UI overview after your server-side call path is working so the transport layer is the only new concept.