Skip to content

Output Messages

mchristegh edited this page Jul 15, 2026 · 1 revision

This page owns the four-output routing rules and the message envelope. For the full list of event types and which outputs each uses, see Events.

The four outputs

# Label Carries
1 Trigger Only a genuine untriggeredtriggered transition. Nothing else, ever.
2 Release Only a genuine triggereduntriggered transition (threshold re-crossed, or quorum lost under the Release policy). Nothing else, ever.
3 Query Only query snapshots — requested by a query message, or produced by a Heartbeat tick. Query events appear on no other output.
4 Events Everything else, plus a duplicate copy of every Trigger and Release event. The only output where msg.ignored can be true.

The guarantee to build automations on: outputs 1 and 2 never carry a blocked, suppressed, or ignored message. Anything that didn't truly happen appears only on output 4, tagged.

The envelope

Every output message is a clone of the message that triggered it, with these properties layered on top:

Property Meaning
msg.consensusEvent The event type — see Events
msg.consensusState waiting, untriggered, or triggered — see States
msg.aggregate Current aggregate value (fraction-true in Boolean mode); null while no data
msg.aggregation The function actually used: mean, median, min, max, trimmedmean, mean(fallback), or fraction
msg.quorum Whether quorum is currently satisfied (true when quorum is disabled)
msg.freshCount Number of fresh sources
msg.sourceCount Number of known sources (learned + expected)
msg.sources Per-source breakdown: { topic: { value, lastSeen, stale, seen } } (lastSeen ISO 8601 or null)
msg.disabled Current disabled flag
msg.ignored true if the message was received but did not change node state. Always false on outputs 1–3.
msg.source "external" — a live incoming message caused this event; "internal" — the node's own clock did (staleness expiry, heartbeat tick, restore)

Event-specific extras — releaseReason, rejectedValue, staleTopic, recoveredTopic, addedTopic, removedTopic, minorityTopics, triggerSet, releaseSet, staleSet — appear only on their events, including rejected attempts, so downstream flows can see exactly what was refused.

Whose message gets cloned?

  • Events with a live cause (readings, commands, setstale-driven staleness flips) clone their own triggering message — your original payload and topic ride along.
  • Internally-caused events (staleness expiry, heartbeat ticks, restore-driven events) have no live message, so they clone the most recent accepted reading's message.

Envelopes reflect the instant of dispatch

Events fire in causal order, and each envelope is a snapshot of the world at the moment that event dispatches — earlier envelopes are never re-stamped with knowledge of the later events they cause. Two visible consequences, both deliberate:

  1. A quorumregained that enables the first-ever evaluation reports consensusState: "waiting" — the silent waiting → untriggered bookkeeping happens after it.
  2. A sourcestale whose expiry costs the quorum still shows quorum: true — the quorumlost that follows immediately is the correction.

Chattiness control

With Emit aggregate on change only checked (the default), an accepted reading event is emitted on output 4 only when it changed the aggregate. sourceadded and sourcerecovered always emit, and rejected readings always emit — they are diagnostics, and suppressing them would reintroduce silent drops.

Clone this wiki locally