Skip to main content

Compose two agents by topics

Intermediate ⏱ 15 min multi-agent · composition · topics

You will build: two independent apps chained into a system — a detector that flags suspicious orders, and a responder that reasons over what the detector flags. No shared code, no framework: one topic.

detector: orders → rules → detector.screen.out ══► responder: (reads it) → llm → responder.reason.out

Prerequisites​

1 · Build the detector — app number one​

pulse new detector --source webhook --stage rule-based:screen
stages:
- name: screen
engine: rule-based
rules:
- { condition: "amount >= 1000", action: flag }
cd detector && pulse secret set PULSE_WEBHOOK_SECRET dev-secret # the scaffolded webhook source requires it
pulse deploy . && cd ..

Its output lives on detector.screen.out — a durable topic, like every stage boundary.

2 · Build the responder — app number two, subscribed to app number one​

pulse new responder --stage llm:reason
stages:
- name: reason
engine: llm
inputTopics: [ detector.screen.out ] # ← the composition, in one line
systemPrompt: |
You receive a flagged order. Assess the risk briefly
and recommend: approve, review, or reject.
cd responder && pulse deploy . && cd ..

3 · Feed the detector, watch the responder​

pulse events publish --topic detector.in --value '{"orderId":"o-9","amount":4200}'
pulse events tail --topic responder.reason.out

The event flows through two separately deployed apps: detector flags it → the flag lands on detector.screen.out → the responder picks it up and reasons → the recommendation appears on the responder's own output.

4 · Scale the pattern​

  • Chain more agents the same way — each new app points inputTopics at any existing topic.
  • Fan out — deploy a second responder reading the same detector.screen.out; both see every flag.
  • Correlate — a stream-stream join matches events across two agents' outputs.

What just happened​

"Multi-agent" here is not a framework feature — it's an addressing scheme. Every stage boundary is a durable, subscribable topic, so systems compose the way Unix pipes compose: independently deployed, independently observable (pulse events tail works at every seam), independently replaceable.

Troubleshooting​

The responder never receives anything

Both apps must be deployed on the same Pulse. Confirm the detector actually emits: pulse events tail --topic detector.screen.out. If that's live but the responder is silent, check the inputTopics spelling.

Next​