Alejandro Rioja.
AI Agents

Agents par Événements vs Agents Planifiés : Quel Pattern pour Quel Travail

Alejandro Rioja
Alejandro Rioja
8 min de lecture
TL;DR

Utilisez des agents par événements quand une action utilisateur exige une réponse immédiate – au-delà de quelques secondes, l'expérience se brise. Utilisez des agents planifiés pour les traitements par lots ou périodiques où le timing est prévisible. La contrainte : les agents par événements doivent être sans état et rapides ; les agents planifiés peuvent être avec état et plus lents.

Newsletter gratuite

Chaque mercredi. 28 400+ opérateurs. Zéro superflu.

Table des matières

Mis à jour mai 2026.

TL;DR : Utilisez des agents par événements quand une action utilisateur exige une réponse immédiate – au-delà de quelques secondes, l’expérience se brise. Utilisez des agents planifiés pour les traitements par lots ou périodiques où le timing est prévisible. La contrainte : les agents par événements doivent être sans état et rapides ; les agents planifiés peuvent être avec état et plus lents.

[Perspective d’opérateur] Je gère plus de 30 agents en production pour ma marque de conseil et Pickleland, une salle de pickleball à Pflugerville, TX. Chacun d’eux correspond à l’un des deux patterns : se déclenche sur un événement, ou se déclenche sur une horloge. Se tromper ici gaspille de l’argent et livre des expériences cassées.

Les deux patterns en langage simple

Un agent par événements se réveille parce que quelque chose s’est passé. Une réservation est arrivée. Un commentaire a été posté. Un formulaire a été soumis. Le déclencheur est externe et imprévisible dans le temps. Le travail : répondre vite.

Un agent planifié se réveille parce que l’horloge l’indique. Chaque matin à 7h. Chaque dimanche à 18h. Chaque heure à l’heure pile. Le déclencheur est interne et totalement prévisible. Le travail : faire un travail minutieux.

C’est tout. Ne compliquez pas. L’architecture découle de la réponse à une question : l’utilisateur ou le système a-t-il besoin d’une réponse maintenant, ou peut-on attendre jusqu’à un moment précis ?

Par événements : l’agent de réponse sociale

Mon agent de réponse sociale se déclenche à chaque nouveau commentaire sur un post Facebook surveillé. L’agent lit le commentaire, classifie l’intention (question, plainte, compliment, spam), rédige une réponse et la publie – ou la signale pour révision humaine si la confiance est faible.

Le cycle complet doit se terminer en moins de 30 secondes, sinon la réponse paraît dépassée. C’est un problème de déclenchement par événements.

Voici un Cloudflare Worker simplifié qui gère le webhook d’un service de surveillance sociale :

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 });
    }

    // Vérifier la signature du webhook
    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;

    // Classer et répondre — garder async pour retourner 200 vite
    env.REPLY_QUEUE.send(event);

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

// Consommateur de file — fait le vrai travail d'IA
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();
    }
  };

Deux choses à noter. Premièrement, le handler fetch retourne 200 immédiatement et délègue le vrai travail à une file d’attente. Cela maintient la réponse au webhook rapide et empêche le service de surveillance de réessayer. Deuxièmement, le consommateur de file effectue le vrai appel IA – classification et rédaction – sans pression temporelle due à une connexion HTTP ouverte.

Planifié : le promoteur d’événements Pickleland

Pickleland gère des courts et des événements. Chaque semaine, quelqu’un doit pousser les prochains événements vers les bons groupes Facebook pour remplir les places. C’est du pur travail par lots périodique – aucune action utilisateur ne le déclenche, et ça n’a pas besoin de se passer en temps réel.

Le promoteur d’événements Pickleland tourne sur un cron, vérifie le système de réservation pour les événements dans les 4 prochains jours, rédige des posts spécifiques à chaque groupe Facebook correspondant, et les présente pour ma révision avant que quoi que ce soit soit publié.

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> {
  // Récupérer les événements du système de réservation
  const upcomingEvents = await fetchUpcomingEvents(env, { daysAhead: 4 });

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

  const drafts: PromoDraft[] = [];

  for (const event of upcomingEvents) {
    // Associer chaque événement aux bons groupes FB
    const groups = await matchFacebookGroups(event, env);

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

  // Sauvegarder les brouillons dans Airtable pour révision — rien ne se publie automatiquement
  await saveDraftsForReview(drafts, env);

  // Me notifier par Slack
  await notifyOperator(
    `${drafts.length} brouillons promo prêts pour révision`,
    env
  );
}

La config wrangler qui relie tout :

toml
# wrangler.toml
[[triggers]]
crons = ["0 18 * * 0"]  # Chaque dimanche à 18h UTC

Notez ce que l’agent planifié peut faire que l’événementiel ne peut pas : il itère sur plusieurs événements, écrit dans une base de données, et envoie une notification récapitulative. Il fait du travail par lots. L’agent par événements doit rester léger et répondre vite.

Planifié : le briefing quotidien

Chaque matin à 7h, mon agent de briefing quotidien tourne. Il récupère les emails de la nuit, mon calendrier, les tâches prioritaires, et toute actualité que j’ai marquée comme pertinente. Il formate tout dans un document unique et le dépose dans mon dossier AI Workspace.

Celui-ci est purement planifié. Il n’y a aucun événement qui le déclencherait – je veux simplement qu’il tourne chaque matin avant de commencer à travailler.

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 * * *"]  # Chaque jour à 7h UTC

Le Promise.all parallèle est délibéré. Les agents planifiés n’ont pas d’humain qui attend – mais ils ne devraient quand même pas être plus lents que nécessaire. Récupérer toutes les sources de données en parallèle, puis faire la synthèse IA une seule fois.

Quand les agents par événements échouent

Le mode d’échec le plus fréquent : quelqu’un construit un agent par événements qui fait trop de travail dans le handler.

Une réservation arrive. L’agent récupère le profil client, l’enrichit depuis trois APIs externes, exécute un modèle de personnalisation, écrit dans le CRM, envoie l’email de confirmation, et met à jour un tableau de bord. Le tout prend 45 secondes. La plateforme de réservation réessaie parce qu’elle n’a pas eu de 200 assez vite. Maintenant l’agent tourne deux fois.

Correction : même approche que l’agent de réponse sociale – retourner 200 immédiatement, pousser l’événement dans une file, laisser le consommateur de file faire le travail lourd de façon asynchrone.

L’autre mode d’échec : utiliser par événements pour du travail qui est en réalité périodique. “Envoyer un récapitulatif hebdomadaire” n’est pas un événement. Ne pas le connecter à un webhook cron synthétique – utiliser un déclencheur planifié approprié.

Quand les agents planifiés échouent

Les agents planifiés échouent quand le travail est en réalité sensible à la latence. Si un utilisateur soumet un formulaire et que l’agent qui le traite tourne sur un cron de 5 minutes, l’utilisateur regarde un spinner pendant 5 minutes. Ce n’est pas un job planifié – c’est un job par événements lent qui prétend être planifié.

L’autre échec : des agents planifiés qui s’étendent à un travail illimité. Si votre cron tourne chaque minute et que chaque invocation peut traiter des centaines d’enregistrements, vous atteindrez vite les limites CPU de Cloudflare. Soit augmenter l’intervalle du cron, ajouter une file pour borner le travail par invocation, soit passer aux Durable Objects pour la coordination longue durée.

Mélanger les patterns : le pipeline de réservations

Certains workflows ont vraiment besoin des deux. Le pipeline de réservations Pickleland fonctionne ainsi :

  1. Par événements : webhook nouvelle réservation → confirmer la réservation, envoyer le reçu au client, mettre à jour la disponibilité. Doit se terminer en moins de 10 secondes.
  2. Planifié : chaque dimanche → examiner toutes les réservations de la semaine passée, générer un rapport récapitulatif, signaler les anomalies (réservations en double, taux d’annulation inhabituels).

Même domaine, deux patterns, deux agents. L’événementiel possède l’expérience utilisateur en temps réel. Le planifié possède la revue opérationnelle hebdomadaire. Ils partagent une base de données, mais rien d’autre.

Ne pas essayer de les combiner en un seul agent qui “fait tout.” Le résultat serait quelque chose de trop lent pour les événements et trop couplé au flux temps réel pour le travail par lots.

Cloudflare Workers : pourquoi c’est la bonne infrastructure pour les deux

Cloudflare Workers gère les deux patterns nativement :

Le déploiement en edge signifie que vos agents par événements répondent vite globalement. Le niveau gratuit est assez généreux pour prototyper les deux patterns sans dépenser. Et la configuration unifiée wrangler.toml signifie qu’on ne gère pas deux setups d’infrastructure séparés pour deux patterns.

La seule chose que Workers ne résout pas bien : les agents qui doivent tourner plus de quelques minutes. Pour ceux-là, utiliser les Durable Objects ou déléguer à un backend plus longue durée.

La conclusion de l’opérateur

Choisir son pattern avant d’écrire une seule ligne de code d’agent. Par événements pour tout ce qu’un humain attend ; planifié pour tout ce qui tourne selon une horloge. Garder les handlers par événements légers – répondre vite, mettre le travail en file. Garder les agents planifiés parallèles – ne pas sérialiser ce qu’on peut paralléliser. L’architecture est simple. La violer est la source de la complexité.

Continuer à lire

Recevez le guide IA dans votre boîte mail

Chaque mercredi. 28 400+ opérateurs. Zéro superflu.

↵ pour voir tous les résultats esc esc pour fermer