Patrons d'intégration
Scénarios concrets de bout en bout que les développeurs construisent réellement, quels endpoints utiliser, dans quel ordre, avec assez de code pour copier-coller.
Retour au hub développeursPatron 1, Pont d'événements de votre SaaS vers Pulse
Votre SaaS émet des webhooks (facturation, e-commerce, planification, interne). Pulse génère une URL publique + un secret HMAC par source ; chaque charge utile vérifiée publie vers un topic qui réveille votre pipeline.
1import requests, hmac, hashlib, json, time
2
3PULSE_URL = "https://pulse.yourdomain.com"
4SECRET = "your-webhook-secret"
5
6def publish_to_pulse(source_id, key, payload_dict):
7 body = json.dumps(payload_dict).encode()
8 signature = hmac.new(SECRET.encode(), body, hashlib.sha256).hexdigest()
9 timestamp = str(int(time.time()))
10 r = requests.post(
11 f"{PULSE_URL}/api/webhooks/{source_id}",
12 headers={
13 "Content-Type": "application/json",
14 "X-Pulse-Signature": signature,
15 "X-Pulse-Timestamp": timestamp,
16 "X-Pulse-Event-Key": key,
17 },
18 data=body,
19 timeout=10,
20 )
21 r.raise_for_status()
22
23publish_to_pulse("billing-ingress", "evt-abc", {"amount": 9900, "customer": "cus_123"})Pulse vérifie le HMAC avant de publier l'événement, rejetant les contrefaçons.
Patron 2, GitOps pour les déploiements d'agents
Les définitions de pipeline vivent dans Git. Les fusions de PR s'appliquent à la pré-production ; un flux de promotion s'applique à la production. Même script d'application par environnement.
1# .github/workflows/pulse-sync.yaml
2on:
3 push:
4 branches: [main]
5 paths: ['infra/pulse-staging/**']
6
7jobs:
8 sync-staging:
9 runs-on: ubuntu-latest
10 steps:
11 - uses: actions/checkout@v4
12 - name: Apply
13 env:
14 PULSE_URL: ${{ vars.PULSE_STAGING_URL }}
15 PULSE_USER: ${{ secrets.PULSE_STAGING_USER }}
16 PULSE_PASS: ${{ secrets.PULSE_STAGING_PASS }}
17 run: |
18 LOGIN=$(curl -sf -X POST "$PULSE_URL/api/auth/login" \
19 -H "Content-Type: application/json" \
20 -d "{\"username\":\"$PULSE_USER\",\"password\":\"$PULSE_PASS\"}")
21 export PULSE_TOKEN=$(echo $LOGIN | jq -r '.accessToken')
22 export CSRF=$(echo $LOGIN | jq -r '.csrfToken')
23 cd infra/pulse-staging
24 ../../scripts/apply-agents.sh
25 ../../scripts/apply-pipelines.shPatron 3, ETL temps réel vers votre entrepôt de données
Reflétez chaque décision Pulse dans votre entrepôt pour la BI. Abonnez-vous via WebSocket ; insérez à mesure que les événements arrivent. Utilisez le polling REST sur /api/pulse/events?since=<cursor> comme complément de rattrapage pour la sémantique au-moins-une-fois.
1# etl.py, long-running service, subscribes and inserts
2import asyncio, websockets, json, psycopg2, os
3
4PULSE_WS = os.environ["PULSE_WS_URL"] # ws://pulse:9091/ws
5TOKEN = os.environ["PULSE_TOKEN"]
6DB_URL = os.environ["DATABASE_URL"]
7
8async def run():
9 conn = psycopg2.connect(DB_URL)
10 cur = conn.cursor()
11 async with websockets.connect(PULSE_WS) as ws:
12 await ws.send(json.dumps({"type": "auth", "token": TOKEN}))
13 async for raw in ws:
14 msg = json.loads(raw)
15 if msg["type"] == "events":
16 data = msg["data"]
17 cur.execute(
18 "INSERT INTO pulse_events (id, topic, ts, payload) VALUES (%s, %s, %s, %s::jsonb)",
19 (data["id"], data["topic"], data["timestamp"], json.dumps(data["payload"])),
20 )
21 conn.commit()
22
23asyncio.run(run())Patron 4, Utiliser un agent Pulse comme outil externe
Vous avez construit un pipeline Pulse utile. Vous voulez qu'un assistant bureau ou un autre hôte d'agent l'appelle.
Chemin le plus rapide, endpoint natif (sans pont)
Pulse expose un endpoint d'appel d'outils conforme à POST /tools. Pointez votre hôte directement dessus et chaque outil Pulse apparaît.
1{
2 "toolServers": {
3 "pulse": {
4 "type": "http",
5 "url": "http://localhost:9090/tools",
6 "headers": {
7 "Authorization": "Bearer <your-pulse-access-token>"
8 }
9 }
10 }
11}Alternative, pont stdio (un outil nommé unique)
Utile quand votre hôte ne parle que stdio, ou quand vous voulez exposer un pipeline spécifique comme un seul outil nommé avec une sémantique synthétisée.
1# ~/.pulse-bridge/bridge.py
2import asyncio, os, requests, json, uuid, time
3from tool_server import Server
4import tool_server.stdio
5
6PULSE_URL = os.environ["PULSE_URL"]
7PULSE_TOKEN = os.environ["PULSE_TOKEN"]
8
9srv = Server("pulse-bridge")
10
11@srv.tool()
12async def summarize_inbox(since_iso: str) -> str:
13 """Use the Pulse email-summariser agent to summarise recent emails."""
14 key = f"host-{uuid.uuid4()}"
15 publish = requests.post(f"{PULSE_URL}/api/pulse/events",
16 headers={"Authorization": f"Bearer {PULSE_TOKEN}"},
17 json={"topic": "inbox.summarise.request",
18 "key": key,
19 "value": json.dumps({"since": since_iso})}).json()
20 started = publish["timestamp"]
21 for _ in range(45):
22 time.sleep(1)
23 r = requests.get(f"{PULSE_URL}/api/pulse/events",
24 headers={"Authorization": f"Bearer {PULSE_TOKEN}"},
25 params={"topic": "inbox.summarise.result", "since": started}).json()
26 for e in r.get("events", []):
27 if e.get("key") == key:
28 return e["value"]
29 raise RuntimeError("Timeout")
30
31if __name__ == "__main__":
32 asyncio.run(tool_server.stdio.stdio_server(srv))Patron 5, Création d'agents programmatique depuis votre assistant
Vous construisez un produit au-dessus de Pulse. Les utilisateurs configurent leur workflow dans VOTRE UI ; vous provisionnez les agents Pulse correspondants en coulisses, créer, planifier, démarrer, mettre à jour, supprimer.
1// backend.ts, your product's API
2import { PulseClient } from './pulse-client';
3
4export async function provisionUserWorkflow(userConfig: UserWorkflow) {
5 const pulse = new PulseClient(process.env.PULSE_URL!);
6 await pulse.login(process.env.PULSE_BOT_USER!, process.env.PULSE_BOT_PASS!);
7
8 const agent = await pulse.call('POST', '/api/pulse/agents', {
9 name: `user-${userConfig.userId}-workflow`,
10 engine: 'llm',
11 inputTopic: `user-${userConfig.userId}.inbound`,
12 outputTopic: `user-${userConfig.userId}.outbound`,
13 config: {
14 systemPrompt: buildPrompt(userConfig),
15 externalTools: userConfig.enabledTools,
16 },
17 });
18
19 await pulse.call('POST', '/api/pulse/schedules', {
20 pipelineOrAgentId: agent.id,
21 cron: userConfig.cron,
22 timezone: userConfig.timezone,
23 });
24
25 await pulse.call('POST', `/api/pulse/agents/${agent.id}/start`);
26 return { agentId: agent.id };
27}Patron 6, Supervision Pulse depuis Grafana
Pulse expose des métriques Prometheus sur /metrics. Récupérez-les, construisez des tableaux de bord, alertez sur la dérive et les sauvegardes anciennes.
1# prometheus.yaml
2scrape_configs:
3 - job_name: 'pulse'
4 scrape_interval: 30s
5 static_configs:
6 - targets: ['pulse.internal:9090']
7 metrics_path: /metricspulse_agents_runningAgents actifs au fil du temps.
pulse_agents_driftedLe watchdog n'a pas pu auto-récupérer.
pulse_events_totalCompteur cumulé d'événements par topic.
pulse_backup_age_secondsHeures depuis la dernière sauvegarde ; alerte > 48 h.
Règles Alertmanager
1groups:
2 - name: pulse
3 rules:
4 - alert: PulseAgentsDrifted
5 expr: pulse_agents_drifted > 0
6 for: 10m
7 annotations:
8 summary: "Pulse has {{ $value }} drifted agents, watchdog didn't auto-recover"
9 - alert: PulseBackupStale
10 expr: pulse_backup_age_seconds > 48 * 3600
11 for: 1hPatron 7, Import en masse d'événements historiques
Migration depuis un autre système ? Rejouez l'historique dans Pulse. Posez un en-tête backfill: true pour que les agents puissent filtrer, évite les effets de bord réels (emails, notifications) pendant l'import.
1import requests, json
2
3PULSE = "http://localhost:9090"
4TOKEN = "..."
5
6with open('historical-events.jsonl') as f:
7 for line in f:
8 ev = json.loads(line)
9 requests.post(f"{PULSE}/api/pulse/events",
10 headers={"Authorization": f"Bearer {TOKEN}"},
11 json={
12 "topic": ev["topic"],
13 "key": ev["key"],
14 "value": json.dumps(ev["payload"]),
15 "headers": {
16 "backfill": "true",
17 "originalTimestamp": ev["timestamp"],
18 },
19 })Limite : ~300 événements/s sur une installation mono-nœud. Pour les imports plus volumineux, publiez par lots avec backoff.
Patron 8, Variantes de pipeline avec feature flags
Testez un nouveau prompt sur 10 % du trafic. Routez de façon déterministe avec un agent rule-based, puis comparez les sorties entre live et candidat.
1# agents/email-triager-router.yaml, routes 10% to candidate, 90% to live
2name: email-triager-router
3engine: rule-based
4inputTopic: email.ingress
5outputTopic: email.ingress.10pct
6config:
7 rules:
8 - condition: "hash(messageId) % 10 == 0"
9 action: emit
10 target: email.ingress.10pct
11 - condition: always
12 action: emit
13 target: email.ingress.90pctOu utilisez la fonctionnalité native de shadow-deploy de Pulse, qui fait cela sans routage rule-based.
Patron 9, Pulse multi-tenant (scénario MSP)
Option 1, Une installation par client
Le plus simple. Chaque client a son propre répertoire de données, domaine et licence. Lancez N processus derrière un reverse proxy ; routez par sous-domaine. Fonctionne d'emblée.
Option 2, Une installation, multi-org
Fonctionnalité Enterprise. Plusieurs organisations partagent un même binaire Pulse ; isolation des données et utilisateurs par org. Nécessite une licence Enterprise.
Patron 10, Intégrer Pulse dans votre produit
Rebrand de l'UI, exposez votre propre API aux utilisateurs finaux, conservez les identifiants admin Pulse dans votre backend. Les utilisateurs finaux s'authentifient contre VOTRE auth, pas celle de Pulse.
La redistribution commerciale nécessite un accord Enterprise, contactez-nous avant la mise en production.
Besoin d'aide pour un patron personnalisé ?
Notre équipe peut revoir votre architecture et recommander la forme d'intégration la plus propre.