Lo Stack di Agenti che Uso per Gestire 30+ Agenti in Produzione (Senza Python)
Gestisco 30+ agenti AI in produzione usando TypeScript, Cloudflare Workers/Queues/KV e modelli Claude — senza Python, senza framework per agenti. Lo stack è volutamente semplice: i Workers gestiscono scheduling e code, KV memorizza lo stato, e l'Anthropic SDK pilota le chiamate al modello direttamente. Il vero vincolo non è il layer AI — è l'infrastruttura che lo circonda.
Ogni mercoledì. 28.400+ operatori. Zero riempitivo.
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
Indice
Aggiornato maggio 2026.
TL;DR: Gestisco 30+ agenti AI in produzione usando TypeScript, Cloudflare Workers/Queues/KV e modelli Claude — senza Python, senza framework per agenti. Lo stack è volutamente semplice: i Workers gestiscono scheduling e code, KV memorizza lo stato, e l’Anthropic SDK pilota le chiamate al modello direttamente. Il vero vincolo non è il layer AI — è l’infrastruttura che lo circonda.
[Prospettiva dell’operatore] Gestisco due aziende: un brand di consulenza AI e Pickleland — una struttura per il pickleball a Pflugerville, TX. Tra le due ho più di 30 agenti in produzione oggi. Questo è lo stack reale, non una demo.
Perché senza Python
La risposta onesta: scrivo TypeScript ogni giorno per il mio lavoro su sito web e prodotti. Aggiungere un secondo linguaggio per gli agenti significa due runtime, due alberi di dipendenze, due pipeline di deploy. Il costo in termini di produttività non è teorico — l’ho pagato su progetti precedenti e ho deciso di non rifarlo.
Il secondo motivo è Cloudflare. Workers esegue TypeScript nativamente all’edge, con Queues, KV, Durable Objects e Cron Triggers integrati. Tutta l’infrastruttura per agenti di cui ho bisogno — scheduling, stato, elaborazione asincrona di job — è a un wrangler deploy di distanza. Non esiste un equivalente Python con la stessa semplicità operativa.
Il terzo motivo: la maggior parte degli argomenti “Python-è-meglio-per-l’AI” significa davvero “Python ha più librerie ML.” Non alleno modelli. Chiamo API. L’Anthropic SDK è TypeScript di prima classe. LangChain e simili sono complessità che non voglio. Quando stai distribuendo agenti, non facendo ricerca, la semplicità vince.
L’infrastruttura centrale: tre primitive Cloudflare
Ogni agente che gestisco tocca almeno uno di questi tre:
Cloudflare Workers — il layer di calcolo. Un Worker è il runtime dell’agente: riceve un trigger (cron, messaggio Queue, HTTP), esegue le chiamate al modello e scrive gli output da qualche parte. Cold start sotto 5ms. Limite di esecuzione 30 secondi di tempo CPU sul piano gratuito, 15 minuti su quello a pagamento. Quasi tutto ciò che costruisco sta in 30 secondi; ciò che non sta usa le Queues per il fan-out.
Cloudflare Queues — elaborazione asincrona di job. Quando un’attività potrebbe richiedere più tempo di una richiesta, o quando ho bisogno di fan-out (generare 12 traduzioni in parallelo), spingo messaggi in una Queue e lascio che i consumer associati li elaborino indipendentemente. Niente polling, niente hack con setTimeout.
Cloudflare KV — stato leggero. Storico delle esecuzioni degli agenti, ultimi timestamp elaborati, risposte API in cache. KV è eventualmente coerente, il che va bene per gli agenti — non eseguo transazioni. Mi dà un semplice store chiave-valore che posso leggere/scrivere da qualsiasi Worker senza avviare un database.
Il layer del modello: Anthropic SDK, due modelli
Uso esattamente due modelli Claude:
claude-sonnet-4-6— per attività che richiedono ragionamento reale: scrivere post di blog, analizzare dati di eventi, generare copy social, pianificare sequenzeclaude-haiku-4-5— per classificazione rapida/economica, decisioni di routing, estrazioni brevi dove il ragionamento completo è eccessivo
L’Anthropic SDK in TypeScript è diretto. Ecco il pattern che uso per ogni chiamata al modello:
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;
}Questa è l’intera interfaccia del modello. Nessuna astrazione sopra. Quando ho bisogno di tool use, aggiungo un array tools. Quando ho bisogno di streaming, sostituisco messages.create con messages.stream. Nessun framework gestisce questo per me — e non lo voglio.
Un agente reale: la content pipeline
L’agente più complesso che gestisco è la content pipeline. Genera post di blog, li traduce in 12 lingue, renderizza SVG di card OG e redige promozioni LinkedIn — tutto come bozze, bloccate dietro la mia revisione prima che venga pubblicato qualcosa.
Il punto di ingresso del Worker si presenta così:
// 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 }>();
// Step 1: genera il post EN
const enPost = await generatePost(topic, env);
await env.CONTENT_KV.put(`draft:${slug}:en`, enPost);
// Step 2: fan-out delle traduzioni 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 });
},
};Ogni traduzione viene eseguita nella propria invocazione Worker. Se una fallisce, la Queue la riprova automaticamente. Ottengo 12 traduzioni in parallelo senza gestire thread, promise o rate-limit backoff.
Un agente reale: il promotore di eventi
Pickleland organizza eventi di pickleball. Ho costruito un agente che scansiona la piattaforma di prenotazione per eventi nei prossimi 4 giorni, redige post per gruppi Facebook per evento e li presenta per la mia revisione prima che esca qualcosa.
Il 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`;Il vero vincolo qui non è il modello — è il workflow. L’agente gira con un trigger cron alle 8 ogni mattina. I post bozza atterrano in una coda di revisione. Approvo o modifico, poi un Worker di pubblicazione separato si attiva. Nessun evento viene pubblicato senza che un umano l’abbia visto.
Come gestisco 30+ agenti senza impazzire
La dashboard di Cloudflare è il mio piano di controllo. Ogni Worker mi mostra il conteggio delle invocazioni, il tasso di errori e il tempo CPU. Ogni Queue mostra il throughput dei messaggi e i fallimenti. KV mostra l’utilizzo dello storage.
Oltre a questo:
- Ogni agente registra un oggetto JSON strutturato alla fine di ogni esecuzione:
{ agent, status, durationMs, inputTokens, outputTokens, costUsd } - Traccio la spesa cumulativa per agente al mese in una semplice base Airtable
- Gli agenti che superano una soglia di costo vengono segnalati per revisione — di solito significa che un prompt è troppo prolisso o che sto usando Sonnet dove Haiku basterebbe
La disciplina non è tecnica. È decidere cosa un agente può fare autonomamente versus cosa richiede la mia approvazione. Bozze di contenuto: autonomo. Qualsiasi cosa tocchi un cliente: revisione umana. Qualsiasi cosa muova denaro: non è lavoro per un agente.
Cosa cambierei se ricominciassi oggi
Una cosa: avrei configurato gli output strutturati (modalità JSON) fin dal primo giorno invece di aggiungerli retroattivamente ad agenti già distribuiti. Parsare testo libero di Claude è una tassa. Quando definisci uno schema Zod e lo passi come forma di risposta attesa, ottieni dati tipizzati e i Workers a valle non devono indovinare.
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 conclusione dell’operatore
Lo stack di agenti che funziona in produzione è quello che puoi debuggare alle 22 quando qualcosa si rompe. Per me, è TypeScript + Cloudflare + Anthropic SDK — non perché sia la combinazione più glamour, ma perché ogni layer è osservabile, distribuibile e sostituibile indipendentemente. I framework sono scommesse sulle astrazioni. Preferisco possedere l’impianto idraulico.
Ogni mercoledì. 28.400+ operatori. Zero riempitivo.
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
Ricevi il manuale dell'IA nella tua casella di posta
Ogni mercoledì. 28.400+ operatori. Zero riempitivo.
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.