Anatomy of pulse.yaml
You will build: a guided read-through of the one file that defines an app — you'll edit each block and see what changes.
Prerequisites
- The
helloapp from Your first pipeline (or scaffold any app).
1 · Open pulse.yaml and find the three blocks
cat pulse.yaml
source: OBSERVE — where events come from
stages: DECIDE — an ordered chain, one engine per stage
sink: ACT — optional; where results go
Every Pulse app is these three blocks. There is no hidden config anywhere else.
2 · The source block
source:
kind: webhook # or: file-tail · http-poll · jdbc-source · …
One connector kind + its settings. Its events always land on <app>.in. Swap kind and nothing downstream changes — stages don't know where events came from.
3 · The stages block
stages:
- name: triage
engine: rule-based
rules:
- { condition: "severity == 'error'", action: flag }
Each rule is a condition plus an action (flag, block, hold, review, or emit:<topic> to route). Each stage names one of the four engines: streaming, rule-based, llm, mcp. Stage n reads stage n−1's topic and publishes to <app>.<stage>.out — which is why you could tail hello.triage.out directly.
4 · Change the rule and redeploy
pulse deploy .
Deploys are idempotent — edit, redeploy, repeat. Send sample.json again and watch how the new rule treats it.
5 · Add a sink (optional block)
sink:
kind: webhook
url: ${secret:MY_WEBHOOK}
Sinks push results out — webhooks, Slack, JDBC, files… Note the ${secret:…} reference: secrets never live inline. That's the subject of Secrets done right.
What just happened
The whole developer surface is one declarative file. Deploy reads it and stands up the runtime; nothing you clicked or exported lives outside it — which is why apps are reviewable in a PR and reproducible on any machine.
Troubleshooting
Deploy fails after my edit
The error names the exact field. The most common one: an unresolved ${secret:…} — deploy refuses to ship a config with a hole in it. Set the secret or remove the reference.