La Stack d'Agents que J'Utilise pour Faire Tourner 30+ Agents en Production (Sans Python)
Je fais tourner 30+ agents IA en production avec TypeScript, Cloudflare Workers/Queues/KV et des modèles Claude — sans Python, sans framework d'agents. La stack est volontairement simple : les Workers gèrent le scheduling et les files d'attente, KV stocke l'état, et l'Anthropic SDK pilote les appels au modèle directement. La vraie contrainte n'est pas la couche IA — c'est l'infrastructure qui l'entoure.
Chaque mercredi. 28 400+ opérateurs. Zéro superflu.
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
Table des matières
Mis à jour mai 2026.
TL;DR: Je fais tourner 30+ agents IA en production avec TypeScript, Cloudflare Workers/Queues/KV et des modèles Claude — sans Python, sans framework d’agents. La stack est volontairement simple : les Workers gèrent le scheduling et les files d’attente, KV stocke l’état, et l’Anthropic SDK pilote les appels au modèle directement. La vraie contrainte n’est pas la couche IA — c’est l’infrastructure qui l’entoure.
[Perspective d’opérateur] Je dirige deux entreprises : une marque de conseil en IA et Pickleland — une installation de pickleball à Pflugerville, TX. Entre les deux, j’ai plus de 30 agents en production aujourd’hui. Voici la stack réelle, pas une démo.
Pourquoi pas Python
La réponse honnête : j’écris du TypeScript chaque jour pour mon site web et mes produits. Ajouter un second langage pour les agents signifie deux runtimes, deux arbres de dépendances, deux pipelines de déploiement. Le coût de productivité n’est pas théorique — je l’ai payé sur des projets précédents et j’ai décidé de ne pas recommencer.
La deuxième raison, c’est Cloudflare. Workers exécute TypeScript nativement à l’edge, avec Queues, KV, Durable Objects et Cron Triggers intégrés. Toute l’infrastructure d’agents dont j’ai besoin — scheduling, état, traitement asynchrone de jobs — est à un wrangler deploy de distance. Il n’existe pas d’équivalent Python avec la même surface opérationnelle.
La troisième raison : la plupart des arguments “Python-est-meilleur-pour-l’IA” signifient en réalité “Python a plus de bibliothèques ML.” Je n’entraîne pas de modèles. J’appelle des APIs. L’Anthropic SDK est du TypeScript de première classe. LangChain et ses semblables représentent une complexité dont je ne veux pas. Quand on déploie des agents plutôt que de les étudier, la simplicité gagne.
L’infrastructure centrale : trois primitives Cloudflare
Chaque agent que je fais tourner touche au moins l’une de ces trois :
Cloudflare Workers — la couche de calcul. Un Worker est le runtime de l’agent : il reçoit un trigger (cron, message Queue, HTTP), exécute les appels au modèle et écrit les sorties quelque part. Démarrage à froid sous 5ms. Limite d’exécution de 30 secondes de temps CPU sur le plan gratuit, 15 minutes sur le plan payant. Presque tout ce que je construis tient en 30 secondes ; ce qui ne tient pas utilise les Queues pour le fan-out.
Cloudflare Queues — traitement asynchrone de jobs. Quand une tâche pourrait prendre plus longtemps qu’une requête, ou quand j’ai besoin de fan-out (générer 12 traductions en parallèle), je pousse des messages dans une Queue et laisse les consumers liés les traiter indépendamment. Pas de polling, pas de bidouilles setTimeout.
Cloudflare KV — état léger. Historique des exécutions d’agents, derniers timestamps traités, réponses API en cache. KV est éventuellement cohérent, ce qui convient parfaitement aux agents — je n’exécute pas de transactions. Ça me donne un store clé-valeur simple que je peux lire/écrire depuis n’importe quel Worker sans démarrer une base de données.
La couche modèle : Anthropic SDK, deux modèles
J’utilise exactement deux modèles Claude :
claude-sonnet-4-6— pour les tâches nécessitant un vrai raisonnement : écrire des posts de blog, analyser des données d’événements, générer du copy social, planifier des séquencesclaude-haiku-4-5— pour la classification rapide/bon marché, les décisions de routing, les extractions courtes où le raisonnement complet est excessif
L’Anthropic SDK en TypeScript est direct. Voici le pattern que j’utilise pour chaque appel au modèle :
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ apiKey: env.ANTHROPIC_API_KEY });
async function runAgent(prompt: string, systemPrompt: string): Promise<string> {
const message = await client.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 2048,
system: systemPrompt,
messages: [{ role: "user", content: prompt }],
});
const block = message.content[0];
if (block.type !== "text") throw new Error("Unexpected content type");
return block.text;
}C’est toute l’interface du modèle. Pas d’abstractions par-dessus. Quand j’ai besoin de tool use, j’ajoute un tableau tools. Quand j’ai besoin de streaming, je remplace messages.create par messages.stream. Aucun framework ne gère ça pour moi — et je n’en veux pas.
Un vrai agent : le pipeline de contenu
L’agent le plus complexe que je fais tourner est le pipeline de contenu. Il génère des posts de blog, les traduit en 12 langues, rend des SVGs de cartes OG et rédige des promos LinkedIn — le tout comme brouillons, bloqués derrière ma révision avant que quoi que ce soit ne soit publié.
Le point d’entrée du Worker ressemble à ceci :
// src/workers/content-pipeline.ts
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const { topic, slug } = await request.json<{ topic: string; slug: string }>();
// Étape 1 : générer le post EN
const enPost = await generatePost(topic, env);
await env.CONTENT_KV.put(`draft:${slug}:en`, enPost);
// Étape 2 : fan-out des traductions via Queue
const locales = ["ar", "de", "es", "fr", "hi", "it", "ja", "ko", "nl", "pt", "ru", "zh"];
for (const locale of locales) {
await env.TRANSLATION_QUEUE.send({ slug, locale, content: enPost });
}
return Response.json({ status: "queued", slug });
},
};Chaque traduction s’exécute dans sa propre invocation Worker. Si l’une échoue, la Queue la réessaie automatiquement. J’obtiens 12 traductions en parallèle sans gérer les threads, les promises ou le backoff de rate limit moi-même.
Un vrai agent : le promoteur d’événements
Pickleland organise des événements de pickleball. J’ai construit un agent qui scanne la plateforme de réservation pour les événements des 4 prochains jours, rédige des posts pour des groupes Facebook par événement et les présente pour ma révision avant que quoi que ce soit ne soit publié.
Le system prompt :
const systemPrompt = `You are a community manager for a pickleball facility.
Write Facebook group posts for upcoming events.
Rules:
- Max 150 words per post
- Lead with what's fun about the event, not the price
- Include the booking URL exactly as provided
- Do not use exclamation marks more than once per post
- Tone: friendly, local, not corporate`;La vraie contrainte ici n’est pas le modèle — c’est le workflow. L’agent tourne avec un trigger cron à 8h chaque matin. Les posts brouillons atterrissent dans une file de révision. J’approuve ou modifie, puis un Worker de publication séparé se déclenche. Aucun événement n’est posté sans qu’un humain l’ait vu.
Comment je gère 30+ agents sans perdre la tête
Le dashboard Cloudflare est mon plan de contrôle. Chaque Worker me montre le nombre d’invocations, le taux d’erreurs et le temps CPU. Chaque Queue montre le débit de messages et les échecs. KV montre l’utilisation du stockage.
Au-delà de ça :
- Chaque agent consigne un objet JSON structuré à la fin de chaque exécution :
{ agent, status, durationMs, inputTokens, outputTokens, costUsd } - Je suis les dépenses cumulées par agent par mois dans une simple base Airtable
- Les agents qui dépassent un seuil de coût sont marqués pour révision — cela signifie généralement qu’un prompt est trop verbeux ou que j’utilise Sonnet là où Haiku suffirait
La discipline n’est pas technique. C’est décider ce qu’un agent peut faire de façon autonome versus ce qui nécessite mon approbation. Brouillons de contenu : autonome. Tout ce qui touche un client : révision humaine. Tout ce qui déplace de l’argent : pas un travail d’agent.
Ce que je changerais si je recommençais aujourd’hui
Une chose : j’aurais configuré les sorties structurées (mode JSON) dès le premier jour plutôt que de les ajouter rétroactivement sur des agents déjà déployés. Parser du texte libre de Claude est une taxe. Quand on définit un schéma Zod et qu’on le passe comme forme de réponse attendue, on récupère des données typées et les Workers en aval n’ont pas à deviner.
import { z } from "zod";
const EventPostSchema = z.object({
headline: z.string().max(80),
body: z.string().max(600),
bookingUrl: z.string().url(),
suggestedPostTime: z.enum(["morning", "afternoon", "evening"]),
});La conclusion de l’opérateur
La stack d’agents qui fonctionne en production est celle que vous pouvez déboguer à 22h quand quelque chose se casse. Pour moi, c’est TypeScript + Cloudflare + Anthropic SDK — non pas parce que c’est la combinaison la plus glamour, mais parce que chaque couche est observable, déployable et remplaçable indépendamment. Les frameworks sont des paris sur des abstractions. Je préfère posséder la plomberie.
Chaque mercredi. 28 400+ opérateurs. Zéro superflu.
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
Recevez le guide IA dans votre boîte mail
Chaque mercredi. 28 400+ opérateurs. Zéro superflu.
Check your inbox.
We sent you a confirmation email — click the link inside to complete your subscription. Check spam if you don't see it within a minute.
You're subscribed.
Welcome — the next edition lands in your inbox soon.
You're already on the list — look for it every Wednesday.