De Agent-Stack die Ik Gebruik voor 30+ Productie-Agents (Zonder Python)
Ik draai 30+ productie-AI-agents met TypeScript, Cloudflare Workers/Queues/KV en Claude-modellen — geen Python, geen agent-framework. De stack is bewust eenvoudig: Workers verwerken scheduling en queuing, KV slaat de staat op, en de Anthropic SDK stuurt de modelaanroepen direct aan. De bepalende beperking is niet de AI-laag — het is de infrastructuur eromheen.
Elke woensdag. 28.400+ operators. Geen opvulling.
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
Inhoudsopgave
Bijgewerkt mei 2026.
TL;DR: Ik draai 30+ productie-AI-agents met TypeScript, Cloudflare Workers/Queues/KV en Claude-modellen — geen Python, geen agent-framework. De stack is bewust eenvoudig: Workers verwerken scheduling en queuing, KV slaat de staat op, en de Anthropic SDK stuurt de modelaanroepen direct aan. De bepalende beperking is niet de AI-laag — het is de infrastructuur eromheen.
[Operator-perspectief] Ik run twee bedrijven: een AI-consultancymerk en Pickleland — een pickleballfaciliteit in Pflugerville, TX. Samen hebben ze vandaag meer dan 30 agents in productie. Dit is de echte stack, geen demo.
Waarom geen Python
Het eerlijke antwoord: ik schrijf elke dag TypeScript voor mijn website- en productwerk. Een tweede taal toevoegen voor agents betekent twee runtimes, twee afhankelijkheidsbomen, twee deployment-pipelines. De productiviteitskosten zijn niet theoretisch — ik heb ze betaald bij eerdere projecten en besloten het niet opnieuw te doen.
De tweede reden is Cloudflare. Workers draait TypeScript native op de edge, met ingebouwde Queues, KV, Durable Objects en Cron Triggers. De volledige agent-infrastructuur die ik nodig heb — scheduling, staat, asynchrone jobverwerking — is één wrangler deploy verwijderd. Er bestaat geen Python-equivalent met dezelfde operationele eenvoud.
De derde reden: de meeste “Python-is-beter-voor-AI”-argumenten betekenen eigenlijk “Python heeft meer ML-bibliotheken.” Ik train geen modellen. Ik roep APIs aan. De Anthropic SDK is eersteklas TypeScript. LangChain en vergelijkbare tools zijn complexiteit die ik niet wil. Als je agents deployt in plaats van onderzoekt, wint eenvoud.
De kern-infrastructuur: drie Cloudflare-primitieven
Elke agent die ik run raakt minimaal een van deze drie:
Cloudflare Workers — de rekenlaag. Een Worker is de runtime van de agent: hij ontvangt een trigger (cron, Queue-bericht, HTTP), voert de modelaanroepen uit en schrijft outputs ergens naartoe. Cold start onder 5ms. Uitvoerlimiet 30 seconden CPU-tijd op het gratis plan, 15 minuten op betaald. Bijna alles wat ik bouw past in 30 seconden; wat niet past, gebruikt Queues voor fan-out.
Cloudflare Queues — asynchrone jobverwerking. Als een taak langer kan duren dan een request, of als ik fan-out nodig heb (12 vertalingen parallel genereren), duw ik berichten in een Queue en laat gebonden consumers ze onafhankelijk verwerken. Geen polling, geen setTimeout-hacks.
Cloudflare KV — lichtgewicht staat. Agent-uitvoeringsgeschiedenis, laatste verwerkte tijdstempels, gecachte API-antwoorden. KV is uiteindelijk consistent, wat prima is voor agents — ik voer geen transacties uit. Het geeft me een eenvoudige sleutel-waardeopslag die ik vanuit elke Worker kan lezen/schrijven zonder een database op te starten.
De modellaag: Anthropic SDK, twee modellen
Ik gebruik precies twee Claude-modellen:
claude-sonnet-4-6— voor taken die echte redenering vereisen: blogposts schrijven, eventdata analyseren, sociale copy genereren, sequenties plannenclaude-haiku-4-5— voor snelle/goedkope classificatie, routingbeslissingen, korte extracties waar volledige redenering overdreven is
De Anthropic SDK in TypeScript is rechtdoorzee. Dit is het patroon dat ik gebruik voor elke modelaanroep:
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;
}Dat is de volledige modelinterface. Geen abstracties bovenop. Als ik tool use nodig heb, voeg ik een tools-array toe. Als ik streaming nodig heb, vervang ik messages.create door messages.stream. Geen framework beheert dit voor mij — en dat wil ik ook niet.
Een echte agent: de content-pipeline
De meest complexe agent die ik draai is de content-pipeline. Hij genereert blogposts, vertaalt ze naar 12 talen, rendert OG-card-SVG’s en stelt LinkedIn-promoties op — alles als concepten, geblokkeerd achter mijn beoordeling voordat er iets gepubliceerd wordt.
Het Worker-ingangspunt ziet er zo uit:
// 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 }>();
// Stap 1: EN-post genereren
const enPost = await generatePost(topic, env);
await env.CONTENT_KV.put(`draft:${slug}:en`, enPost);
// Stap 2: vertalingen fan-outen 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 });
},
};Elke vertaling wordt uitgevoerd in zijn eigen Worker-aanroep. Als een mislukt, probeert de Queue het automatisch opnieuw. Ik krijg 12 parallelle vertalingen zonder threads, promises of rate-limit backoff zelf te beheren.
Een echte agent: de eventpromotor
Pickleland organiseert pickleballevenementen. Ik heb een agent gebouwd die het boekingsplatform scant voor evenementen in de komende 4 dagen, Facebook-groepsberichten per evenement opstelt en ze ter beoordeling aanbiedt voordat er iets naar buiten gaat.
De systeemprompt:
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`;De bepalende beperking hier is niet het model — het is de workflow. De agent draait dagelijks om 8 uur op een cron-trigger. De conceptberichten landen in een beoordelingswachtrij. Ik keur goed of bewerk, dan viert een aparte publicatie-Worker. Geen evenement wordt gepost zonder dat een mens het heeft gezien.
Hoe ik 30+ agents beheer zonder mijn verstand te verliezen
Het Cloudflare-dashboard is mijn besturingsvlak. Elke Worker toont me aanroeptellingen, foutenpercentage en CPU-tijd. Elke Queue toont berichtdoorvoer en mislukkingen. KV toont opslaggebruik.
Daarnaast:
- Elke agent logt aan het einde van elke run een gestructureerd JSON-object:
{ agent, status, durationMs, inputTokens, outputTokens, costUsd } - Ik houd cumulatieve uitgaven per agent per maand bij in een eenvoudige Airtable-database
- Agents die een kostendrempel overschrijden worden gemarkeerd voor beoordeling — doorgaans betekent dat een prompt te uitgebreid is of dat ik Sonnet gebruik waar Haiku zou volstaan
De discipline is niet technisch. Het is beslissen wat een agent autonoom mag doen versus wat mijn goedkeuring nodig heeft. Contentconcepten: autonoom. Alles wat een klant raakt: menselijke beoordeling. Alles wat geld verplaatst: geen agentwerk.
Wat ik zou veranderen als ik vandaag begon
Eén ding: ik zou gestructureerde outputs (JSON-modus) vanaf dag één instellen in plaats van ze achteraf op al gedeployde agents te zetten. Vrije Claude-tekst parsen is een belasting. Als je een Zod-schema definieert en het doorgeeft als de verwachte antwoordvorm, krijg je getypeerde data terug en hoeven downstream Workers niet te gissen.
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"]),
});De conclusie van de operator
De agent-stack die in productie werkt, is degene die je om 22 uur kunt debuggen als er iets kapotgaat. Voor mij is dat TypeScript + Cloudflare + Anthropic SDK — niet omdat het de meest glamoureuze combinatie is, maar omdat elke laag onafhankelijk observeerbaar, deploybaar en vervangbaar is. Frameworks zijn weddenschappen op abstracties. Ik heb liever eigenaarschap over de loodgieterij.
Elke woensdag. 28.400+ operators. Geen opvulling.
✓ Check your inbox — click the confirmation link to complete sign-up.
✓ You're subscribed!
✓ You're already on the list.
Ontvang het AI-playbook in je inbox
Elke woensdag. 28.400+ operators. Geen opvulling.
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.