What this solves
A weekly digest email has three placements: hero, body card, footer. If contact-policy fatigue or decisioning gates empty the hero, you don’t want to send a footer-only email — that’s worse than not sending. Atomic coupling lets you say “this channel is all-or-nothing within itself” without forcing every flow on that channel to be atomic.Why this works
Coupling is per-channel, not global. EachChannel.couplingMode defaults to "partial" (any non-empty placement ships). Switching it to "atomic" makes the post-group coupling pass scan that channel’s placement results; if any one is empty, the rest are emptied with a cascade record in trace.channelCoupling[].
Cross-channel coupling is intentionally not supported — different channels are different attention surfaces, and an empty SMS shouldn’t suppress an email.
Three knobs
Step 1 — Mark the email channel atomic
id goes in the body — PUT /api/v1/channels updates by id, there is no /channels/{id} sub-route.
Step 2 — Fire a multi-placement recommend
What you’ll see when coupling fires
Response body:<email-body-card> would have had offers — because the hero was empty and the channel is atomic. The cascaded: true flag in channelCoupling[] is your audit trail: this wasn’t “no offers were available,” this was “we deliberately suppressed.”
Why not just use Group.allowPartial?
Group.allowPartial was the old switch. It’s deprecated and no-op now (the field still parses to keep legacy IRs valid). It conflated two distinct cases:
- “Operator chose to require all placements filled” (now:
Channel.couplingMode = "atomic") - “Contact policy fatigue happened to empty everything” (now: surfaces in the trace’s
contactPolicyResults[]regardless)
allowPartial could only do flow-wide all-or-nothing.
Per-flow override
A weekly-digest flow needs atomic; a same-channel transactional alert flow needs partial. Set the channel default to atomic, then override on the transactional flow:Proof reference
T8 of the proof bundle:channelCoupling.cascaded = true with both placements empty, when the hero is fatigued out by a frequency cap.