Alejandro Rioja.
AI Agents

Gebeurtenisgestuurde vs Geplande Agenten: Welk Patroon voor Welke Taak

Alejandro Rioja
Alejandro Rioja
7 min lezen
TL;DR

Gebruik gebeurtenisgestuurde agenten wanneer een gebruikersactie onmiddellijke reactie vereist — elke vertraging van meer dan een paar seconden breekt de ervaring. Gebruik geplande agenten voor batch- of periodiek werk waarbij de timing voorspelbaar is. De beperking: gebeurtenisgestuurde agenten moeten stateless en snel zijn; geplande agenten mogen stateful en langzamer zijn.

Gratis nieuwsbrief

Elke woensdag. 28.400+ operators. Geen opvulling.

Inhoudsopgave

Bijgewerkt mei 2026.

TL;DR: Gebruik gebeurtenisgestuurde agenten wanneer een gebruikersactie onmiddellijke reactie vereist — elke vertraging van meer dan een paar seconden breekt de ervaring. Gebruik geplande agenten voor batch- of periodiek werk waarbij de timing voorspelbaar is. De beperking: gebeurtenisgestuurde agenten moeten stateless en snel zijn; geplande agenten mogen stateful en langzamer zijn.

[Operatorperspectief] Ik beheer meer dan 30 productieagenten voor mijn consultingmerk en Pickleland, een pickleballfaciliteit in Pflugerville, TX. Elk van hen valt in een van de twee patronen: activeert op een gebeurtenis, of activeert op een klok. Dit verkeerd doen verspilt geld en levert kapotte ervaringen op.

De twee patronen in gewone taal

Een gebeurtenisgestuurde agent wordt wakker omdat er iets is gebeurd. Er is een boeking binnengekomen. Er is een reactie geplaatst. Er is een formulier ingediend. De trigger is extern en onvoorspelbaar in timing. De taak: snel reageren.

Een geplande agent wordt wakker omdat de klok het zegt. Elke ochtend om 7 uur. Elke zondag om 18 uur. Elk uur op het hele uur. De trigger is intern en volledig voorspelbaar. De taak: grondig werk verrichten.

Dat is alles. Maak het niet ingewikkelder. De architectuur volgt uit het antwoord op één vraag: heeft de gebruiker of het systeem nu onmiddellijk een reactie nodig, of kan dit wachten tot een specifiek moment?

Gebeurtenisgestuurd: de social reply-agent

Mijn social reply-agent activeert wanneer er een nieuwe reactie op een gemonitorde Facebook-post verschijnt. De agent leest de reactie, classificeert de intentie (vraag, klacht, compliment, spam), stelt een antwoord op en plaatst het — of markeert het voor menselijke beoordeling als het vertrouwen laag is.

De volledige doorlooptijd moet in minder dan 30 seconden zijn afgerond, anders voelt het antwoord verouderd. Dat is een gebeurtenisgestuurd probleem.

Hier is een vereenvoudigde Cloudflare Worker die de webhook van een social monitoring-service afhandelt:

typescript
// workers/social-reply.ts
export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method !== "POST") {
      return new Response("Method not allowed", { status: 405 });
    }

    // Webhookhandtekening verifiëren
    const sig = request.headers.get("x-webhook-signature") ?? "";
    const body = await request.text();
    const valid = await verifySignature(body, sig, env.WEBHOOK_SECRET);
    if (!valid) return new Response("Unauthorized", { status: 401 });

    const event = JSON.parse(body) as SocialCommentEvent;

    // Classificeren en beantwoorden — async houden zodat we snel 200 kunnen terugsturen
    env.REPLY_QUEUE.send(event);

    return new Response("OK", { status: 200 });
  },
};

// Queue-consumer — doet het echte AI-werk
export const queue: ExportedHandlerQueueHandler<Env, SocialCommentEvent> =
  async (batch, env) => {
    for (const msg of batch.messages) {
      const comment = msg.body;

      const classification = await classifyComment(comment.text, env);
      if (classification.intent === "spam") {
        msg.ack();
        continue;
      }

      const reply = await draftReply(comment, classification, env);

      if (classification.confidence > 0.85) {
        await postReply(comment.postId, comment.id, reply, env);
      } else {
        await flagForReview(comment, reply, env);
      }

      msg.ack();
    }
  };

Twee dingen om op te letten. Ten eerste geeft de fetch handler onmiddellijk 200 terug en verplaatst het echte werk naar een queue. Dit houdt de webhookreactie snel en voorkomt dat de monitoringservice het opnieuw probeert. Ten tweede voert de queue-consumer de echte AI-aanroep uit — classificeren en opstellen — zonder tijdsdruk van een open HTTP-verbinding.

Gepland: de Pickleland evenementenpromotor

Pickleland beheert courts en evenementen. Elke week moet iemand aankomende evenementen naar de juiste Facebook-groepen pushen om plaatsen te vullen. Dit is puur periodiek batchwerk — geen gebruikersactie triggert het, en het hoeft niet in realtime te gebeuren.

De Pickleland evenementenpromotor draait op een cron, controleert het boekingssysteem op evenementen in de komende 4 dagen, stelt locatiespecifieke berichten op voor elke overeenkomende Facebook-groep, en legt ze voor mijn beoordeling voor voordat er iets live gaat.

typescript
// workers/event-promoter.ts
export default {
  async scheduled(
    event: ScheduledEvent,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void> {
    ctx.waitUntil(runPromoter(env));
  },
};

async function runPromoter(env: Env): Promise<void> {
  // Evenementen ophalen uit het boekingssysteem
  const upcomingEvents = await fetchUpcomingEvents(env, { daysAhead: 4 });

  if (upcomingEvents.length === 0) return;

  const drafts: PromoDraft[] = [];

  for (const event of upcomingEvents) {
    // Elk evenement koppelen aan de juiste FB-groepen
    const groups = await matchFacebookGroups(event, env);

    for (const group of groups) {
      const post = await draftPromoPost(event, group, env);
      drafts.push({ event, group, post });
    }
  }

  // Concepten opslaan in Airtable voor beoordeling — niets wordt automatisch geplaatst
  await saveDraftsForReview(drafts, env);

  // Mij notificeren via Slack
  await notifyOperator(
    `${drafts.length} promotieconcepten klaar voor beoordeling`,
    env
  );
}

De wrangler-configuratie die alles verbindt:

toml
# wrangler.toml
[[triggers]]
crons = ["0 18 * * 0"]  # Elke zondag om 18 uur UTC

Merk op wat de geplande agent kan doen wat de gebeurtenisgestuurde niet kan: itereren over meerdere evenementen, schrijven naar een database en een samenvattingsnotificatie sturen. Het doet batchwerk. De gebeurtenisgestuurde agent moet lean blijven en snel reageren.

Gepland: het dagelijkse briefing

Elke ochtend om 7 uur draait mijn dagelijkse briefing-agent. Hij haalt nachtelijke e-mails op, mijn agenda, toptaken en elk nieuws dat ik als relevant heb gemarkeerd. Hij formatteert alles in één document en plaatst het in mijn AI Workspace-map.

Deze is puur gepland. Er is geen gebeurtenis die hem zou activeren — ik wil hem gewoon elke ochtend voordat ik begin met werken.

typescript
// workers/daily-brief.ts
export default {
  async scheduled(
    event: ScheduledEvent,
    env: Env,
    ctx: ExecutionContext
  ): Promise<void> {
    ctx.waitUntil(buildDailyBrief(env));
  },
};

async function buildDailyBrief(env: Env): Promise<void> {
  const [emails, calendar, tasks] = await Promise.all([
    fetchOvernightEmails(env),
    fetchTodayCalendar(env),
    fetchTopTasks(env),
  ]);

  const brief = await synthesizeBrief({ emails, calendar, tasks }, env);

  await writeToWorkspace(brief, env);
}
toml
[[triggers]]
crons = ["0 7 * * *"]  # Elke dag om 7 uur UTC

De parallelle Promise.all is bewust. Geplande agenten hebben geen wachtende mens — maar ze zouden toch niet langzamer moeten zijn dan nodig. Alle databronnen parallel ophalen, dan eenmaal de AI-synthese uitvoeren.

Wanneer gebeurtenisgestuurde agenten falen

Het meest voorkomende faalpatroon: iemand bouwt een gebeurtenisgestuurde agent die te veel werk doet in de handler.

Er komt een boeking binnen. De agent haalt het klantprofiel op, verrijkt het vanuit drie externe API’s, voert een personalisatiemodel uit, schrijft naar het CRM, stuurt de bevestigingsmail en werkt een dashboard bij. Het hele ding duurt 45 seconden. Het boekingsplatform probeert het opnieuw omdat het niet snel genoeg een 200 ontving. Nu draait de agent twee keer.

Correctie: dezelfde aanpak als de social reply-agent — onmiddellijk 200 terugsturen, de gebeurtenis naar een queue pushen, de queue-consumer het zware werk asynchroon laten doen.

Het andere faalpatroon: gebeurtenisgestuurd gebruiken voor werk dat eigenlijk periodiek is. “Een wekelijkse samenvatting sturen” is geen gebeurtenis. Dit niet koppelen aan een synthetische cron-webhook — een juiste geplande trigger gebruiken.

Wanneer geplande agenten falen

Geplande agenten falen wanneer het werk eigenlijk latentiegevoelig is. Als een gebruiker een formulier indient en de agent die het verwerkt draait op een 5-minuten cron, staart de gebruiker tot 5 minuten naar een spinner. Dat is geen gepland job — het is een traag gebeurtenisgestuurd job dat doet alsof het gepland is.

Het andere falen: geplande agenten die uitbreiden naar onbegrensd werk. Als de cron elke minuut draait en elke aanroep honderden records kan verwerken, worden Cloudflare’s CPU-limieten snel bereikt. Ofwel het cron-interval verlengen, een queue toevoegen om het werk per aanroep te begrenzen, ofwel overstappen op Durable Objects voor langlopende coördinatie.

Patronen mixen: de boekingspipeline

Sommige workflows hebben echt beide nodig. De Pickleland boekingspipeline werkt als volgt:

  1. Gebeurtenisgestuurd: nieuwe boeking webhook → boeking bevestigen, kassabon naar klant sturen, beschikbaarheid bijwerken. Moet in minder dan 10 seconden zijn voltooid.
  2. Gepland: elke zondag → alle boekingen van de afgelopen week bekijken, een samenvattingsrapport genereren, anomalieën markeren (dubbele boekingen, ongebruikelijke annuleringspercentages).

Zelfde domein, twee patronen, twee agenten. De gebeurtenisgestuurde is eigenaar van de realtime gebruikerservaring. De geplande is eigenaar van de wekelijkse operationele review. Ze delen een database maar niets anders.

Probeer ze niet samen te voegen in één agent die “alles doet.” Het resultaat is iets dat te langzaam is voor gebeurtenissen en te sterk gekoppeld aan de realtime flow voor batchwerk.

Cloudflare Workers: waarom het de juiste infrastructuur is voor beide

Cloudflare Workers handelt beide patronen native af:

De edge-deployment betekent dat gebeurtenisgestuurde agenten wereldwijd snel reageren. De gratis laag is genereus genoeg om beide patronen te prototypen zonder iets uit te geven. En de uniforme wrangler.toml-configuratie betekent dat je geen twee afzonderlijke infrastructuursetups beheert voor twee patronen.

Het enige wat Workers niet goed oplost: agenten die langer dan een paar minuten moeten draaien. Gebruik daarvoor Durable Objects of delegeer aan een langer durend backend.

De conclusie van de operator

Kies het patroon voordat je een enkele regel agentcode schrijft. Gebeurtenisgestuurd voor alles waarop een mens wacht; gepland voor alles dat op een klok draait. Houd gebeurtenisgestuurde handlers lean — snel reageren, werk in de queue zetten. Houd geplande agenten parallel — niet serialiseren wat je kunt paralleliseren. De architectuur is eenvoudig. Het schenden ervan is waar complexiteit vandaan komt.

Lees verder

Ontvang het AI-playbook in je inbox

Elke woensdag. 28.400+ operators. Geen opvulling.

↵ alle resultaten bekijken esc esc om te sluiten