Use Cases (Mis à jour: 02/06/2026)

Comment développer un chatbot avec Claude Code

Apprenez à développer un chatbot avec Claude Code. Exemples de code pratiques et instructions étape par étape inclus.

Comment développer un chatbot avec Claude Code

Développer un chatbot avec Claude Code

Le développement d’un chatbot IA implique de nombreux éléments : implémentation de l’interface utilisateur, intégration API, gestion des conversations, traitement du streaming, etc. Avec Claude Code, vous pouvez construire un chatbot intégrant tous ces éléments en peu de temps.

Implémentation de l’interface de chat de base

> Crée un composant chatbot en React.
> Avec support du streaming de réponses, affichage de l'historique des conversations et formulaire de saisie.
import { useState, useRef, useEffect } from "react";

interface Message {
  id: string;
  role: "user" | "assistant";
  content: string;
}

export function ChatBot() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState("");
  const [isLoading, setIsLoading] = useState(false);
  const messagesEndRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const sendMessage = async () => {
    if (!input.trim() || isLoading) return;

    const userMessage: Message = {
      id: crypto.randomUUID(),
      role: "user",
      content: input,
    };

    setMessages((prev) => [...prev, userMessage]);
    setInput("");
    setIsLoading(true);

    const assistantId = crypto.randomUUID();
    setMessages((prev) => [
      ...prev,
      { id: assistantId, role: "assistant", content: "" },
    ]);

    try {
      const response = await fetch("/api/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          messages: [...messages, userMessage].map(({ role, content }) => ({
            role,
            content,
          })),
        }),
      });

      const reader = response.body!.getReader();
      const decoder = new TextDecoder();

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        const chunk = decoder.decode(value);
        setMessages((prev) =>
          prev.map((m) =>
            m.id === assistantId
              ? { ...m, content: m.content + chunk }
              : m
          )
        );
      }
    } catch (error) {
      setMessages((prev) =>
        prev.map((m) =>
          m.id === assistantId
            ? { ...m, content: "Une erreur est survenue. Veuillez réessayer." }
            : m
        )
      );
    }

    setIsLoading(false);
  };

  return (
    <div className="flex flex-col h-[600px] border rounded-lg">
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {messages.map((msg) => (
          <div
            key={msg.id}
            className={`flex ${msg.role === "user" ? "justify-end" : "justify-start"}`}
          >
            <div
              className={`max-w-[70%] p-3 rounded-lg ${
                msg.role === "user"
                  ? "bg-blue-600 text-white"
                  : "bg-gray-100 text-gray-900"
              }`}
            >
              {msg.content}
            </div>
          </div>
        ))}
        <div ref={messagesEndRef} />
      </div>

      <div className="border-t p-4 flex gap-2">
        <input
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && sendMessage()}
          placeholder="Saisissez un message..."
          className="flex-1 p-2 border rounded-lg"
          disabled={isLoading}
        />
        <button
          onClick={sendMessage}
          disabled={isLoading}
          className="px-4 py-2 bg-blue-600 text-white rounded-lg disabled:opacity-50"
        >
          Envoyer
        </button>
      </div>
    </div>
  );
}

Route API avec support du streaming

Route API backend qui appelle l’API Anthropic et renvoie les résultats en streaming.

import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic();

export async function POST(request: Request) {
  const { messages } = await request.json();

  const stream = await client.messages.stream({
    model: "claude-sonnet-4-20250514",
    max_tokens: 1024,
    system: "Vous êtes un assistant aimable et attentionné. Répondez en français.",
    messages,
  });

  const encoder = new TextEncoder();

  const readable = new ReadableStream({
    async start(controller) {
      for await (const event of stream) {
        if (
          event.type === "content_block_delta" &&
          event.delta.type === "text_delta"
        ) {
          controller.enqueue(encoder.encode(event.delta.text));
        }
      }
      controller.close();
    },
  });

  return new Response(readable, {
    headers: { "Content-Type": "text/plain; charset=utf-8" },
  });
}

Persistance de l’historique des conversations

Sauvegarde des conversations en base de données pour pouvoir les reprendre ultérieurement.

import { db } from "@/lib/database";

export async function saveConversation(
  userId: string,
  messages: Message[]
) {
  return db.conversation.upsert({
    where: { id: `${userId}-current` },
    update: {
      messages: JSON.stringify(messages),
      updatedAt: new Date(),
    },
    create: {
      id: `${userId}-current`,
      userId,
      messages: JSON.stringify(messages),
    },
  });
}

export async function loadConversation(userId: string): Promise<Message[]> {
  const conv = await db.conversation.findUnique({
    where: { id: `${userId}-current` },
  });
  return conv ? JSON.parse(conv.messages as string) : [];
}

Intégration du RAG (génération augmentée par la recherche)

Pour créer un chatbot qui répond à partir de documents internes, l’architecture RAG est efficace.

import { searchDocuments } from "@/lib/vector-search";

async function generateRAGResponse(query: string, conversationHistory: Message[]) {
  // Recherche de documents pertinents
  const relevantDocs = await searchDocuments(query, { limit: 5 });
  const context = relevantDocs
    .map((doc) => `---\n${doc.title}\n${doc.content}\n---`)
    .join("\n");

  const systemPrompt = `Répondez aux questions en vous appuyant sur les documents suivants.
Si l'information n'est pas disponible dans les documents, répondez « Cette information n'a pas été trouvée ».

${context}`;

  return client.messages.stream({
    model: "claude-sonnet-4-20250514",
    max_tokens: 1024,
    system: systemPrompt,
    messages: conversationHistory,
  });
}

Pour étendre les fonctionnalités avec l’intégration de serveurs MCP, consultez le guide des serveurs MCP, et pour une conception efficace des prompts, consultez 5 astuces pour améliorer vos prompts.

Résumé

Avec Claude Code, vous pouvez développer efficacement un chatbot complet incluant l’interface de chat, l’API streaming, la gestion des conversations et l’architecture RAG. L’approche consistant à ajouter progressivement des fonctionnalités est efficace.

Pour plus de détails, consultez la documentation officielle de Claude Code et la référence API Anthropic.

Mise à niveau 2026 pour la production

Un chatbot est une application qui reçoit un message, conserve le contexte utile et répond sous forme de conversation. Dit simplement, c’est un point d’entrée pour le support, la vente, la recherche documentaire ou l’accompagnement d’un utilisateur. La difficulté n’est pas de dessiner une fenêtre de chat; elle consiste à définir ce que le bot peut faire, ce qu’il ne doit pas promettre, et comment il transfère la demande quand l’automatisation devient risquée.

Avec Claude Code, commencez par un périmètre étroit. Répondre aux dix questions les plus fréquentes est souvent plus rentable qu’un assistant généraliste. Un périmètre clair permet de vérifier les réponses, de limiter les coûts, de protéger les données sensibles et de mesurer si le bot apporte vraiment une valeur commerciale.

Tableau d’architecture

CoucheRôlePoint de vigilance
UI ReactSaisie, historique, chargement et retryLe modèle de base est dans la documentation React useState
Route APIGarde les clés côté serveur et valide la requêteAjoutez taille maximale, authentification et timeout
StreamingAffiche la réponse progressivementLes primitives sont décrites dans MDN Streams API
StockagePermet reprise, audit et améliorationConservez peu de données et prévoyez la suppression
RAGRecherche dans les documents internes ou produitSans preuve suffisante, le bot doit le dire
WebhooksEnvoie les événements vers CRM, tickets ou SlackVoir Claude Code Webhook Implementation
AnalytiqueMesure succès, escalade et clics de CTAComplétez avec Claude Code Analytics Implementation

Pour le contrat d’API, partez du format décrit dans Claude Code API Development: messages avec rôle et contenu, instruction système côté serveur, puis réponse streamée. Ce format reste lisible quand vous ajoutez une application mobile, un widget différent ou une couche de modération.

Démo exécutable de streaming

Enregistrez ce fichier sous chatbot-stream-demo.mjs, puis lancez node chatbot-stream-demo.mjs. Il n’appelle aucun service externe; il vérifie seulement le flux, l’historique et l’ordre des messages.

const encoder = new TextEncoder();
const decoder = new TextDecoder();

const faq = new Map([
  ["password", "Open the account page, choose Reset password, and follow the email link."],
  ["pricing", "The pricing page explains plans. For a custom quote, collect team size and required features."],
  ["refund", "Refund requests should be routed to support with the order id and purchase email."],
]);

const history = [];

function chooseAnswer(question) {
  const normalized = question.toLowerCase();
  for (const [keyword, answer] of faq) {
    if (normalized.includes(keyword)) return answer;
  }
  return "I could not find a safe answer in the FAQ. I will hand this to a human operator.";
}

async function* streamText(text) {
  for (const token of text.split(/(\s+)/)) {
    await new Promise((resolve) => setTimeout(resolve, 15));
    yield encoder.encode(token);
  }
}

async function ask(question) {
  history.push({ role: "user", content: question });
  const answer = chooseAnswer(question);
  process.stdout.write(`\nUser: ${question}\nAssistant: `);

  let fullAnswer = "";
  for await (const chunk of streamText(answer)) {
    const token = decoder.decode(chunk);
    fullAnswer += token;
    process.stdout.write(token);
  }

  history.push({ role: "assistant", content: fullAnswer });
}

await ask("How do I reset my password?");
await ask("Can I see pricing before talking to sales?");

console.log(`\n\nSaved ${history.length} messages.`);

En production, remplacez chooseAnswer par l’appel Claude. Gardez la séquence: enregistrer la question, diffuser la réponse, puis enregistrer la réponse finale. Elle évite un failure fréquent où l’écran affiche du texte partiel mais la base stocke une réponse vide.

Cas d’usage réels

Premier use case: qualification commerciale pour un SaaS. Le chatbot répond aux questions de prix, sécurité, intégrations et conformité, puis propose une consultation quand l’intention est forte. L’équipe commerciale reçoit moins de demandes froides et plus d’échanges préparés.

Deuxième cas: support interne. Congés, notes de frais, VPN, matériel et onboarding génèrent beaucoup de répétitions. Le bot peut citer la page exacte avec RAG et créer un ticket si une validation humaine est nécessaire.

Troisième cas: site de formation ou média technique. Quand un lecteur hésite entre API, webhooks ou analytics, le bot peut recommander les articles pertinents et orienter vers training pour un accompagnement payant. Ce workflow respecte l’intention de lecture au lieu d’afficher une bannière générique.

Quatrième cas: collecte d’incident. Le bot demande message d’erreur, heure, navigateur, compte concerné et étapes de reproduction. Le résultat attendu est un dossier complet pour le support, pas une réponse magique.

Échecs et risques à éviter

N’envoyez pas tout l’historique au modèle. Les longues conversations coûtent plus cher, ralentissent la réponse et peuvent faire remonter de vieilles instructions. Résumez les anciens tours et gardez seulement les décisions utiles.

Ne laissez pas RAG inventer une réponse. Si la recherche documentaire retourne des résultats faibles, le bot doit annoncer l’incertitude et proposer une route humaine. C’est indispensable pour le support, la conformité et la confiance.

Ne sous-estimez pas les risques du streaming. Une connexion coupée peut laisser une bulle vide, un double clic peut mélanger deux réponses, et une requête bloquée peut garder le bouton en chargement. Prévoyez désactivation, annulation, timeout et message de reprise.

Ne publiez pas sans mesure. Suivez les questions non résolues, les escalades, les clics de CTA et les conversations qui mènent à un achat ou une consultation. Le nombre de messages n’est pas un indicateur de qualité.

CTA de monétisation

Le chatbot doit mener vers une seule action commerciale claire: diagnostic, revue d’implémentation, formation ou modèle prêt à adapter. Pour ClaudeCodeLab, la suite logique est training, car le lecteur peut passer de la théorie à une session pratique.

Le parcours éditorial reste simple: comprendre ici, approfondir l’API avec Claude Code API Development, connecter les événements avec webhooks, puis mesurer les conversions avec analytics.

#Claude Code #chatbot #AI #streaming #RAG
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.