DevOps Elastic Hayway
Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

Vercel AI SDK 2026 : generateText, streamText, useChat

À la fin de ce tutoriel Vercel AI SDK, vous saurez installer le package ai, brancher un modèle via Vercel AI Gateway (ou un provider dédié), générer du texte avec generateText, streamer avec streamText, exposer une route Next.js App Router compatible useChat, appeler des tools multi-étapes (stopWhen), et produire des outputs structurés avec Output.object — lab local sans secrets en clair.

Niveau : Intermédiaire · Temps estimé : 50–60 min · Versions testées : Node.js 22+, Next.js App Router, package ai (ligne AI SDK 6) · Dernière vérification : 2026-09-11

Prérequis

Ce que nous allons construire

/tmp/lab-vercel-ai-sdk
  ├── scripts/summarize-incident.mts   → generateText (runbook / faux log)
  └── (option) my-ai-app/              → Next.js App Router
        ├── .env.local                 → AI_GATEWAY_API_KEY (local only)
        ├── app/api/chat/route.ts      → streamText + UI message stream
        └── app/page.tsx               → useChat (@ai-sdk/react)
             → tools Zod + stopWhen
             → Output.object (schéma incident)
             → tableau erreurs · quiz · FAQ · SEO HOLD

(Schéma à remplacer par une cover locale, alt : « Vercel AI SDK — generateText, streamText, useChat, tools, structured output — 2026 ».)

Leçon 44 (après OpenRouter #43) : standardiser l’intégration LLM TypeScript. Angle DevOps : résumé d’incident, chat runbook, tools infra factices.

Étape 1 — Pourquoi le Vercel AI SDK (carte 2026)

Intégrer un LLM « à la main » (fetch provider, formats messages, streaming SSE, tools) crée un couplage fragile. Le AI SDK (toolkit TypeScript de Vercel) unifie :

Surface Rôle
AI SDK Core (ai) generateText, streamText, tools, agents, outputs structurés
AI SDK UI (@ai-sdk/react, …) Hooks chat / objets (useChat, useObject) framework-agnostic
AI SDK Harnesses HarnessAgent pour brancher des harnesses type Claude Code / Codex / Pi

Providers : Vercel AI Gateway (défaut, modèles en string provider/model), ou packages @ai-sdk/openai, @ai-sdk/anthropic, @ai-sdk/google, etc. Docs : ai-sdk.dev · sdk.vercel.ai/docs.

Étape 2 — Lab : résumé d’incident avec generateText

mkdir -p /tmp/lab-vercel-ai-sdk/scripts && cd /tmp/lab-vercel-ai-sdk
pnpm init
pnpm add ai zod dotenv
# Clé gateway uniquement en local / CI secrets — jamais commitée
printf 'AI_GATEWAY_API_KEY=REMPLACERn' > .env
echo '.env' >> .gitignore

Créez scripts/summarize-incident.mts :

import 'dotenv/config';
import { generateText } from 'ai';

const fakeLog = `
[2026-09-11T03:12:01Z] ERROR api-gateway timeout upstream=payments latency_ms=8200
[2026-09-11T03:12:08Z] WARN  k8s Deployment/payments replicas=2 ready=0
[2026-09-11T03:12:40Z] INFO  pagerduty incident=INC-1042 sev=2
`.trim();

const { text, usage } = await generateText({
  model: 'xai/grok-4.6', // string gateway ; adaptez au modèle dispo
  system:
    'Tu es un SRE. Réponds en français, structuré, sans inventer de métriques absentes du log.',
  prompt: `Résume l'incident en 5 puces max (symptôme, blast radius, hypothèses, prochaines actions) :n${fakeLog}`,
});

console.log(text);
console.log('usage:', usage);
# Exemple d'exécution (Node 22+)
pnpm exec tsx scripts/summarize-incident.mts

generateText convient aux jobs non interactifs : résumé de logs, ticket, message Slack, agent batch. Le résultat expose notamment text, usage, toolCalls / toolResults si tools, et output si schéma structuré.

Étape 3 — Chat streaming Next.js : streamText + useChat

cd /tmp/lab-vercel-ai-sdk
pnpm create next-app@latest my-ai-app
# App Router + TypeScript + Tailwind : oui
cd my-ai-app
pnpm add ai @ai-sdk/react zod
printf 'AI_GATEWAY_API_KEY=REMPLACERn' > .env.local

Route Handler app/api/chat/route.ts :

import {
  streamText,
  convertToModelMessages,
  createUIMessageStreamResponse,
  toUIMessageStream,
  type UIMessage,
} from 'ai';

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: 'xai/grok-4.6',
    system:
      'Assistant runbook DevOps. Français, concret, refuse les secrets et les credentials.',
    messages: await convertToModelMessages(messages),
  });

  return createUIMessageStreamResponse({
    stream: toUIMessageStream({ stream: result.stream }),
  });
}

UI app/page.tsx — 'use client', hook useChat de @ai-sdk/react : affichez messages (rôle + parts de type text), et sur submit appelez sendMessage({ text: input }) puis videz le champ. Par défaut le hook POST sur /api/chat.

pnpm run dev
# http://localhost:3000 — testez un message court

Les messages UI (UIMessage, parts) ≠ messages modèle : passez par convertToModelMessages. Renvoyez createUIMessageStreamResponse + toUIMessageStream. Branchez onError sur streamText (erreurs avalées côté serveur).

Changer de provider

// Gateway (défaut) — string
model: 'anthropic/claude-sonnet-4.5';

// Provider dédié
import { openai } from '@ai-sdk/openai';
model: openai('gpt-5.1'); // après : pnpm add @ai-sdk/openai

Étape 4 — Tools + multi-étapes (stopWhen)

Les LLM hallucinent facilement sur l’état infra. Un tool expose une action typée (Zod) que le modèle peut appeler ; le serveur exécute execute et renvoie le résultat.

import {
  streamText,
  tool,
  isStepCount,
  convertToModelMessages,
  createUIMessageStreamResponse,
  toUIMessageStream,
  type UIMessage,
} from 'ai';
import { z } from 'zod';

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: 'xai/grok-4.6',
    messages: await convertToModelMessages(messages),
    stopWhen: isStepCount(5), // sinon 1 step = arrêt après le tool call
    tools: {
      getServiceHealth: tool({
        description: 'Statut factice d’un service lab.',
        inputSchema: z.object({
          service: z.string().describe('Nom du service, ex. payments'),
        }),
        execute: async ({ service }) => ({
          service,
          env: 'lab',
          status: service === 'payments' ? 'degraded' : 'ok',
          readyReplicas: service === 'payments' ? 0 : 2,
        }),
      }),
    },
  });

  return createUIMessageStreamResponse({
    stream: toUIMessageStream({ stream: result.stream }),
  });
}

Sans stopWhen (souvent 1 step), le modèle s’arrête après le tool call (tool-getServiceHealth) sans synthèse. Avec isStepCount(5), il réinjecte le résultat et répond. Tools DevOps lab : status factice, runbook mock — jamais de credentials en entrée.

Étape 5 — Outputs structurés (AI SDK 6)

En AI SDK 6, generateObject / streamObject sont dépréciés. Préférez generateText / streamText avec output: Output.object({ schema }) :

import { generateText, Output } from 'ai';
import { z } from 'zod';

const incidentSchema = z.object({
  severity: z.enum(['sev1', 'sev2', 'sev3', 'sev4']),
  service: z.string(),
  summary: z.string(),
  nextActions: z.array(z.string()).min(1).max(5),
});

const { output } = await generateText({
  model: 'xai/grok-4.6',
  output: Output.object({ schema: incidentSchema }),
  prompt:
    'À partir de ce log lab, produis un objet incident strict : ERROR payments timeout, ready=0, INC-1042 sev2.',
});

console.log(output);

Zod valide la forme (JSON → ticket / webhook). UI : useObject. Tools + output : augmentez stopWhen (l’output compte comme une step).

Étape 6 — Sécurité et déploiement DevOps

Règle Pratique
Secrets .env.local / Secret Manager / variables CI — jamais dans le repo ni le bundle client
Surface Route Handler serveur uniquement pour appels LLM ; le navigateur parle à /api/chat
Prompt injection Instructions système + tools en allowlist ; ne pas exécuter du shell arbitraire depuis le modèle
Coût Limiter max tokens / rate limit (Edge Config, KV, WAF) ; logs usage
Observabilité Callbacks onEnd / lifecycle pour tracer steps, tools, latence
Harnesses Pour agents CLI existants, explorer HarnessAgent (surface Harnesses) plutôt que de réécrire tout

En prod : env projet séparées (preview / production) et modèle gateway piné (provider/model).

Cas d’usage DevOps (rapide)

Trois patterns : chat runbook (/api/chat + useChat, éventuellement RAG), job one-shot (generateText + mesure usage), agent outillé (tools Zod + stopWhen, allowlist stricte — voir prompt injection). L’IA propose ; l’humain valide les changements destructifs. Avant merge : pas de clé dans le diff, modèle piné, onError sur streamText, rate limit sur /api/chat.

Erreurs fréquentes

Symptôme Cause Correction
401 / auth gateway Clé absente ou mauvaise var AI_GATEWAY_API_KEY dans .env.local ; redémarrer pnpm dev
Chat vide après un tool 1 seule step stopWhen: isStepCount(5) (ou condition adaptée)
Types UIMessage vs modèle Mauvais format messages convertToModelMessages(messages)
generateObject is deprecated Ancien tuto Migrer vers Output.object sur generateText / streamText
Secret commité .env versionné Révoquer la clé, ajouter .env* au .gitignore, rotation
Stream qui « ne finit pas » Stream non consommé Toujours renvoyer createUIMessageStreamResponse / consommer textStream

Quiz (3 questions)

1. Quelle fonction Core convient le mieux à un job batch « résumer ce log » ?
– A. useChat
– B. generateText
– C. HarnessAgent uniquement
– D. createNextApp

2. En AI SDK 6, comment produire un objet JSON typé recommandé ?
– A. Parser le markdown à la main
– B. generateText + output: Output.object({ schema })
– C. Uniquement JSON.parse sur text
– D. Forcer streamObject sans alternative

3. Pourquoi ajouter stopWhen: isStepCount(5) avec des tools ?
– A. Accélérer le DNS
– B. Permettre plusieurs steps (tool → synthèse texte)
– C. Remplacer Zod
– D. Désactiver le streaming

Réponses : 1‑B · 2‑B · 3‑B

FAQ rapide

  • AI SDK = uniquement Vercel Hosting ? Non — toolkit TypeScript ; Vercel reste l’éditeur et le gateway est optionnel.
  • Faut-il Next.js ? Non pour Core (generateText en script Node). Next.js + @ai-sdk/react pour le chat UI rapide.
  • Gateway vs @ai-sdk/openai ? Gateway = une clé, beaucoup de modèles en string ; package provider = contrôle direct d’un vendor.
  • Où placer la clé ? Serveur / CI secrets uniquement — jamais NEXT_PUBLIC_* pour une clé LLM.

FAQ

Pourquoi le Vercel AI SDK en DevOps ?
Pour coller rapidement un assistant interne (runbooks, résumé d’incident) avec streaming et tools, sans réinventer le wiring provider.

Clés API côté browser ?
Non — toujours serveur. Rotation et budgets comme tout secret ops.

Lien OpenRouter ?
Oui pour multi-modèles — openrouter-multi-modeles.

Structured outputs ?
ai-structured-outputs · function calling ai-function-calling.

Hub ?
/ia/ · parcours.

Pour aller plus loin

Maillage série IA Outils 2026

← Précédent OpenRouter : multi-modèles
→ Suivant Perplexity pour recherche tech
Hub IA pour DevOps : parcours 2026
Aussi Function calling · Structured outputs · RAG docs infra · MCP DevOps · Ollama locaux

Compléments opérationnels

Standard de brief réutilisable

Pour vercel-ai-sdk, adoptez un brief unique partagé par l’équipe. Il contient toujours cinq champs : objectif mesurable, contexte borné (lab/staging), liste blanche de fichiers ou ressources, interdits explicites (secrets, réseau, prod), et definition of done exécutable (commande de test ou checklist). Sans ces champs, l’outil improvisera — parfois avec élégance, souvent hors périmètre.

Stockez les briefs gagnants sous briefs/vercel-ai-sdk/ dans un dépôt de documentation interne. Chaque brief cite le commit de référence et le modèle utilisé. Au troisième succès comparable, ouvrez une PR qui transforme le brief en rule, Skill ou slash command. Voir ai-skills-concept, claude-skills-instructions et evaluer-qualite-skill.

Revue de diff comme compétence P0

La vitesse d’un agent n’a aucune valeur si personne ne sait lire un diff. Instituez une règle simple : aucun apply massif sans parcours hunk par hunk. Posez-vous trois questions : ce changement est-il demandé ? est-il testé ? est-il réversible ? Si une réponse est non, refusez ou exigez un plan plus petit.

En atelier, faites commenter un diff à voix haute pendant cinq minutes. Les juniors apprennent ainsi le vocabulaire du refus. Reliez cette pratique à ai-code-review-pr et aux workflows ai-agent-workflows.

Sécurité continue

Les surfaces vercel-ai-sdk multiplient les occasions d’injection et de fuite. Traitez tickets, README upstream, logs et ressources MCP comme des données non fiables. Séparez instructions et données. Allowlist tools. Confirmation humaine avant mutation. Guide : ai-prompt-injection-securite, mcp-servers-devops, claude-code-mcp.

Secrets : variables d’environnement de session, gestionnaire d’équipe, rotation, jamais de commit. Si un secret fuit dans un chat vendor, supposez-le compromis et rotatez.

Coûts, modèles et mode dégradé

Documentez un mapping fast/strong et un soft-cap mensuel dans la stack perso. OpenRouter peut aider à basculer — openrouter-multi-modeles. Le local (ollama-llm-locaux + continue-dev) sert de mode dégradé ou de bac à sable confidentialité.

Surveillez les changements silencieux de modèle par défaut : une régression de qualité est souvent un routing vendor, pas « l’équipe qui a oublié comment prompter ».

Ancrage parcours

vercel-ai-sdk n’est qu’une étape du parcours IA DevOps 2026.

Rituals hebdomadaires

Hebdo : promouvoir un brief en Skill/rule ; archiver un échec instructif ; vérifier le budget tokens.

Quand arrêter l’outil

Arrêtez la session si : le DoD échoue deux fois de suite sans diagnostic clair ; l’outil insiste pour sortir du scope ; une commande dangereuse revient après refus ; vous ne comprenez plus le diff.

Ponts concrets vers d’autres tutoriels

Après ce lab, enchaînez selon besoin : agent CLI (claude-code-demarrer, openai-codex-intro-2026, aider-pair-programming), IDE (windsurf-cascade, continue-dev, cursor-agent-composer-2026), qualité (evaluer-qualite-skill, ai-routines-agents), ou recherche (gemini-cli-deep-research, chatgpt-search-browsing).

Retour parcours IA — hub Claude, Codex, ChatGPT et Skills.