Le Guide des Agents — StreamFlow Pulse
Observer → décider → agir. Un agent est un pipeline sur un flux — pas une boucle de chat.
Table des Matières
1. Le modèle mental
Un agent dans Pulse n'est pas une boucle de chat. C'est un pipeline qui vit sur un flux : une source alimente des évènements dans un topic, une chaîne d'étapes transforme et décide, et un sink (ou l'agent suivant) reçoit le résultat. Chaque étape utilise l'un des quatre moteurs et publie sa sortie sur son propre topic — <app>.in → <stage>.out → … — pour que chaque décision intermédiaire soit observable, tail-able et rejouable.
La boucle à garder en tête : observer → décider → agir. Les sources observent. Les étapes décident. Les sinks et outils MCP agissent. Comme chaque sortie n'est qu'un autre topic, le « multi-agent » n'est pas une fonctionnalité du framework — c'est simplement pointer l'entrée de l'agent suivant sur la sortie de l'agent précédent.
2. Démarrage rapide — quatre commandes
1# 0. boot a local Pulse and log the CLI in (dev mode)
2pulse server start --dev
3
4# 1. scaffold: source → stages → sink
5pulse new oncall \
6 --source file-tail \
7 --stage rule-based:triage \
8 --stage llm:reason \
9 --stage mcp:act \
10 --sink webhook
11
12# 2. fill in pulse.yaml (paths, rules, prompt, tools) then deploy
13pulse deploy .
14
15# 3. feed it an event and watch it decide, live
16pulse events send --topic oncall.in --data @sample.json
17pulse events tail --topic oncall.reason.outLe scaffolding écrit trois fichiers : pulse.yaml (l'app), sample.json (un évènement de test) et un README.md. Le deploy monte la source, la chaîne d'étapes reliées par topics, le sink — plus une API HTTP typée et un SDK pour l'app.
Découvrir ce qui est disponible : pulse new --list-sources, --list-sinks et --list-operators énumèrent la palette de connecteurs et d'opérateurs. --list-templates affiche les apps prêtes à l'emploi utilisables via --from-template.
3. Anatomie de pulse.yaml
1source: # OBSERVE — where events come from
2 kind: file-tail # file-tail · webhook · http-poll · jdbc-source · …
3 path: /var/log/app/events.log
4
5stages: # DECIDE — each stage = one engine
6 - name: triage
7 engine: rule-based
8 rules: [ "severity == 'error'" ]
9
10 - name: reason
11 engine: llm
12 systemPrompt: |
13 Classify the incident and draft a
14 one-line on-call summary.
15
16 - name: act
17 engine: mcp
18 mcpTools: [ pagerduty.createIncident ]
19
20sink: # ACT — where results go (optional)
21 kind: webhook
22 url: ${secret:ALERT_WEBHOOK}- source — un bloc, un type de connecteur. Ses évènements atterrissent sur <app>.in.
- stages — une chaîne ordonnée. L'étape n consomme le topic de sortie de l'étape n−1 et publie sur <app>.<stage>.out.
- sink — optionnel. Tout ce que la palette propose : webhook, chat, JDBC, protocole Kafka, fichiers…
- secrets — toujours
$${secret:NAME}ou$${env:VAR}, jamais en clair. Le deploy échoue bruyamment sur les références non résolues plutôt que d'expédier une config cassée.
4. Les quatre moteurs
La règle de conception qui rend les agents rapides et bon marché : utiliser le moteur le moins cher capable de prendre chaque décision. Façonner avec streaming, filtrer avec rule-based, réserver llm à la vraie ambiguïté, et agir sur le monde avec mcp.
engine: streaming — façonner le flux
Traitement de flux déterministe et stateful, au coût microseconde. Aucun modèle sur le chemin.
| Capacité | Ce que vous déclarez |
|---|---|
| Fenêtres | tumbling / sliding, clées sur tout champ, event-time avec watermarks ; les évènements en retard vont en DLQ |
| Agrégations | count · sum · min · max · avg · first · last · stddev · countWhere(expr) · sumWhere(expr) |
| Opérateurs | filter · map · reduce · aggregate · dedup · join (stream-stream) · process (état keyed + timers) |
| Entrées | union multi-topic — une étape peut consommer plusieurs topics |
engine: rule-based — décider l'évident
Prédicats déclaratifs sur les champs d'évènement. Les évènements qui matchent passent (éventuellement transformés) ; les autres s'arrêtent. À utiliser pour garder 95 % du trafic loin du LLM : routage, filtrage, seuils, triage.
engine: llm — raisonner sur les cas difficiles
Un appel de modèle par évènement, piloté par votre systemPrompt. Amenez votre fournisseur : configurez une clé API pour un modèle hébergé, ou pointez vers un runtime de modèle local pour l'inférence on-prem. L'étape reçoit l'évènement (plus les enrichissements amont) et émet la réponse structurée du modèle sur son topic de sortie.
Contrainte honnête : aucun fournisseur configuré → l'étape llm se déclare unhealthy plutôt que de laisser passer les évènements silencieusement. Même philosophie partout : une étape cassée est visible, jamais invisible.
engine: mcp — agir sur le monde
Des étapes qui appellent de vrais outils via le Model Context Protocol : interroger des systèmes, créer des tickets, lancer des workflows, ou attendre une approbation humaine — l'humain est une étape du pipeline, pas un ajout tardif. Les outils viennent de plugins MCP installés dans Pulse ; mcpTools liste ceux que l'étape peut invoquer.
Contrainte honnête : tant que son plugin n'est pas installé, une étape mcp affiche blocked dans la vue pipeline. C'est voulu — vous voyez exactement ce qui manque au lieu d'un no-op silencieux.
5. Composer des systèmes multi-agents
Aucune couche d'orchestration spéciale à apprendre. Les topics sont la primitive de composition :
- Chaîner — la source de l'agent B lit le topic de sortie de l'agent A. Un pipeline de pipelines.
- Fan out — plusieurs agents s'abonnent au même topic ; chacun voit chaque évènement.
- Fan in — une étape streaming prend une union multi-topic et fusionne les flux.
- Corréler — un join stream-stream apparie des évènements entre deux flux dans une fenêtre (une commande et son paiement, une alerte et son ack).
Comme chaque saut est un topic durable, les jointures entre agents sont observables par défaut — pulse events tail fonctionne à chaque jointure, pas seulement aux extrémités.
6. Appeler votre agent depuis l'extérieur
Chaque app déployée expose la même surface HTTP, donc n'importe quel client — un script, un moteur de workflow, un orchestrateur — s'intègre de la même façon :
| Besoin | Endpoint |
|---|---|
| Envoyer un évènement | POST /api/pulse/x/<app>/in |
| Lire les résultats | GET /api/pulse/events/<topic> |
| Streamer les résultats live | GET /api/pulse/events/stream (SSE) |
| Requête/réponse sur un flux | pulse-py client.duplex() (WebSocket corrélé) |
Des exemples de ponts sont fournis dans le repo pour les moteurs de workflow, orchestrateurs et plateformes d'intégration les plus courants — même surface Pulse à chaque fois, seul le nœud client change.
7. Durabilité, rejeu & débogage
- Reprise après crash. Les offsets de flux par agent sont persistés. Redémarrez Pulse en vol et chaque agent reprend exactement là où il s'était arrêté — aucun trou, aucun double traitement.
- Rejeu déterministe. Rejouer un agent sur les évènements exacts qu'il a vus et obtenir des décisions byte-identiques en mode mocké — l'outil des enquêtes « pourquoi a-t-il fait ça ? ».
- Récupération d'état fenêtré. L'état de fenêtre checkpointé survit à un kill et se reconstruit au redémarrage ; les agrégats long-terme ne sont pas perdus à cause d'un processus fautif.
- Trajectoire par évènement. Le chemin de chaque évènement à travers les étapes est tracé (compatible W3C) et persisté — vous pouvez rejouer temporellement un évènement à travers le pipeline après coup.
- Dead-letter queues. Les évènements en échec et les arrivées vraiment tardives atterrissent dans une DLQ durable au lieu de disparaître.
La boucle de débogage quotidienne
1pulse logs -f # tail the engine log
2pulse events tail --topic oncall.reason.out # watch a stage's output live
3pulse metrics agent reason # throughput / lag / errors per agent8. Secrets & configuration
1pulse secret set ALERT_WEBHOOK https://hooks.example.com/… # stored locally, 0600$${secret:NAME}se résout depuis le store de secrets local du CLI au moment du deploy.$${env:VAR}se résout depuis l'environnement.- Non résolu = deploy en échec. Une référence non résoluble avorte le deploy avec une erreur nommée — une config trouée n'atteint jamais la production.
9. Référence rapide CLI
| Commande | Rôle |
|---|---|
| pulse server start --dev | Démarrer un Pulse local et auto-login du CLI |
| pulse new <app> --source … --stage … --sink … | Scaffold pulse.yaml + sample.json + README |
| pulse new --list-sources / --list-sinks / --list-operators / --list-templates | Explorer la palette |
| pulse deploy . | Déployer l'app : source, étapes, sink, API + SDK |
| pulse events send --topic <t> --data @f.json | Publier un évènement de test |
| pulse events tail --topic <t> | Tail live d'un topic |
| pulse logs -f | Tail du log moteur |
| pulse metrics agent <name> | Débit, lag, erreurs par agent |
| pulse secret set <NAME> <value> | Stocker un secret pour ${secret:NAME} |
Maintenant, construisez-en un.
Le moyen le plus rapide d'intégrer le modèle est de regarder un agent décider sur des évènements live — ça prend environ trois minutes.